在Spring中默认使用JDK 动态代理实现AOP编程。使用org.spring.framework.aop.framework.ProxyFactoryBean
创建代理是SpringAOP实现的基本方式。
通知类型
- 环绕通知
环绕通知(org.aopalliance.intercept.MethodInterceptor
)是在目标方法执行前和执行后实施增强,可应用于日志记录、事务处理等功能。 - 前置通知
前置通知(org.springframework.aop.MethodBeforeAdvice
)是在目标方法执行前实施增强,可应用于权限管理等功能。 - 后置返回通知
后置返回通知(org.springframework.aop.AfterReturningAdvice
)是在目标方法成功执行后实施增强,可应用于关闭流、删除临时文件等功能。 - 后置(最终)通知
后置通知(org.springframework.aop.AfterAdvice
)是在目标方法执行后实施增强,与后置返回通知不同的是,不管是否发生异常都要执行该类通知,该类通知可应用于释放资源。 - 异常通知
异常通知(org.springframework.aop.ThrowsAdvice
)是在方法抛出异常后实施增强,可应用于处理异常、记录日志等功能。 - 引入通知
引入通知(org.springframework.aop.IntroductionInterceptor
)是在目标类中添加一些新的方法和属性,可应用于修改目标类(增强类)。
ProxyFactoryBean
ProxyFactoryBean是org.springframework.beans.factory.FactoryBean接口的实现类,FactoryBean负责实例化一个Bean实例,ProxyFactoryBean 负责为其他Bean实例创建代理实例。
常用属性
属性 | 描述 |
---|---|
target | 代理的目标对象 |
proxyInterfaces | 代理需要实现的接口列表,如果有多个接口,则使用List标签 赋值 |
interceptorNames | 需要织入的通知,即定义的切面类 |
proxyTargetClass | 是否对类代理而不是接口,默认值为false,使用JDK动态代理;当为true时,使用CGLIB动态代理 |
singleton | 返回代理实例是否为单例,默认为true |
演示(以环绕通知为例)
导入相关的jar包
- spring-aop.jar
- aopalliance.jar
创建切面类MyAspect
,实现环绕通知的接口MethodInterceptor
package gzc.aopalliance.proxyfactorybean;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
//基于代理类的AOP实现
//切面类
public class MyAspect implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation arg0) throws Throwable {
//增强方法
check();
except();
Object obj = arg0.proceed();
log();
// 返回目标方法的返回值
return obj;
}
public void check() {
System.out.println("模拟权限控制");
}
public void except(Exception e) {
System.out.println("模拟异常处理:" + e.getMessage());
}
public void log() {
System.out.println("模拟日志记录");
}
}
目标类TestDaoImpl
package gzc.dao.impl;
import org.springframework.stereotype.Repository;
import gzc.dao.TestDao;
public class TestDaoImpl implements TestDao {
@Override
public void save() {
// TODO Auto-generated method stub
// int a = 100 / 0;
System.out.println("保存...");
}
@Override
public void delete() {
// TODO Auto-generated method stub
System.out.println("删除...");
}
}
配置
<bean id="myTestDao" class="gzc.dao.impl.TestDaoImpl"/>
<!-- 配置代理类实现AOP -->
<!-- 配置切面类bean -->
<bean id="myAspect" class="gzc.aopalliance.proxyfactorybean.MyAspect" />
<!-- 使用Spring代理工厂定义一个名为testDaoProxy的代理对象 -->
<bean id="testDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 指定代理实现的接口-->
<property name="proxyInterfaces" value="gzc.dao.TestDao" />
<!-- 指定目标对象 -->
<property name="target" ref="myTestDao" />
<!-- 指定切面,织入环绕通知-->
<property name="interceptorNames" value="myAspect"/>
<!-- 指定代理方式,true指定CGLIB动态代理,false指定JDK动态代理 -->
<property name="proxyTargetClass" value="true"/>
</bean>
测试
public class Test {
public static void main(String[] args) {
ApplicationContext appCon = new ClassPathXmlApplicationContext("applicationContext.xml");
// 基于代理类的AOP实现 环绕通知
TestDao testAdvice = (TestDao) appCon.getBean("testDaoProxy");
testAdvice.save();
System.out.println("=============================");
testAdvice.delete();
}
}