1. SpringAOP的实现原理
public interface ToBPayment {
void pay();
}
public class AlipayToB implements ToBPayment {
ToBPayment toBPayment;
public AlipayToB(ToBPayment toBPayment) {
this.toBPayment = toBPayment;
}
@Override
public void pay() {
beforePay();
toBPayment.pay();
afterPay();
}
private void afterPay() {
System.out.println("支付");
}
private void beforePay() {
System.out.println("取款");
}
}
public class ToBPaymentImpl implements ToBPayment {
@Override
public void pay() {
System.out.println("以公司的名义进行支付");
}
}
public class ProxyDemo {
public static void main(String[] args) {
ToBPayment toBProxy = new AlipayToB(new ToBPaymentImpl());
toBProxy.pay();
}
}
2. JDK动态代理
- 寻求改进
- 溯源ClassLoader
- 通过带有包名的类来获取对应class文件的二进制字节流
- 根据读取的字节流,将代表的静态存储结构转化为运行时数据结构
- 生成一个代表该类的Class对象,作为方法区该类的数据访问入口
- 改进的切入点
- 根据一定规则去改动或者生成新的字节流,将切面逻辑织入其中
- 行之有效的方案就是取代被代理类的动态代理机制
- 根据接口或者目标类,计算出代理类的字节码并加载到JVM中去
- JDK动态代理
- 程序运行时动态生成类的字节码,并加载到JVM中
- 要求【被代理的类】必须实现接口
- 并不要求【代理对象】去实现接口,所以可以复用代理对象的逻辑
public interface ToBPayment {
void pay();
}
public class ToBPaymentImpl implements ToBPayment {
@Override
public void pay() {
System.out.println("以公司的名义进行支付");
}
}
public class AlipayInvocationHandler implements InvocationHandler {
private Object targetObject;
public AlipayInvocationHandler(Object targetObject) {
this.targetObject = targetObject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
beforePay();
Object result = method.invoke(targetObject, args);
afterPay();
return result;
}
private void afterPay() {
System.out.println("支付");
}
private void beforePay() {
System.out.println("取款");
}
}
public class JdkDynamicProxyUtil {
public static <T> T newProxyInstance(T targetObject, InvocationHandler handler) {
ClassLoader classLoader = targetObject.getClass().getClassLoader();
Class<?>[] interfaces = targetObject.getClass().getInterfaces();
return (T) Proxy.newProxyInstance(classLoader, interfaces, handler);
}
}
public class ProxyDemo {
public static void main(String[] args) {
ToBPayment toBPayment = new ToBPaymentImpl();
InvocationHandler handlerToB = new AlipayInvocationHandler(toBPayment);
ToBPayment toBProxy = JdkDynamicProxyUtil.newProxyInstance(toBPayment, handlerToB);
toBProxy.pay();
}
}
3. CGLIB动态代理
- 代码生成库:Code Generation Library
- 不要求被代理类实现接口
- 内部主要封装了ASM Java字节码操控框架
- 动态生成子类以覆盖非final的方法,绑定钩子回调自定义拦截器
public class CommonPayment {
public void pay() {
System.out.println("个人名义或者公司名义都可以走这个支付通道");
}
}
public class AlipayMethodInterceptor implements MethodInterceptor {
@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);
}
}
public class ProxyDemo {
public static void main(String[] args) {
CommonPayment commonPayment = new CommonPayment();
MethodInterceptor methodInterceptor = new AlipayMethodInterceptor();
CommonPayment commonPaymentProxy = CglibUtil.createProxy(commonPayment, methodInterceptor);
commonPaymentProxy.pay();
}
}
4. JDK动态代理和CGLIB实现机制
- JDK动态代理:基于反射机制实现,要求业务类必须实现接口
- JDK原生,在JVM里运行较为可靠
- 平滑支持JDK版本升级
- CGLIB:基于ASM机制实现,生成业务类的子类作为代理类
5. SpringAOP的底层机制
- CGLIB和JDK动态代理共存
- 默认策略:Bean实现了接口则用JDK,否则使用CGLIB