一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情。
spring的代理又可以分为JDK动态代理和CGLIB代理。之前谢过了JDK动态代理,这篇主要分析CGLIB代理,围绕CglibAopProxy展开。
CGLib的动态代理
还有一个叫CGLib的动态代理,和JDK动态代理相比较:JDK创建代理有一个限制,就是只能为接口创建代理实例,而对于没有通过接口定义业务方法的类,则可以通过CGLib创建动态代理.
代码示例
创建接口
public interface Subject {
void request();
void hello();
}
创建目标对象
public class RealSubject implements Subject {
public void request() {
System.out.println("real subject execute request..");
}
public void hello() {
System.out.println("real subject execute hello..");
}
}
创建代理对象
public class CglibProxyInterceptor implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object result = null;
try {
result = methodProxy.invokeSuper(o, objects);
} catch (Exception e) {
throw e;
}
return result;
}
过程分析
CGLIB代理主要是由CglibAopProxy完成,从其getProxy方法入手,进行分析,CGLIB是通过生成被代理的子类 完成动态代理的,通过this.advised.addInterface(additionalInterface) 添加代理类实现的接口;
创建并配置 Enhance,在为Enhancer设置拦截器链时,代码 enhancer.setCallbackFilter(new ProxyCallbackFilter(...)); ,封装了ProxyCallbackFilter,它实现了CallBackFilter接口.
在ProxyCallbackFilter中也提到使用AOP_PROXY实际上就是DynamicAdvisedInterceptor。DynamicAdvisedInterceptor实现了MethodInterceotor方法
JDK动态代理和CGLib的比较
JDK代理使用的是反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。 CGLIB代理使用字节码处理框架asm,对代理对象类的class文件加载进来,通过修改字节码生成子类。
JDK创建代理对象效率较高,执行效率较低; CGLIB创建代理对象效率较低,执行效率高。
JDK动态代理机制是委托机制,只能对实现接口的类生成代理,通过反射动态实现接口类; CGLIB则使用的继承机制,针对类实现代理,被代理类和代理类是继承关系。