相关推荐recommended
【Spring】难理解的Aop编程 | 入门?
作者:mmseoamin日期:2024-02-20

作者:狮子也疯狂

专栏:《spring开发》

坚持做好每一步,幸运之神自然会驾凌在你的身上

【Spring】难理解的Aop编程 | 入门?,在这里插入图片描述,第1张

目录

  • 一. 🦁 前言
  • 二. 🦁 常见概念
    • 2.1 常见术语
    • 2.2 AOP入门
      • Ⅰ. 🐇 功能场景
      • Ⅱ. 🐇 实现过程
      • 2.3 通知类型
        • Ⅰ. 🐇 编写通知方法
        • Ⅱ. 🐇 编写切面
        • Ⅲ. 🐇 测试
        • 三. 🦁 切点表达式
          • 3.1 使用语法
          • 四. 🦁 总结

            一. 🦁 前言

            继上两篇文章,狮子总结了Spring中IOC的底层原理、基本使用以及注解使用。今天来细说一下Spring的另外一个重要原理——面向切面编程(Aspect Oriented Programming),即我们常说的AOP。它是实现功能统一维护的一种技术,它将业务逻辑的各个部分进行隔离,使开发人员在编写业务逻辑时可以专心于核心业务,从而提高了开发效率。

            二. 🦁 常见概念

            AOP 能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可扩展性和可维护性。

            SpringAOP是基于动态代理的,如果要代理的对象实现了某个接口,那么SpringAOP就会使用JDK动态代理去创建代理对象;而对于没有实现接口的对象,就无法使用JDK动态代理,转而使用CGlib动态代理生成一个被代理对象的子类来作为代理。

            【Spring】难理解的Aop编程 | 入门?,在这里插入图片描述,第2张

            2.1 常见术语

            名称说明
            连接点(Joinpoint)指能被拦截到的点,在Spring中只有方法能被拦截
            切点(Pointcut)指要对哪些连接点进行拦截,即被增强的方法。
            通知(Advice)指拦截后要做的事情,即切点被拦截后执行的方法
            切面(Aspect)切点+通知称为切面
            目标(Target)被代理的对象
            代理(Proxy)代理对象
            织入(Weaving)生成代理对象的过程

            2.2 AOP入门

            现在来简单了解一下AOP的使用,SpringAOP中已经集成了AspectJ框架(应该是Java生态中最为完整的AOP框架了),我们使用该框架来实现一个简易的AOP功能。

            Ⅰ. 🐇 功能场景

            持久层的每个方法结束后都可以打印一条日志

            Ⅱ. 🐇 实现过程

            1. 创建maven项目,并且引入以下依赖:
            
            
                org.springframework
                spring-context
                5.3.12
            
            
            
                org.aspectj
                aspectjweaver
                1.8.7
            
            
            
                junit
                junit
                4.12
                test
            
            
            1. 编写连接点(该处省略持久层接口)
            @Repository
            public class UserDaoImpl implements UserDao{
                public void add(){
                    System.out.println("用户新增");
                    |
                    |
               }
                public void delete(){
                    System.out.println("用户删除");
               }
                public void update(){
                    System.out.println("用户修改");
               }
            }
            
            1. 编写通知类
            public class MyAspectJAdvice {
                // 后置通知
                public void myAfterReturning() {
                    System.out.println("打印日志...");
               }
            }
            
            1. 配置切面
            
            
            
            
             
            
            
            
             
            
            
            
            
            
             
             
            
            
            1. 测试
            public class UserDaoTest {
                @Test
                public void testAdd(){
            		ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
                    UserDao userDao = (UserDao)ac.getBean("userDao");
                    userDao.add();
               }
                @Test
               public void testDelete(){
                 	ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
                 	UserDao userDao = (UserDao)ac.getBean("userDao");
                 	userDao.delete();
               }
                @Test
                public void testUpdate(){
                 	ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
                    UserDao userDao = (UserDao)ac.getBean("userDao");
                    userDao.update();
               }
            }
            

            通过调用就会发现,每个方法都会打印语句:打印日志...。这就是AOP的使用入门。

            2.3 通知类型

            我们通过上面的案例会发现,这里写了一个后置通知,那么有哪些类型的通知呢?我们来看看:

            【Spring】难理解的Aop编程 | 入门?,在这里插入图片描述,第3张

            通知类型描述
            前置通知在方法执行前添加功能
            后置通知在方法正常执行后添加功能
            异常通知在方法抛出异常后添加功能
            最终通知无论方法是否抛出异常,都会执行该通知
            环绕通知在方法执行前后添加功能

            我们通过案例来看看这些通知类型的实现以及使用

            【Spring】难理解的Aop编程 | 入门?,在这里插入图片描述,第4张

            Ⅰ. 🐇 编写通知方法

            通过构造MyAspectAdvice通知类,在里面编写通知方法。

            // 通知类
            public class MyAspectAdvice {
              // 后置通知
              public void myAfterReturning(JoinPoint joinPoint) {
                System.out.println("切点方法名:" + joinPoint.getSignature().getName());
                System.out.println("目标对象:" + joinPoint.getTarget());
                System.out.println("打印日志" + joinPoint.getSignature().getName() + "方法被执行了!");
               }
              // 前置通知
              public void myBefore() {
                System.out.println("前置通知...");
               }
              // 异常通知
              public void myAfterThrowing(Exception ex) {
                System.out.println("异常通知...");
                System.err.println(ex.getMessage());
               }
              // 最终通知
              public void myAfter() {
                System.out.println("最终通知");
               }
              // 环绕通知
              public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
                System.out.println("环绕前");
                Object obj = proceedingJoinPoint.proceed(); // 执行方法
                System.out.println("环绕后");
                return obj;
               }
            }
            

            Ⅱ. 🐇 编写切面

            
            
              
              
                
                
                
                
                
                
                
                
                
                
                
                
              
            
            

            Ⅲ. 🐇 测试

            在这里就不阐述了,跟上面的案例是一样的。

            三. 🦁 切点表达式

            我们上面的几个案例中都用到了切点表达式,即:

            【Spring】难理解的Aop编程 | 入门?,在这里插入图片描述,第5张

            使用AspectJ需要使用切点表达式配置切点的位置。

            【Spring】难理解的Aop编程 | 入门?,在这里插入图片描述,第6张

            3.1 使用语法

            访问修饰符 返回值 包名.类名.方法名(参数列表)

            遵循以下习惯:

            • 访问修饰符可以省略、返回值使用 * 代表任意类型、包名使用 * 表示任意包,多级包结构要写多个 * ,使用 *.. 表示任意包结构
            • 类名和方法名都可以用 * 实现通配。
            • 参数列表

              基本数据类型直接写类型

              引用类型写 包名.类名

              *表示匹配一个任意类型参数

              .. 表示匹配任意类型任意个数的参数

            • 全通配: * *..*.*(..)

            四. 🦁 总结

            今天总结了AOP的基本使用方法。通过使用AspectJ框架来实现AOP的基本用法以及介绍了该框架的几种通知类型。今天的分享到这里,希望您喜欢!