Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何拦截构造函数_Java_Bytecode_Byte Buddy - Fatal编程技术网

Java 如何拦截构造函数

Java 如何拦截构造函数,java,bytecode,byte-buddy,Java,Bytecode,Byte Buddy,我想截取所有用@Inject注释的方法。下面的测试表明,它可以很好地处理方法,但不能处理构造函数。我错过了什么 我试图添加一个定制的方法匹配器,但我注意到从来没有给我一个与构造函数对应的MethodDescription public class InterceptConstructorTest { @Test public void testConstructorInterception() { ByteBuddyAgent.install();

我想截取所有用@Inject注释的方法。下面的测试表明,它可以很好地处理方法,但不能处理构造函数。我错过了什么

我试图添加一个定制的方法匹配器,但我注意到从来没有给我一个与构造函数对应的MethodDescription

public class InterceptConstructorTest {

    @Test
    public void testConstructorInterception() {

        ByteBuddyAgent.install();

        new AgentBuilder.Default().type(nameStartsWith("test")).transform(new AgentBuilder.Transformer() {

            @Override
            public Builder<?> transform(Builder<?> builder, TypeDescription td) {

                return builder.method(isAnnotatedWith(Inject.class))
                        .intercept(MethodDelegation.to(MethodInterceptor.class).andThen(SuperMethodCall.INSTANCE));
            }
        }).installOnByteBuddyAgent();

        // Call constructor => NOT intercepted 
        MyClass myClass = new MyClass("a param");

        // Call method => intercepted
        myClass.aMethod("a param");
    }
}

class MyClass {

    @Inject
    public MyClass(String aParam) {
        System.out.println("constructor called");
    }

    @Inject
    public void aMethod(String aParam) {
        System.out.println("aMethod called");
    }
}

class MethodInterceptor {

    public static void intercept(@Origin Method method) {
        System.out.println("Intercepted: " + method.getName());
    }
}

您明确指定只希望拦截方法:

builder.method(isAnnotatedWith(Inject.class))
您也可以这样做:

builder.constructor(isAnnotatedWith(Inject.class))
甚至:

builder.invokeable(isAnnotatedWith(Inject.class))
然而,这里有一个陷阱。任何构造函数都必须从被拦截的构造函数中调用另一个构造函数。在您的情况下,这已经通过使用
SuperMethodCall.INSTANCE
给出,您的代码将运行。但是,请注意某些构造对构造函数不可用,例如,在调用超级构造函数之前,不能插入
@This
引用。如果合适,您可以切换以下选项:

MethodDelegation.to(MethodInterceptor.class)
                .andThen(SuperMethodCall.INSTANCE)
成为

SuperMethodCall.INSTANCE
               .andThen(MethodDelegation.to(MethodInterceptor.class))
当使用这种排序时,JVM不再抱怨是否插入了被拦截实例的属性

最后,确保提供适当的拦截:

class MethodInterceptor {

    public static void intercept(@Origin Method method) {
        System.out.println("Intercepted: " + method.getName());
    }

    public static void intercept(@Origin Constructor<?> constructor) {
        System.out.println("Intercepted: " + constructor.getName());
    }
}
类方法拦截器{
公共静态无效截距(@Origin方法){
System.out.println(“截获:“+method.getName());
}
公共静态无效截获(@Origin构造函数){
System.out.println(“截获:“+constructor.getName());
}
}

否则,Byte Buddy无法将
构造函数
引用绑定到
方法
并放弃绑定该方法(从0.7.6开始,以前存在一个导致验证器错误的错误)。在使用Java 8时,还可以使用
可执行文件
类型提供一个拦截器。

我用“构造函数”尝试了这两种方法和“invokable”,我得到了以下异常(版本0.7.5):您正在使用@Origin和一个应该使用构造函数的方法类型。Buddy应该会注意到,这是一个bug。您需要使用构造函数作为拦截器的类型。哦,对了,谢谢!现在我更好地理解了异常消息。我不知道反射API区分了构造函数和方法。在构建器上使用方法/构造函数/可调用也更有意义。我将修复它,明天早上推出新版本。
class MethodInterceptor {

    public static void intercept(@Origin Method method) {
        System.out.println("Intercepted: " + method.getName());
    }

    public static void intercept(@Origin Constructor<?> constructor) {
        System.out.println("Intercepted: " + constructor.getName());
    }
}