用于最终量化方法的方法拦截器

时间:2015-04-30 04:18:46

标签: java reflection

我正在尝试一些可以拦截类中方法的方法拦截器。我尝试使用cglib,bytebuddy。我不能使用普通的Java代理类,因为它是一个类。有没有办法拦截我的final方法。 这是我尝试过的。

//我的目标类,

public class Hello {
    public final  String sayHello(){
    //return lower case hello
    return "hello";
    }
}

//主要应用程序

public class InterApp {
    public static void main(String[] d) throws Exception {
        new InterApp().loadclassDD();
    }

    public void loadclassDD() throws Exception {
       //Byte-buddy
        Hello helloObject1 = new ByteBuddy()
                .subclass(Hello.class)
                .method(named("sayHello"))
                .intercept(MethodDelegation.to(LoggerInterceptor.class))
                .make()
                .load(getClass().getClassLoader(),
                        ClassLoadingStrategy.Default.WRAPPER).getLoaded()
                .newInstance();
        System.out.println(helloObject1.sayHello());
       //CGLIB
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Hello.class);
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object arg0, Method arg1, Object[] arg2,
                    MethodProxy arg3) throws Throwable {
                System.out.println("method name " + arg1.getName());
                return arg3.invokeSuper(arg0, arg2).toString().toUpperCase();
            }
        });
        Hello proxy = (Hello) enhancer.create();
        System.out.println(proxy.sayHello());
    }
}

// LoggerInterceptor - Byte-buddy实现

public class LoggerInterceptor {
public static String log(@SuperCall Callable<String> zuper)throws Exception {
    System.out.println("Method intercepted");
    return zuper.call().toUpperCase();
}
}

如果我从方法中移除最终量词,则两者都在工作(提供大写HELLO作为输出)。这是什么原因。?有没有办法实现这个目标?如果我的理解是错误的,请纠正我。

2 个答案:

答案 0 :(得分:0)

您可以引入一个由最终课程实现的界面。这样,代理方法将成为一种选择,因为代理可以委托给原始类,同时仍然保持实现的最后一个方面。

Byteman会失败,因为您正在尝试子类化并覆盖最终方法。如果你手动编码或通过一些字节码操作lib,这没关系。它只是违反了你的班级定义的合同。因此即使它起作用,它可能仍然是一个坏主意,因为原始类的作者定义了最终方面是有原因的。

答案 1 :(得分:0)

与上述答案似乎暗示/可能使用Byteman更改方法sayHello的定义相反,即使它是最终的。例如,以下Byteman规则:

RULE更改返回值 CLASS你好 方法说你好 出口 如果是真的 DO $! = $! +&#34;来自Byteman&#34; ENDRULE

将更新返回的字符串为&#34; Hello来自Byteman&#34;。