前言
学到了现在,我们开启新的篇章:Spring AOP的学习,那么说到Spring AOP就要先知道什么是AOP?
AOP(Aspect Oriented Programming),即面向切面编程,是一种程序设计思想和开发方法,它将业务逻辑和横切关注点进行分离,使系统更具模块化、可重用性和维护性。
在传统的OOP(Object Oriented Programming)中,业务逻辑通常被包含在对象的方法中,而横切关注点(如日志、安全、事务等)则分散在各个模块之间,难以管理和维护。而AOP通过切面(Aspect)的概念,将横切关注点从业务逻辑中抽离出来,形成一个独立的模块,使得这些关注点能够更加明确和集中地处理,避免了代码的重复和耦合。
切面可以理解为对业务逻辑的横向扩展,通过定义一系列的切点(Join point)和通知(Advice),将这些扩展应用到系统中的特定位置,如方法执行前、执行后等,并可以定义切点的时机、条件等,实现对横切关注点的灵活控制。同时,AOP还提供了各种其他概念和技术支持,如切面组合(Aspect composition)、切面织入(Aspect weaving)等,使得开发者可以更灵活地对系统进行模块化和定制化。
总之,AOP是一种重要的编程思想和方法论,它通过分离横切关注点和业务逻辑,在保持系统整体性的同时,提高了系统的可复用性、可维护性和可扩展性。在实际的软件开发中,AOP已经被广泛地应用于各个领域,并且得到了良好的效果和反响
具体如何理解呢?举一个例子,在我实现博客系统页面的时候,在进入博客列表页,博客详情页的时候,是需要先验证一下用户信息的,当时我实现的方式,在具体的后端代码中添加一个验证的方法,对于整体来说,这些重复的代码就显得冗余了而且后期维护起来改一处,其他处你说改不改?而AOP的思想就是把这个身份验证的方法拎出来,专门有一块地方来处理身份验证的操作的。
AOP是个思想但是不是为了替代OOP,而是对于OOP进行扩展补充。
该如何学习Spring AOP?
1.AOP组成 2. 使用 3.原理
1.AOP的相关概念
1.切面(类)
指某一个方面的具体内容就是一个切面,比如刚才提到的用户验证就是一个切面。
切面就是包含了切点和通知,也包含了连接点的定义。
2.切点
切点就是定义一个拦截规则。还是进行一个声明方法。
还是前言的案例,如果是登录页还需要登陆验证吗?就是规定一下哪些部分需要进行拦截。
3.连接点
所有触发拦截的点都叫连接点
4.通知
具体的拦截部分执行的业务逻辑~
Spring 切⾯类中,可以在⽅法上使⽤以下注解,会设置⽅法为通知⽅法,在满⾜条件后会通知本
⽅法进⾏调⽤:
前置通知使⽤ @Before:通知⽅法会在⽬标⽅法调⽤之前执⾏。
后置通知使⽤ @After:通知⽅法会在⽬标⽅法返回或者抛出异常后调⽤返回之后通知使⽤ @AfterReturning:通知⽅法会在⽬标⽅法返回后调⽤。
抛异常后通知使⽤ @AfterThrowing:通知⽅法会在⽬标⽅法抛出异常后调⽤。
环绕通知使⽤ @Around:通知包裹了被通知的⽅法,在被通知的⽅法通知之前和调⽤之后执
⾏⾃定义的⾏为。
2.实现Spring AOP
2.1 添加Spring Boot AOP框架
要注意的是田间的Spring Boot AOP的框架,而不是Spring AOP的
2.2 创建切面
创建切面其实就是创建一个类
@Aspect注解是表明了这个类是切面类,而@Compnent注解也是不能少的,因为我们要知道这个aop框架是在SpringBoot基础上实现的,如果没有这个注解,该aop就不会随着spring的启动而启动了,换句话说,如果不加此注解,aop虽然存在但是没办法使用了。
Spring AOP 和 aspectJ的区别
二者其实是竞争的关系,在一开始的时候,spring是没有aop这个功能的,所以民间大佬创造了aspectj这个东西,后来spring也发现了aop这个需求,因此也创造了spring aop 但是spring这个公司发现大家习惯于使用了aspectj,因此spring采用还是aspectj的语法,但实现方式是spring aop的。
2.3 创建切点
创建切点其实就是在切面类里创建方法,此方法的目的一是为了规定一下拦截规则,而是声明了方法。但是这方法是没有具体实现的代码的,具体的业务拦截是在通知里面实现的。
在注解里面
2.4 创建通知
创建通知,其实就是实现具体的拦截业务。
比如创建一个后置通知,在你具体的业务执行完之后,才去执行的通知
2.5 创建连接点
连接点就是触发拦截的点,在注解中我们已经声明了触发拦截的规则,就是在contoller包下UserController该类的所有方法。
执行结果:
要注意的是around通知的使用
around通知的实现:
要注意的是around和其他的通知的执行顺序:
具体的理解(个人):当我们使用around的时候,是需要获取到连接点的,也就是UserController类的,那就是使用了ProceedingJoinPoint,获取到这个类,而proceed的方法就是执行这个类的,在proceed之前之后就可以执行其他操作了。也就是说around把执行具体方法这个过程包裹起来了,而其他的通知相当于也是随着proceed来执行的~~
3. Spring AOP的原理
Spring AOP是在动态代理的基础上实现的,何为动态代理,就是在目标对象和代理对象中间建立一层,通过中间层去实现对目标对象的访问与操作。就好比在用户登陆验证的业务场景下,如果没有AOP的思想的话,我们要进行验证操作就得是在有需要的目标对象(目标的类)都得加上一个验证的方法,而如果使用动态代理的方式去实现的话,目标对象(目标的类)就不需要考虑这个验证的方法了,专心做自己的事情就ok了。
Spring AOP 是构建在动态代理基础上,因此 Spring 对 AOP 的⽀持局限于⽅法级别的拦截。
Spring AOP ⽀持 JDK Proxy 和 CGLIB ⽅式实现动态代理。默认情况下,实现了接⼝的类,使
⽤ AOP 会基于 JDK ⽣成代理类,没有实现接⼝的类,会基于 CGLIB ⽣成代理类
在学习Spring AOP的原理前还需要了解一下Spring AOP的另一个相关概念:
织入
简单来说织入就是指的是代理的生成时机,这个时机可以是编译期间运行期间类加载期间,而我们的Spring AOP则是在运行期间进行的。
正如前面提到Spring AOP有俩种方式实现:JDK Proxy动态代理和CGLIB
JDK Proxy实现动态代理:
JDK动态代理具体实现就是实现目标对象接口的对象(相当于用了目标对象的接口,再创建一个代理对象),有这个代理类对象是在运行期进行织入的,所以JDK动态代理就必须要求目标对象是实现接口的。
在JDK动态代理中,通过反射机制实现了在运行时获取接口信息、方法信息和参数信息等功能,并且利用反射机制动态地创建代理对象,使得我们能够在不修改原始类代码的情况下对其进行增强或者控制。
CGLIB实现动态代理:
CGLIB就是实现目标对象的子类来进行代理,因此它要求目标对象不能被final修饰。CGLIB利用ASM框架直接操作字节码生成代理类。
二者区别: