我在用cglib实现动态代理功能时,发现无法拦截静态方法,而是直接调用的静态方法。
追踪了一下源码,发现把静态方法过滤掉了,没做拦截。
代理模式中的真实角色和代理角色都继承或实现一个抽象类或接口,甚至普通的类也行,都是代理模式的大致意思,代理角色中传入真实角色实例后,在调用真实方法前后或做处理。
那么,既然抽象出来的那“哥们”,可以是类,比如cglib中就是利用继承,对pojo进行动态字节码生成其子类,即生成的代理角色,但是不代理static普通方法,而我自己写一个靠继承实现的代理的话,显然能实现,即重写抽象出的类的static普通方法。
想问问,为什么会这样,为什么要这样?恳请各位解答,不甚感激!
下面是做的例子,比较了static和非static方法被拦截的情况。
真实对象
public class TargetObject {
public static void businessLogic() {
System.out.println("目标对象/真实对象中的 业务逻辑处理");
}
}
具体代理控制逻辑,实现MethodInterceptor接口
public class AroundAdvice implements MethodInterceptor {
/*
* 重写方法
*
* @see net.sf.cglib.proxy.MethodInterceptor#intercept(java.lang.Object,
* java.lang.reflect.Method, java.lang.Object[],
* net.sf.cglib.proxy.MethodProxy)
*/
/**
* Parameters: obj - "this", the enhanced object
*
* method - intercepted Method args - argument array; primitive types are
* wrapped
*
* proxy - used to invoke super (non-intercepted method); may be called as
* many times as needed
*
* Returns: any value compatible with the signature of the proxied method.
* Method returning void will ignore this value.
*/
@Override
public Object intercept(Object target, Method method, Object[] arg2,
MethodProxy methodProxy) throws Throwable {
System.out.println("目标对象/真实对象 方法调用之前...");
Object result=methodProxy.invokeSuper(target,arg2);
System.out.println("目标对象/真实对象 方法调用之后...");
return result+"<--真实对象的返回值。 \"通知\"中的新加内容";
}
}
生成代理对象的工具类
public class ProxyUtil {
public static TargetObject getProxy() {
// 增强处理器:拦截的方法插入代理控制逻辑的处理器
Enhancer enhancer = new Enhancer();
// 设置要代理的目标类
enhancer.setSuperclass(TargetObject.class);
// 设置要代理的拦截器
enhancer.setCallback(new AroundAdvice());
// 生成并返回代理对象
return (TargetObject) enhancer.create();
}
}
测试类
public class Test {
public static void main(String[] args) {
TargetObject targetObject = ProxyUtil.getProxy();
targetObject.businessLogic();
}
}
TargetObject中的方法为static修饰时,打印:
目标对象/真实对象中的 业务逻辑处理
去掉static,打印:
目标对象/真实对象 方法调用之前...
目标对象/真实对象中的 业务逻辑处理
目标对象/真实对象 方法调用之后...
Static proxy uses AspectJ. I specifically tried it with AspectJ, but it cannot be achieved by simple AspectJ. However, it can be implemented using asm. It can be implemented by modifying the class bytecode during runtime, but it is very troublesome. If you have no special needs, just write it normally. I will post a piece of asm later on how to change it
Anyway, I will post the implementation of asm below
Why cglib cannot intercept static methods is because of the way Cglib is implemented: the generated proxy class inherits from the proxy class/target class. When requested, it executes its own woven enhancements and then executes the target method, so it is created using inheritance. The proxy class cannot proxy any final methods and classes, as well as static methods.