目录

SpringSpringAOP详解,彻底了解切点通知,附有注解和XML开发完整流程

【Spring】SpringAOP详解,彻底了解切点通知,附有注解和XML开发完整流程

SpringAOP

概念

https://i-blog.csdnimg.cn/img_convert/44c93fa6d8f038a92ef5366a22a013bc.png

快速入门

需求

https://i-blog.csdnimg.cn/img_convert/7f48efb431e680d4b52acf4dbe097de3.png

导入依赖

https://i-blog.csdnimg.cn/img_convert/a396889f9c33eabf39cd1080a3b78c67.png

xml文件开启aop支持

https://i-blog.csdnimg.cn/img_convert/165a2701b61edd6232a82ff566f61ce0.png

自定义aspect切面类

在类上加上@Component和@Aspect

使用@Pointcut注解来指定要被增强的方法

使用@Before注解来给我们的增强代码所在的方法进行标识,并且指定了增强代码是在被增强方法执行之前执行的。

https://i-blog.csdnimg.cn/direct/44bc2071a707440eae9f17656ac12c7a.png

这里的@Pointcut注解就定义了一个切点,表示在这些包下所有的方法增强

需要定义一个没有方法体的方法作为切入点表达式的一个标识

如果有很多个切点,就需要对应写多个无方法体的方法来做标识

结构

https://i-blog.csdnimg.cn/img_convert/efe878a8ba7b78d20e09cddf6a371b83.png

service类代码加@Service注解

https://i-blog.csdnimg.cn/img_convert/1b32459fd6104fc77d709b474f46e8db.png

https://i-blog.csdnimg.cn/img_convert/b3ed2f62db0af99c27a531700495f174.png

测试类只调用deleteAll方法

https://i-blog.csdnimg.cn/img_convert/6d608aec3b0db2387ab7e1ca19b30bbf.png

结果输出

https://i-blog.csdnimg.cn/img_convert/d6ce276b1440922a15b6863d648ae110.png


专业名词

https://i-blog.csdnimg.cn/img_convert/b491c17d1fefb4a6e44cbe919fdb5b5f.png

https://i-blog.csdnimg.cn/img_convert/bbef1f46db28eb18c54a4152b3c7600f.png

代理类

有了AOP增强的对象,通过.getBean获取的对象不是之前的对象,而是 代理对象

那么没有AOP增强的对象通过.getBean获取的对象是之前的对象


切点

切点表达式

https://i-blog.csdnimg.cn/img_convert/5d2eeb607cc75020be2c95b17be490d4.png

https://i-blog.csdnimg.cn/img_convert/65ca1869615075c5b5a727580f9240f8.png

返回值类型,包名,类名,方法名,参数

https://i-blog.csdnimg.cn/img_convert/6b72ae70a75f8bdf424a81f1508bb58f.png


切点函数

@ annotation

可以自定义哪些方法需要增强

1.自定义注解@InvokeLog(名称任意)

https://i-blog.csdnimg.cn/img_convert/e3df2fdd887e5bbeb5927d8c8f40cf14.png

2.给需要增强的方法上增加我们的注解

https://i-blog.csdnimg.cn/img_convert/6f0657c2c6f8dcfb4a1c09ef506cc2ba.png

3.在切面类使用@annotation(自定义注解全类名)

https://i-blog.csdnimg.cn/img_convert/0e65f0a90d03bf63c51823d0f324b96b.png


通知

通知分类

https://i-blog.csdnimg.cn/img_convert/1bdd3936eb5a593e3ca654c0ab1809a6.png

伪代码用于理解执行时机

https://i-blog.csdnimg.cn/img_convert/342af0d24ff7bc94a392eef3754608ec.png

环绕通知@Around

方法参数获取ProceedingJoinPont对象

通过对象调用proceed()执行 目标方法

然后try-catch

在任意位置写增强代码

https://i-blog.csdnimg.cn/img_convert/2dfe62db199290165ede2b23bac086f7.png

通过给通知方法传递ProceedingJoinPont对象参数

然后在try-catch中用这个对象调用proceed()方法,也就是增强目标方法

就可以把增强的方法写在1234任意位置


获取被增强方法的信息

只有获取了被增强方法的信息才能有效的增强方法,而不是简单的输出语句

我们可以在 除了环绕通知外的所有通知方法 中增加一个JoinPoint类型的参数。

这个参数封装了被增强方法的相关信息。

我们可以通过这个参数获取到除了异常对象和返回值之外的所有信息。

https://i-blog.csdnimg.cn/img_convert/06b580756ba6c69503d3ecff172287ef.png

一般通过.getSignature()获取签名封装对象后再去.get其他方法

https://i-blog.csdnimg.cn/direct/92d679e2e0ce44ebac56f9740545671f.png


获取增强方法的返回值和异常对象

需要在方法参数上增加一个对应类型的参数

并且使用注解的属性进行配置。这样Spring会把你想获取的数据赋值给对应的方法参数。

https://i-blog.csdnimg.cn/img_convert/592b483da15d57570fc9ed137da2c597.png

返回值在@AfterReturning里使用,异常对象在@AfterThrowing里使用

因为注解有多个参数,所以value不能省略了

在通知方法中就可以通过传递参数用ret. 和t.去使用获取到的东西了


环绕通知获取信息

https://i-blog.csdnimg.cn/img_convert/08686c23fa39a40e68f1aca01eeee0da.png

该参数的proceed()方法被调用相当于被增强方法被执行

调用后的返回值就相当于被增强方法的返回值。

注意事项

如果有返回值,在通知方法也要有返回值

return的是通知方法的返回值,不是增强方法的返回值,只是获取到了增强方法的返回值通过通知方法返回

可以进行篡改

https://i-blog.csdnimg.cn/img_convert/7c22c46ec9d544f72fb01a397f3ce45a.png

注解方式配置AOP完整流程

结构

https://i-blog.csdnimg.cn/img_convert/4590f31628008c7048d0924b38f2ab4c.png

依赖

https://i-blog.csdnimg.cn/img_convert/42a5d6a1efb11f4a2483c0c3fab49504.png

xml文件

https://i-blog.csdnimg.cn/img_convert/b446bbe00bd37a339ba7b33ad2612af7.png

自定义注解

https://i-blog.csdnimg.cn/img_convert/658cebe359e19bf5683510e89a3ebe10.png

切面类

https://i-blog.csdnimg.cn/img_convert/8970c029d2bbf4ebe7f9bea26f573dd3.png

实现类

https://i-blog.csdnimg.cn/img_convert/b32b08402a291be47e2932da4c6527b8.png

工具类略

测试类

https://i-blog.csdnimg.cn/img_convert/5e715a25787619560f29502ccf4f3d53.png

XML配置AOP(可跳过)

定义切面类

没有@Aspect@Pointcut@Around等注解,

但是要放到spring容器中,要加@Component注解

目标类和切面类都要放到容器中

https://i-blog.csdnimg.cn/img_convert/9d85876861c11a4ff6430ca9bbc7942a.png

依赖

https://i-blog.csdnimg.cn/img_convert/5910d6694d600032aafbac1e75475894.png

xml文件配置

https://i-blog.csdnimg.cn/img_convert/c0b4b74e916524fd846d4329567f6328.png


多切面顺序问题

在实际项目中我们可能会存在配置了多个切面类的情况。这种情况下我们很可能需要控制切面的顺序。

我们在默认情况下Spring有它自己的排序规则。(按照类名排序)

如果是注解方式配置的AOP可以在切面类上加@Order注解来控制顺序。@Order中的属性越小优先级越高。

如果是XML方式配置的AOP,可以通过调整配置顺序来控制。

下面这种配置方式就会先使用CryptAspect里面的增强,在使用APrintLogAspect里的增强

https://i-blog.csdnimg.cn/img_convert/e0e1ce9188baa77ab89f777d6d61f50d.png