SpringAOP
- 什么是面向切面编程
切面取代了继承和委托的方法。横切关注点被模块化一个特殊的类,叫做切面
- AOP术语
通知(Advice):
切面的工作内容,叫作通知。通知定义了切面什么时候以及何时使用,通知的工作。有5种类型的通知
-
前置通知(方法开始前)
-
后置通知(方法结束后)
-
返回通知(执行成功后调用通知)
-
异常通知(执行异常后调用)
-
环绕通知(前置+后置)
连接点(Join Point):
应用这些通知的时间叫做连接点(可以切入的点)
切点(Poincut):
切点定义会匹配通知要织入的一个或多个连接点
切面(Aspect)
切点和通知共同定义的切面是什么。
引入(Introduction)
引入允许我们在不修改的情况下向现有的类里面添加新的方法或属性
织入(Wearing)
织入是把切面应用到目标对象上并创建新的代理对象的过程
- Spring对AOP的支持
Spring提供了4种对AOP的支持
-
基于经典代理的Spring AOP
-
纯POJO切面
-
@AspectJ注解驱动的切面
-
注入式Aspectj切面
前面三种都是springAOP的实现变体
- 通过切点来选择连接点
Spring中,使用AspectJ的切点表达式来定义切点。Spring只支持AspectJ的切点指示器。
Spring可以使用的切点指示器
如果使用了其他的治指示器,就会抛出非法参数异常
- 编写切点
使用切点表达式来定义切点
AspectJ指示器 后面这一串是类或接口名
94b84b7b6f1fa8b4cafa0a09711a60a1.png
*表示任意返回值 这是指定的方法 ..表示任意参数,还可以使用&& 、||、!来在后面添加不同的限制条件,比如within(包名)来限制使用,使用bean(bean名字)来限定bean的使用
- 使用注解来创建切面
702ecfe0228209abc3b82c123ccb95f8.png
使用@Aspect标签来表示这是一个通知,使用@Before,@After来配置前置通知还是后置通知,使用表达式来限定切入点,后面的方法则是通知的内容
AspectJ注解详细
@After 在方法返回或异常后调用
@Before 在方法执行之前调用
@Around 通知方法会把目标方法包装起来
@AfterReturning 返回后调用
@AfterThrowing 异常后调用
相同的切点重复的定义不是一件好事。所以使用@Pointcut(表达式)来定义一个切点,在它下面的方法名就可以在后面代替掉这个长长的表达式
1a404f1a73daf444a5262a5335685504.png
现在这个performce方法的具体内容已经不重要了,他应该是空的
注意,这个Advice类任然是一个POJO,也可以被装配成一个Bean。使用JavaConfig的话,可以在类的级别上使用@EnableAspectJAutoProxy注解开启自动代理的功能
62e5abb3b603511059fed28f2bcfd8ff.png
测试代码如下
2bcaf1b09a2c87fa544b384291b60cb9.png
使用注解来配置AOP的操作略过
- 创建环绕通知
环绕通知可以把目标方法全部包裹起来,就像在编写前置通知的同时编写后置通知一样
9f5f4a4e4410471f6670a209e26d7ed7.png
传入一个ProceedingJoinPointl类来标记对象方法的位置,并且要调用proceed()方法。如果不调用的话就会阻塞对原目标函数的调用
你也可以在通知里多次调用这个方法来达到多次调用目标方法的效果
结果如下:
46530a7118405281127a6601a4742983.png
- 处理通知中的参数
如果我们所通知的方法里有参数的话,以上的三点可能就不是很合适了。
Bean中的方法如下
37b7c9a445843193b60baa204b8b240d.png
调用方法如下
b86c7cf0999293b1d4b0a401d5b833f5.png
报表达式如下
b33f959a8a4687821def1a764d0fb08c.png
args()表示传给目标方法的参数也会传到通知里去
bc00e25c91a5be8b2af3c4c8a4eac4e2.png
执行结果如下
b20ac471b82c7771daa16e7bc4dce5bb.png
实现高级的功能的时候可以在通知类里面写上相应的成员变量作为数据结构,比如记录播放次数等
- 通过注解注入新功能
AOP只是一个代理,它实现了被通知bean的接口。如果这个时候这个代理实现一个新的接口的话,看起来就像那个Bean实现类那个新的接口一样。
具体操作如下
需要加入的新接口如下
c6a513461d081f729c1f27ac968ce8f2.png
上面接口的实现类如下
f9ace7c5579fa6e04b1a2ccb50120234.png
配置一个新的切面文件,使用@DeclareParent标记来配置需要加上新功能的接口和扩展的接口
vaule表示需要扩展的接口,+表示实现它的类都会获得扩展
defaultImpl表示要加上的接口实现类
后面的静态属性表明了要扩展哪个接口
具体配置如下
d75f4273fc5f61463133b1be302c0d67.png
调用的时候就有这个接口了
3bbb6d7a4767c02ac09bf63afcf783fc.png
ad13773ec12f4b598e45abd77ea80e7b.png
如果你有源码,那么使用注解配置bean是很棒的选择。但是再没有源码的情况下,或者不能侵入该代码的情况下,使用xml配置切面就是唯一的选择了
-
再xml里面配置AOP略过
-
注入AspectJ切面
AspectJ切面的应用比Spring更加广泛,比如可以在Bean构造的时候创建切面。AspectJ的切面和SpringAOP切面是相互独立的,AspectJ切面几乎不会涉及到任何的Spring。










网友评论