• SpringAOP底层原理


    目录

    两种实现方式

    JDK动态代理

    编写接口

    接口的实现类

    创建代理对象

    测试

    CGLIB动态代理

    需要增强的方法

    创建代理对象

    测试

     关于两种代理需要知道的点


    两种实现方式

    SpringAOP底层根据接口的使用情况,有两种的实现方式

    1. 有接口的时候:使用jdk动态代理
    2. 没有接口的情况:使用cglib动态代理

    JDK动态代理

    编写接口

    1. package com.heaboy.aopdemo.jdkproxy;
    2. public interface TargetInteface {
    3. void method1();
    4. void method2();
    5. int method3(Integer i);
    6. }

    接口的实现类

    1. package com.heaboy.aopdemo.jdkproxy;
    2. public class Target implements TargetInteface {
    3. @Override
    4. public void method1() {
    5. System.out.println("method1 running ...");
    6. }
    7. @Override
    8. public void method2() {
    9. System.out.println("method2 running ...");
    10. }
    11. @Override
    12. public int method3(Integer i) {
    13. System.out.println("method3 running ...");
    14. return i;
    15. }
    16. }

    创建代理对象

    对于代码的解析已写在注释中方便理解,这里在invoke调用前后都添加通知 => 环绕通知

    1. package com.heaboy.aopdemo.jdkproxy;
    2. import java.lang.reflect.InvocationHandler;
    3. import java.lang.reflect.Method;
    4. import java.lang.reflect.Proxy;
    5. public class TargetProxy {
    6. public static Object getTarget(T t) {
    7. //Proxy.newProxyInstance中的三个参数,分别对应下面的三个传入数据
    8. //ClassLoader loader:用来知名生成代理对象所使用的类加载器
    9. //Class interfaces 用来知名目标类实现的所有接口
    10. //InvocationHandler h 里面的方法就是这个代理对象要做的事情
    11. return Proxy.newProxyInstance(t.getClass().getClassLoader(), t.getClass().getInterfaces(), new InvocationHandler() {
    12. //实现InvocationHandler接口后,需要重写invoke方法,invoke方法用于调用被代理对象的方法
    13. @Override
    14. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    15. // proxy就是目标对象t,method就是调用目标对象中方法,args就是调用目标对象中方法的参数。
    16. //比如说:代理对象.method1(),这时proxy就是目标类,method1就是method,args就是method1方法参数。
    17. System.out.println("执行方法前...");
    18. Object invoke = method.invoke(t, args);
    19. System.out.println("执行方法后...");
    20. return invoke;
    21. }
    22. });
    23. }
    24. }

    测试

    1. package com.heaboy.aopdemo.jdkproxy;
    2. public class TargetUser {
    3. public static void main(String[] args) {
    4. TargetInteface target = (TargetInteface) TargetProxy.getTarget(new Target());
    5. target.method1();
    6. System.out.println("-----------------------------");
    7. target.method2();
    8. System.out.println("-----------------------------");
    9. System.out.println(target.method3(3));
    10. }
    11. }

     

    CGLIB动态代理

    需要增强的方法

    1. package com.heaboy.aopdemo.cglibproxy;
    2. public class Target {
    3. public void method1() {
    4. System.out.println("method1 running ...");
    5. }
    6. public void method2() {
    7. System.out.println("method2 running ...");
    8. }
    9. public int method3(Integer i) {
    10. System.out.println("method3 running ...");
    11. return i;
    12. }
    13. }

    创建代理对象

    1. package com.heaboy.aopdemo.cglibproxy;
    2. import net.sf.cglib.proxy.Enhancer;
    3. import net.sf.cglib.proxy.MethodInterceptor;
    4. import net.sf.cglib.proxy.MethodProxy;
    5. import java.lang.reflect.Method;
    6. public class TargetProxy {
    7. public static Object getProxy(T t) {
    8. Enhancer en = new Enhancer(); //使用Enchancer为无接口类创建代理对象
    9. en.setSuperclass(t.getClass());//设置要代理的目标类
    10. en.setCallback(new MethodInterceptor() {//代理类需要完成的工作
    11. //重写intercept方法
    12. @Override
    13. public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    14. System.out.println("执行方法前。。。");
    15. //调用原有方法
    16. Object invoke = methodProxy.invokeSuper(object, args);
    17. // Object invoke = method.invoke(t, args);// 作用等同与上面。
    18. System.out.println("执行方法后。。。");
    19. return invoke;
    20. }
    21. });
    22. //返回创建好的代理类对象
    23. return en.create();
    24. }
    25. }

    测试

    1. package com.heaboy.aopdemo.cglibproxy;
    2. import java.util.ArrayList;
    3. import java.util.List;
    4. public class TargetUser {
    5. public static void main(String[] args) {
    6. //创建代理类
    7. Target target = (Target) TargetProxy.getProxy(new Target());
    8. //打印生成的代理类全限定类名
    9. System.out.println(target.getClass().getName());
    10. //调用代理类方法
    11. target.method1();
    12. }
    13. }


     关于两种代理需要知道的点

    • SpringAOP生成动态代理对象
      • 实现了接口:JDK动态代理
      • 无接口类:CGLIB动态代理
    • SpringAOP生成动态代理对象不需要特殊编译器
    • SpringAOP可以根据目标对象是否实现接口,自动选择代理模式
    • 优先对接口创建代理,方便程序的解耦与维护
    • 被final标记的方法 -> 方法不能重写 -> 无法被代理
  • 相关阅读:
    angular升级后用Cesium等编译出现Can‘t resolve (fs, http, https, url, path, stream, zlib)等问题
    雪花算法生成分布式主键ID
    YOLOV5算法二之数据集转换及自动划分训练集与测试集
    Windows搭建MQTT服务器
    shell语法(一)
    微信小程序中使用Behavior混入
    FAQ是什么?该如何编辑FAQ?
    IntelliJ IDEA 安装及创建Java项目
    机器学习入门五(随机森林模型数据分类及回归)
    法制博览杂志法制博览杂志社法制博览编辑部2022年第24期目录
  • 原文地址:https://blog.csdn.net/qq_57031340/article/details/126753007