
4.3 基于代理类的AOP实现
从4.2节可知,在Spring中默认使用JDK动态代理实现AOP编程。使用org.springframework.aop.framework.ProxyFactoryBean创建代理是Spring AOP实现的最基本方式。
① 通知类型
在讲解ProxyFactoryBean之前先了解一下Spring的通知类型。根据Spring中通知在目标类方法中的连接点位置,通知可以分为6种类型。
1)环绕通知
环绕通知(org.aopalliance.intercept.MethodInterceptor)是在目标方法执行前和执行后实施增强,可应用于日志记录、事务处理等功能。
2)前置通知
前置通知(org.springframework.aop.MethodBeforeAdvice)是在目标方法执行前实施增强,可应用于权限管理等功能。
3)后置返回通知
后置返回通知(org.springframework.aop.AfterReturningAdvice)是在目标方法成功执行后实施增强,可应用于关闭流、删除临时文件等功能。
4)后置(最终)通知
后置通知(org.springframework.aop.AfterAdvice)是在目标方法执行后实施增强,与后置返回通知不同的是,不管是否发生异常都要执行该类通知,该类通知可应用于释放资源。
5)异常通知
异常通知(org.springframework.aop.ThrowsAdvice)是在方法抛出异常后实施增强,可应用于处理异常、记录日志等功能。
6)引入通知
引入通知(org.springframework.aop.IntroductionInterceptor)是在目标类中添加一些新的方法和属性,可应用于修改目标类(增强类)。
② ProxyFactoryBean
ProxyFactoryBean是org.springframework.beans.factory.FactoryBean接口的实现类,FactoryBean负责实例化一个Bean实例,ProxyFactoryBean负责为其他Bean实例创建代理实例。ProxyFactoryBean类的常用属性如表4.1所示。
表4.1 ProxyFactoryBean类的常用属性

下面通过一个实现环绕通知的实例演示Spring使用ProxyFactoryBean创建AOP代理的过程。
1)导入相关JAR包
在核心JAR包的基础上需要向ch4应用的/WEB-INF/lib目录下导入JAR包spring-aop-5.0.2.RELEASE.jar和aopalliance-1.0.jar。
aopalliance-1.0.jar是AOP联盟提供的规范包,可以通过地址“http://mvnrepository.com/artifact/aopaliance/aopalliance/1.0”下载。
2)创建切面类
由于该实例实现环绕通知,所以切面类需要实现org.aopalliance.intercept. MethodInterceptor接口。在src目录下创建一个spring.proxyfactorybean包,并在该包中创建切面类MyAspect。
MyAspect的代码如下:

3)配置切面并指定代理
切面类需要配置为Bean实例,这样Spring容器才能识别为切面对象。在spring.proxyfactorybean包中创建配置文件applicationContext.xml,并在文件中配置切面和指定代理对象。
applicationContext.xml的代码如下:

在上述配置文件中首先通过<bean>元素定义了目标对象和切面,然后使用ProxyFactoryBean类定义了代理对象。
4)创建测试类
在spring.proxyfactorybean包中创建测试类ProxyFactoryBeanTest,在主方法中使用Spring容器获取代理对象,并执行目标方法。
ProxyFactoryBeanTest的代码如下:

上述测试类的运行结果与图4.3一样,这里不再赘述。