Spring AOP的实现原理--CGLIB动态代理
CGLIB(Code Generation Library)
JDK 动态代理需要代理类实现接口--生成动态代理类的时候需要传入被代理类实现的接口。
-
CGLIB不要求被代理类实现接口
-
内部主要封装了ASM(Java字节码操控框架)CGLIB是基于ASM封装的上层应用库
-
动态生成子类以覆盖非 final的方法,绑定钩子回调自定义拦截器
CGLIB核心类或接口讲解:
Callback回调接口
package net.sf.cglib.proxy;
public interface Callback {
}
MethodInterceptor接口继承自Callback 接口具有回调功能,相当于 JDK动态代理里面的 InvocationHandler
package net.sf.cglib.proxy;
import java.lang.reflect.Method;
//用于拦截方法调用
public interface MethodInterceptor extends Callback {
//该拦截方法前三个参数和 JDK动态代理的 InvocationHandler接口中的invoke(Object proxy, Method method, //Object[] args) 相同
// /** @param proxy Object proxy:真实的代理对象(不是被代理对象)。
* @param method Method method:表示的是目标对象(被代理对象)的方法的实例
* @param args Object[] args:方法里面需要用到的参数
MethodProxy CGLIB生成代替Method的动态代理Method对象**/
Object intercept(Object var1, Method var2, Object[] var3, MethodProxy var4) throws Throwable;
}
核心类:Enhancer
package net.sf.cglib.proxy;
public class Enhancer extends AbstractClassGenerator {
//通过公共的或者静态的 create 方法就能创建出对应的动态代理实例来
public static Object create(Class type, Callback callback) {
Enhancer e = new Enhancer();
e.setSuperclass(type);
e.setCallback(callback);
return e.create();
}
public static Object create(Class superclass, Class[] interfaces, Callback callback) {
Enhancer e = new Enhancer();
e.setSuperclass(superclass);
e.setInterfaces(interfaces);
e.setCallback(callback);
return e.create();
}
CGLIB使用:
Aspect
public class AlipayMethodInterceptor implements MethodInterceptor {
/**
*
* @param o 真实的代理对象(非被代理对象)
* @param method 表示的是目标对象(被代理对象)的方法的实例
* @param args 方法里面需要用到的参数
* @param methodProxy CGLIB生成代替Method的动态代理Method对象
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
beforePay();
//执行被代理类的方法逻辑
Object result = methodProxy.invokeSuper(o,args);
afterPay();
return result;
}
private void afterPay() {
System.out.println("支付给商家");
}
private void beforePay() {
System.out.println("从招商银行取款");
}
}
public class CglibUtil {
public static <T> T createProxy(T targetObject, MethodInterceptor methodInterceptor) {
return (T) Enhancer.create(targetObject.getClass(), methodInterceptor);
}
}
CommonPayment commonPayment = new CommonPayment();
JdkDynamicProxyUtil.newProxyInstance(commonPayment, handler);
AlipayMethodInterceptor alipayMethodInterceptor = new AlipayMethodInterceptor();
CommonPayment commonPaymentProxyWithCglib = CglibUtil.createProxy(commonPayment, alipayMethodInterceptor);
commonPaymentProxyWithCglib.pay();
输出:
从招商银行取款
个人名义或者公司名义都可以走这个支付通道
支付给商家
JDK动态代理和CGLIB
实现机制:
-
JDK动态代理:基于反射机制实现,要求业务类必须实现接口
-
CGLIB:基于ASM机制实现,生成业务类的子类作为代理类
JDK动态代理的优势:
-
JDK原生,在JVM里运行较为靠谱
-
平滑支持JDK版本的升级
CGLIB的优势:
被代理对象无需实现接口,能实现代理类的无侵入。
Spring AOP 的底层机制:
CGLIB和JDK动态代理共存
默认策略,如果目标Bean实现了接口则使用JDK,否则使用CGLIB
网友评论