11.Spring AOP

06-15 1194阅读

文章目录

  • 1.什么是 Spring AOP?
  • 2.为什要用 AOP?
  • 3.Spring AOP 应该怎么学习呢?
    • 3.1 AOP 组成
      • 3.1.1 切⾯(Aspect)= 切点 + 通知
      • 3.1.2 连接点(Join Point)
      • 3.1.3 切点(Pointcut)
      • 3.1.4 通知(Advice)
      • 3.2 Spring AOP 实现
        • 3.2.1五大通知类型
        • 3.2.2 @Order注解解析
        • 3.2.3切点表达式
        • 3.2.4@annotation
        • 3.3 Spring AOP 实现原理 - 代理模式(静态代理,动态代理)
          • 3.3.1静态代理 代码实现
          • 3.3.1动态代理 代码实现
            • 3.3.1.1jdk 动态代理实现
            • 3.3.1.2CGLIB 动态代理实现
            • 3.3.2面试题

              大家好,我是晓星航。今天为大家带来的是 Spring AOP 相关的讲解!😀

              1.什么是 Spring AOP?

              Spring两大核心思想:Ioc Aop

              在介绍 Spring AOP 之前,⾸先要了解⼀下什么是 AOP?

              AOP(Aspect Oriented Programming):⾯向切⾯编程,它是⼀种思想,它是对某⼀类事情的集中处理。⽐如⽤户登录权限的效验,没学 AOP 之前,我们所有需要判断⽤户登录的⻚⾯(中的⽅法),都要各⾃实现或调⽤⽤户验证的⽅法,然⽽有了 AOP 之后,我们只需要在某⼀处配 置⼀下,所有需要判断⽤户登录⻚⾯(中的⽅法)就全部可以实现⽤户登录验证了,不再需要每个⽅法中都写相同的⽤户登录验证了。 ⽽ AOP 是⼀种思想,

              ⽽ Spring AOP 是⼀个框架,提供了⼀种对 AOP 思想的实现,它们的关系和 IoC 与 DI 类似。

              2.为什要用 AOP?

              想象⼀个场景,我们在做后台系统时,除了登录和注册等⼏个功能不需要做⽤户登录验证之外,其他⼏ 乎所有⻚⾯调⽤的前端控制器( Controller)都需要先验证⽤户登录的状态,那这个时候我们要怎么处理呢?

              我们之前的处理⽅式是每个 Controller 都要写⼀遍⽤户登录验证,然⽽当你的功能越来越多,那么你要写的登录验证也越来越多,⽽这些⽅法⼜是相同的,这么多的⽅法就会代码修改和维护的成本。那有没 有简单的处理⽅案呢?答案是有的,对于这种功能统⼀,且使⽤的地⽅较多的功能,就可以考虑 AOP 来统⼀处理了。

              除了统⼀的⽤户登录判断之外,AOP 还可以实现:

              • 统⼀⽇志记录
              • 统⼀⽅法执⾏时间统计
              • 统⼀的返回格式设置
              • 统⼀的异常处理
              • 事务的开启和提交等

                也就是说使⽤ AOP 可以扩充多个对象的某个能⼒,所以 AOP 可以说是 OOP(Object Oriented Programming,⾯向对象编程)的补充和完善。

                3.Spring AOP 应该怎么学习呢?

                11.Spring AOP

                3.1 AOP 组成

                3.1.1 切⾯(Aspect)= 切点 + 通知

                切⾯(Aspect)由切点(Pointcut)和通知(Advice)组成,它既包含了横切逻辑的定义,也包 括了连接点的定义。

                切⾯是包含了:通知、切点和切⾯的类,相当于 AOP 实现的某个功能的集合。

                3.1.2 连接点(Join Point)

                应⽤执⾏过程中能够插⼊切⾯的⼀个点,这个点可以是⽅法调⽤时,抛出异常时,甚⾄修改字段 时。切⾯代码可以利⽤这些点插⼊到应⽤的正常流程之中,并添加新的⾏为。

                连接点相当于需要被增强的某个 AOP 功能的所有⽅法。

                3.1.3 切点(Pointcut)

                Pointcut 是匹配 Join Point 的谓词。

                Pointcut 的作⽤就是提供⼀组规则(使⽤ AspectJ pointcut expression language 来描述)来 匹配 Join Point,给满⾜规则的 Join Point 添加 Advice。

                切点相当于保存了众多连接点的⼀个集合(如果把切点看成⼀个表,⽽连接点就是表中⼀条⼀条 的数据)。

                3.1.4 通知(Advice)

                切⾯也是有⽬标的 ——它必须完成的⼯作。在 AOP 术语中,切⾯的⼯作被称之为通知。

                通知:定义了切⾯是什么,何时使⽤,其描述了切⾯要完成的⼯作,还解决何时执⾏这个⼯作的问题。

                Spring 切⾯类中,可以在⽅法上使⽤以下注解,会设置⽅法为通知⽅法,在满⾜条件后会通知本 ⽅法进⾏调⽤:

                • 前置通知使⽤ @Before:通知⽅法会在⽬标⽅法调⽤之前执⾏。
                • 后置通知使⽤ @After:通知⽅法会在⽬标⽅法返回或者抛出异常后调⽤。
                • 返回之后通知使⽤ @AfterReturning:通知⽅法会在⽬标⽅法返回后调⽤。
                • 抛异常后通知使⽤ @AfterThrowing:通知⽅法会在⽬标⽅法抛出异常后调⽤。
                • 环绕通知使⽤ @Around:通知包裹了被通知的⽅法,在被通知的⽅法通知之前和调⽤之后执 ⾏⾃定义的⾏为。

                  切点相当于要增强的⽅法。

                  3.2 Spring AOP 实现

                  11.Spring AOP11.Spring AOP

                  加了Aop方法后,查询消耗的时间:

                  11.Spring AOP

                  概念理解:

                  11.Spring AOP

                  代码图解:

                  11.Spring AOP

                  3.2.1五大通知类型

                  Spring中AOP的通知类型有以下几种:

                  • @Around:环绕通知,此注解标注的通知方法在目标方法前,后都被执行
                  • @Before:前置通知,此注解标注的通知方法在目标方法前被执行
                  • @After: 后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行
                  • @AfterReturning:返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行
                  • @AfterThrowing:异常后通知,此注解标注的通知方法发生异常后执行

                    11.Spring AOP

                    11.Spring AOP

                    定义五个方法:

                    11.Spring AOP

                    切点

                    11.Spring AOP

                    自定义切点pt

                    11.Spring AOP

                    多个切面执行顺序

                    11.Spring AOP

                    3.2.2 @Order注解解析

                    如果我们每次使用切面都要算顺序未免会很麻烦,为了解决这个问题我们引入了 @Order

                    11.Spring AOP

                    从结果可以看出,我们给Order传参的数字越小,优先级越高

                    11.Spring AOP

                    11.Spring AOP

                    3.2.3切点表达式

                    11.Spring AOP

                    11.Spring AOP

                    11.Spring AOP

                    切点表达式支持通配符表达:

                    11.Spring AOP

                    3.2.4@annotation

                    execution表达式更适用有规则的,如果我们要匹配多个无规则的方法呢,比如:TestController中的t1()和UserController中的u1()这两个方法.

                    这个时候我们使用execution这种切点表达式来描述就不是很方便了

                    我们可以借助自定义注解的方式以及另一种切点表达式 @annotation 来描述这一类的切点

                    实现步骤:

                    1. 编写自定义注解
                    2. 使用 @annotation 表达式来描述切点
                    3. 在连接点的方法上添加自定义注解

                    准备测试代码:

                    @RequestMapping("/test")
                    @RestController
                    public class TestController {
                        @RestMapping("/t1")
                        public String t1() {
                            return "t1";
                        }
                        @RestMapping("/t2")
                        public boolean t2() {
                            return true;
                        }
                    }
                    

                    自定义注解声明: — MyAspect

                    11.Spring AOP

                    自定义注解使用:

                    11.Spring AOP

                    注意这里的@MyAspect就是我们自定义的@Before生效注解

                    11.Spring AOP

                    idea运行结果

                    3.3 Spring AOP 实现原理 - 代理模式(静态代理,动态代理)

                    基于动态代理来实现的

                    代理模式:静态代理模式、动态代理模式

                    使用代理前:

                    11.Spring AOP

                    使用代理后:

                    11.Spring AOP

                    生活中的代理

                    • 艺人经纪人:广告商找艺人拍广告,需要经过经纪人,由经纪人来和艺人进行沟通
                    • 房屋中介:房屋进行租赁时,卖方会把房屋授权给中介,由中介来代理看房,房屋咨询等服务
                    • 经销商:厂商不直接对外销售产品,由经销商负责代理销售
                    • 秘书/助理:合作伙伴找老板谈合作,需要先经过秘书/助理预约

                      静态代理:在程序运行前,代理对象就已经对目标对象进行了步骤的预执行代码

                      例如:我们在结账时买完东西老板会给我们拿袋子装东西,静态代理就是提前把袋子拿好,而动态代理则是需要时再拿,不提前分配。

                      代理模式的主要角色

                      1. Subject: 业务接口类,可以是抽象类或者接口(不一定有)
                      2. RealSubject: 业务实现类,具体的业务执行,也就是被代理对象,
                      3. Proxy: 代理类. RealSubject的代理

                      比如房屋租赁

                      Subject 就是提前定义了房东做的事情,交给中介代理,也是中介要做的事情

                      RealSubject:房东

                      Proxy: 中介

                      UML类图如下:

                      11.Spring AOP

                      代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强.

                      根据代理的创建时期,代理模式分为静态代理和动态代理

                      • 静态代理:由程序员创建代理类或特定工具自动生成源代码再对其编译,在程序运行前代理类的.class 文件就已经存在了.
                      • 动态代理:在程序运行时,运用反射机制动态创建而成.

                        3.3.1静态代理 代码实现

                        房东接口:

                        11.Spring AOP

                        房东类:

                        11.Spring AOP

                        中介:

                        11.Spring AOP

                        主函数:

                        11.Spring AOP

                        3.3.1动态代理 代码实现

                        3.3.1.1jdk 动态代理实现

                        jdk代理类代码:

                        11.Spring AOP

                        主函数:

                        11.Spring AOP

                        11.Spring AOP

                        JDK只能代理接口,不能代理类

                        3.3.1.2CGLIB 动态代理实现

                        CGLIB代理类代码:

                        11.Spring AOP

                        主函数:

                        //CGLib 动态代理
                                HouseSubject proxy3 = (HouseSubject) Enhancer.create(target.getClass(), new CGLibIntercepter(target));
                                proxy3.rentHouse();
                        //CGLib 代理类
                                HouseSubjectClass proxy4 = (HouseSubjectClass) Enhancer.create(subjectClass.getClass(), new CGLibIntercepter(subjectClass));
                                proxy4.rentHouse();
                        

                        11.Spring AOP

                        CGLIB既可以代理类,又可以代理接口

                        3.3.2面试题

                        1.Spring AOP是怎么实现的?

                        答:基于动态代理实现的。

                        2.动态代理是怎么实现的?

                        答:Spirng动态代理是基于JDK和CGlib实现的

                        3.Spring 使用的哪个动态代理?

                        答:JDK和CGLIb都用

                        4.什么时候用JDK,什么时候用CGLIb?

                        答:代理类只能使用CGlib。代理接口可以使用JDK,也可以使用CGLib。

                        5.JDK和CGLib有什么区别?

                        答:SpringBoot 2.X以后,默认使用CGLIB代理

                        spring.aop.proxy-target-class=false 设置JDK代理

                        11.Spring AOP

                        感谢各位读者的阅读,本文章有任何错误都可以在评论区发表你们的意见,我会对文章进行改正的。如果本文章对你有帮助请动一动你们敏捷的小手点一点赞,你的每一次鼓励都是作者创作的动力哦!😘

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]