SpringAOP之代理

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值