如何拦截抽象方法

时间:2017-03-30 21:23:37

标签: java interceptor cglib

问题标题并未完全描述问题的含义,但我无法在标题限制内进行。如果你帮我把它改成更方便,我会很高兴。

我有一些类层次结构如下所述:

AbstractParent:

public abstract class AbstractParent {

    public void realParentMethod() {
        System.out.println("invoking abstractMethod from realParentMethod");
        abstractMethod();
    }

    public abstract void abstractMethod();

}

ChildImpl:

public class ChildImpl extends AbstractParent {

    public void abstractMethod() {
        System.out.println("abstractMethod implementation is running!");
    }

}

我想在此层次结构中拦截每个方法调用并添加一些功能。即使方法是相互调用的,我也希望每次都能拦截它们。

我使用带有MethodInterceptor实现的cglib Enhancer来执行此操作:

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class Main {

public static void main(String[] srgs) {
    AbstractParent parentImpl = new ChildImpl();

    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(AbstractParent.class);
    enhancer.setCallback(new LocalMethodInterceptor(parentImpl));

    AbstractParent proxyImpl = (AbstractParent) enhancer.create();
    // straight calling abstractMethod
    proxyImpl.abstractMethod();
    System.out.println("-----------------");
    // calling realParentMethod will lead to abstractMethod calling
    proxyImpl.realParentMethod();
    }

    static class LocalMethodInterceptor<T> implements MethodInterceptor {

        private T origin;

        public LocalMethodInterceptor(T origin) {
            this.origin = origin;
        }

        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            try {
                System.out.println("intercept method["+method.getName()+"] before execution!");
                return method.invoke(origin, args);
            } finally {
                System.out.println("cleanup after  method["+method.getName()+"] execution!");
            }
        }
    }
}

问题是任何方法只拦截一次: 如果我调用抽象方法 - 它将被拦截。但层次结构的计划方式使您永远不必调用它(abstractMethod)。你只需调用realParentMethod就可以为你做所有的事情,这意味着它会从它自己调用abstractMethod。

在这个例子中,如果你调用realParentMethod只会拦截realParentMethod,那么就会跳过抽象方法。

以下是此示例的一些控制台输出:

intercept method[abstractMethod] before execution!
abstractMethod implementation is running!
cleanup after  method[abstractMethod] execution!
-----------------
intercept method[realParentMethod] before execution!
invoking abstractMethod from realParentMethod
abstractMethod implementation is running!
cleanup after  method[realParentMethod] execution!

1 个答案:

答案 0 :(得分:1)

这是您委派方法的结果,您在另一个实例T origin上调用截获的方法。 Cglib创建一个代理,它覆盖任何方法来实现MethodInterceptor。因此,拦截器仅在直接调用时应用。一旦你传递给origin对象,拦截器就不再有效了。

如果要拦截任何方法调用,而不是委托,则需要使用cglib对象替换委派目标。您可以通过MethodProxy实例调用原始方法来调用原始方法。