目录

chen 的个人博客

VX:ZzzChChen
Phone:13403656751
Email:zxydczzs@gmail.com

X

Spring AOP的实现原理以及应用场景。

AOP 应用场景

  1. 记录日志;
  2. 监控方法运行时间(监控性能);
  3. 权限控制;
  4. 缓存优化(第一次调用查询数据库,将查询结果放入内存对象,第二次调用则直接从内存对象返回,不需要查询数据库);
  5. 事务管理(调用方法前开启事务,调用方法后提交关闭事务);

AOP 实现原理

Spring 中 AOP 的两种实现方式:
  1. JDK 动态代理;
  2. Cglib 动态代理;

JDK 动态代理

  1. 引入依赖,有 Spring、单元测试和日志管理;

     1<dependencies>
     2        <!-- Spring -->
     3        <dependency>
     4            <groupId>org.springframework</groupId>
     5            <artifactId>spring-context</artifactId>
     6        </dependency>
     7
     8        <!-- 单元测试 -->
     9        <dependency>
    10            <groupId>junit</groupId>
    11            <artifactId>junit</artifactId>
    12            <scope>test</scope>
    13        </dependency>
    14        <!-- 日志 -->
    15        <dependency>
    16            <groupId>org.slf4j</groupId>
    17            <artifactId>slf4j-log4j12</artifactId>
    18        </dependency>
    19</dependencies>
    
  2. UserDao 接口

    1public interface UserDao {
    2    public void saveUser();
    3}
    4
    
  3. UserDao 实现类

    1public class UserDaoImpl implements UserDao {
    2
    3    @Override
    4    public void saveUser() {
    5        System.out.println("持久层:用户保存");
    6    }
    7}
    
  4. 动态代理

     1@Test
     2    public void test1() {
     3
     4        final UserDao userDao = new UserDaoImpl();
     5        // newProxyInstance的三个参数解释:
     6        // 参数1:代理类的类加载器,同目标类的类加载器
     7        // 参数2:代理类要实现的接口列表,同目标类实现的接口列表
     8        // 参数3:回调,是一个InvocationHandler接口的实现对象,当调用代理对象的方法时,执行的是回调中的invoke方法
     9        //proxy为代理对象
    10        UserDao proxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(),
    11                userDao.getClass().getInterfaces(), new InvocationHandler() {
    12
    13                    @Override
    14                    // 参数proxy:被代理的对象
    15                    // 参数method:执行的方法,代理对象执行哪个方法,method就是哪个方法
    16                    // 参数args:执行方法的参数
    17                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    18                        System.out.println("记录日志");
    19                        Object result = method.invoke(userDao, args);
    20                        return result;
    21                    }
    22                });
    23        //代理对象执行方法
    24        proxy.saveUser();
    25    }
    
  5. 结果,在没有修改原有类的代码的情况下,对原有类的

这里写图片描述

Cglib 动态代理

在实际开发中,可能需要对没有实现接口的类增强,用 JDK 动态代理的方式就没法实现。采用 Cglib 动态代理可以对没有实现接口的类产生代理,实际上是生成了目标类的子类来增强。
首先,需要导入 Cglib 所需的 jar 包。提示:spring 已经集成了 cglib,我们已经导入了 spring 包,所以不需要再导入其它包了。
  1. 创建 LinkManDao 类,没有实现任何接口

    1public class LinkManDao {
    2    public void save(){
    3        System.out.println("持久层:联系人保存....");
    4    }
    5}
    
  2. 动态代理

     1@Test
     2    public void test2() {
     3        final LinkManDao linkManDao = new LinkManDao();
     4        // 创建cglib核心对象
     5        Enhancer enhancer = new Enhancer();
     6        // 设置父类
     7        enhancer.setSuperclass(linkManDao.getClass());
     8        // 设置回调
     9        enhancer.setCallback(new MethodInterceptor() {
    10            /**
    11             * 当你调用目标方法时,实质上是调用该方法
    12             * intercept四个参数:
    13             * proxy:代理对象
    14             * method:目标方法
    15             * args:目标方法的形参
    16             * methodProxy:代理方法
    17            */
    18            @Override
    19            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
    20                    throws Throwable {
    21                System.out.println("记录日志");
    22                 Object result = method.invoke(linkManDao, args);
    23                return result;
    24            }
    25        });
    26        // 创建代理对象
    27        LinkManDao proxy = (LinkManDao) enhancer.create();
    28        proxy.save();
    29    }
    
  3. 结果

这里写图片描述


标题:Spring AOP的实现原理以及应用场景。
作者:zzzzchen
地址:https://dczzs.com/articles/2021/10/29/1635508763586.html