课程概要:
- Spring AOP的基本概念
- Spring AOP的增强类型
- Spring AOP的前置增强
- Spring AOP的后置增强
- Spring AOP的环绕增强
- Spring AOP的异常抛出增强
- Spring AOP的引介增强
一.Spring AOP
增强
的基本概念
Spring当中的专业术语-advice,翻译成中文就是增强的意思。
所谓增强,其实就是向各个程序内部注入一些逻辑代码从而增强原有程序的功能。
二.Spring AOP的增强类型
首先先了解一下增强接口的继承关系
如上图所示:
其中带Spring标志的是Spring定义的扩展增强接口
其中带aopalliance标志的是AOP联盟所定义的接口
按照增加在目标类方法连接点的位置可以将增强划分为以下五类:
- 前置增强 (org.springframework.aop.BeforeAdvice) 表示在目标方法执行前来实施增强
- 后置增强 (org.springframework.aop.AfterReturningAdvice) 表示在目标方法执行后来实施增强
- 环绕增强 (org.aopalliance.intercept.MethodInterceptor) 表示在目标方法执行前后同时实施增强
- 异常抛出增强 (org.springframework.aop.ThrowsAdvice) 表示在目标方法抛出异常后来实施增强
- 引介增强 (org.springframework.aop.introductioninterceptor) 表示在目标类中添加一些新的方法和属性
其中,引介增强是一种特殊的增强。他可以在目标类中添加属性和方法,通过拦截定义一个接口,让目标代理实现这个接口。他的连接点是类级别的,而前面的几种则是方法级别的。
其中,环绕增强是AOP联盟定义的接口,其他四种增强接口则是Spring定义的接口。
其实,AOP增强很简单:
通过实现这些增强接口,在实现这些接口的方法当中定义横切逻辑,然后通过配置Spring的配置文件就可以完成将增强织入到目标方法当中了。
补充:增强既包含了横切逻辑同时又包含了部分连接点信息。
三.Spring AOP的前置增强
1.通过代码实现增强
在Spring当中,仅支持方法级别的增强,利用MethodBeforeAdvice实现,表示在目标方法执行前实施增强。
示例演示:
对服务生的服务用语进行强制规范。我们假设服务生只需要干两件事情:1.欢迎顾客 2.对顾客提供服务
那么我们创建的示例代码的主要步骤如下:
- 创建业务接口类:Waiter.java
- 创建业务实现类:NativeWaiter.java
- 创建业务增强类:GreetingBeforeAdvice.java
- 创建增强测试类:TestAdvice.java
接下来我们分别在IDEA中创建相应的类。
服务生接口Waiter.java
服务生实现类NativeWaiter.java
服务生业务增强类GreetingBeforeAdvice.java
增强测试类TestBeforeAdvice.java
程序运行结果:
How Are You! mr.icarus
greet toicarus...
How Are You! mr.icarus
servingicarus...
2.ProxyFactory介绍
其实ProxyFactory代理技术就是利用jdk代理或者cglib代理的技术,将增强应用到目标类当中。
Spring定义的AOP Proxy类具有两个final类型的实现类,如下图所示:
其中:
Cglib2AopProxy是使用cglib代理技术来创建代理
JdkDynamicAopProxy是使用jdk代理技术来创建代理
那么使用JDK代理来实现上面的代码则为:
使用CGLib代理则为:
可以观察到,ProxyFactory通过addAdvice来增加一个增强。
用户可以使用该方法增加多个增强,通过增强形成一个增强链,他们的调用顺序和添加顺序是一致的
3.通过配置文件实现增强
我们也可以通过配置文件来实现Spring的前置增强,并且大多数情况下都是使用配置文件方式。
首先我们介绍下ProxyFactory Bean配置文件当中常用的属性:
- target:我们需要代理的目标对象
- proxyInterfaces:代理所要实现的接口,可以是多个接口
- interceptorNames:需要织入的目标对象的Bean的列表(增强类的Bean列表),使用Bean的名称来指定。
- singleton:确定返回的代理是不是单实例的,系统默认返回的是单实例的。
- optimize:当值为true时,强制使用cglib代理。当是singleton的实例时我们推荐使用cglib代理,当是其他作用域的时候,推荐使用JDK的代理。原因是cglib创建代理速度比较慢,但是运行效率高。JDK代理则刚好相反。
- proxyTargetClass:是否对类进行代理而不是对接口进行代理,当值为true的时候使用cglib代理
接下来我们使用配置文件对上面的示例代码进行配置:
接下来我们创建对应的测试文件
可以看到输出结果为:
How Are You! mr.icarus
greet toicarus...
How Are You! mr.icarus
servingicarus...
和我们通过代码实现增强的结果相同
四.Spring AOP的后置增强
后置增强在目标方法调用后执行,例如上面的例子中,在服务生每次服务后,也需要向客人问候,可以通过后置增强来实施这一要求,步骤如下:
- 创建业务接口类:Waiter.java
- 创建业务实现类:NativeWaiter.java
- 创建业务增强类:GreetingAfterAdvice.java
- 创建配置文件:conf-advice.xml
- 创建增强测试类:TestAdvice.java
接下来我们在IDEA中创建相应的代码:
我们继续使用上面的例子,由于
Waiter.java和
NativeWaiter.java已经创建好了
我们只需创建
GreetingAfterAdvice.java
接下来我们修改对应的配置文件
首先得将后者增强类作为bean配置到文件当中
<bean id="gerrtingAfter" class="cn.lovepi.chapter07.aop.advice.GreetingAfterAdvice"/>
接下来得在ProxyFactory Bean当中添加织入的bean
p:interceptorNames="gerrtingBefore,gerrtingAfter"
完整的配置文件如下:
测试文件和上面的保持不变,运行测试类,测试结果为:
How Are You! mr.icarus
greet toicarus...
please enjoy youself!
How Are You! mr.icarus
servingicarus...
please enjoy youself!
五.Spring AOP的环绕增强
环绕增强允许在目标类方法调用前后织入横切逻辑,它综合实现了前置,后置增强两者的功能,下面是我们用环绕增强同时实现上面的我们的示例。步骤如下:
- 创建业务接口类:Waiter.java
- 创建业务实现类:NativeWaiter.java
- 创建业务增强类:GreetingInterceptor.java
- 创建配置文件:conf-advice.xml
- 创建增强测试类:TestAdvice.java
接下来我们在IDEA中来实现。
首先创建
GreetingInterceptor.java
接下来在配置文件中对其进行配置:
启动测试类,观察打印结果:
How Are You! mr.icarus
GreetingInterceptor:How are you!
greet toicarus...
GreetingInterceptor: please enjoy youself!
please enjoy youself!
How Are You! mr.icarus
GreetingInterceptor:How are you!
servingicarus...
GreetingInterceptor: please enjoy youself!
please enjoy youself!
可以看到,我们成功在示例中实现了前置增强,后者增强以及环绕增强。
六.Spring AOP的异常抛出增强
异常抛出增强表示在目标方法抛出异常后实施增强,最适
合的场景是事务管理,比如当参与事事务的方法抛出异常后需要回滚事务。
异常抛出增强类需要实现
ThrowsAdvice接口,
ThrowsAdvic
e接口并没有定义任何的方法,他只是一个标志接口。
在运行期,Spring采用反射的机制来进行判断。我们必须采用以下的形式来定义异常抛出的方法
public void afterThrowing(Method method,Object[] args,Object target,Throwable t)
其中:
方法名必须为
afterThrowing,方法入参中前三个入参是可选的,即要么同时存在,要么都没有
最后一个入参是
Throwable及其子类,必须得有。
也可以在异常增强类中定义多个方法,Spring会自动选择匹配的方法来进行调用。
在类的继承树上,两个类的距离越近,则两个类的相似度越高
那么当方法抛出异常时,会优先选取异常入参和抛出的异常相似度最高的afterThrowing方法。
接下来我们创建示例来演示一下,步骤如下:
- 创建业务实现类:ForumService.java
- 创建业务增强类:TransactionManager.java
- 创建配置文件:conf-advice.xml
- 创建增强测试类:TestAdvice.java
接下来我们在IDEA上分别创建对应的代码:
首先,我们创建业务逻辑类ForumService
接下来我们创建增强类TransactionManager
接下来我们编写对应的配置文件
创建相应的测试类进行测试
运行结果为:
method:removeForum
抛出异常:removeForum:Exception...
成功回滚事务
method:updateForum
抛出异常:updateForum:Exception...
成功回滚事务
七.Spring AOP的引介增强
引介增强是一种比较特殊的增强类型,他不是在目标方法周围织入增强,而是为目标创建新的方法和属性,所以他的连接点是类级别的而非方法级别的。通过引介增强我们可以为目标类添加一个接口的实现即原来目标类未实现某个接口,那么通过引介增强可以为目标类创建实现某接口的代理。
接下来我们创建一个示例来演示下,步骤如下:
- 创建接口类:Monitorable.java
- 创建业务类:PerformanceMonitor.java
- 创建增强类:ControllablePerformanceMonitor.java
- 创建配置文件:conf-advice-introduce.xml
- 创建增强测试类:TestIntroduce.java
接下来我们在IDEA上分别创建对应的代码:
首先创建性能监视接口Monitorable
创建测试接口Testable
接下来创建业务类
接下来创建增强类 ControllablePerformanceMonitor
接下来创建所要增强的方法类
创建配置文件来将所设置的代码组合起来:
创建对应的测试类
创建配置文件来将所设置的代码组合起来:
创建对应的测试类
程序运行结果为:
模拟删除Forum记录:10
模拟删除Topic记录:1022
begin monitor...
模拟删除Forum记录:10
end monitor...
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.removeForum花费40毫秒。
begin monitor...
模拟删除Topic记录:1022
end monitor...
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.removeTopic花费20毫秒。
总结:
增强其实就是对原有的方法或类动态增加功能,可为方法执行前后以及所抛出的异常进行逻辑处理。实现增强的方式有两种:代码方式和XML配置文件方式,建议在以后开发中使用后者,这样可以避免代码的耦合度,方便后期维护。
注意需要使用AspectJ需要引入一些jar包:
aopalliance.jar
aspectjrt.jar
aspectjtools.jar
aspectjweaver.jar
org.aspectj.matcher.jar
可以根据需要引入上面的部分包,不一定全部需要引入,然后就可以编译通过了,
如果还缺其他的包,可以百度查,然后下载下来就可以了。
资源下载地址:http://download.csdn.net/download/a1317338022/10130277