一、SpringAOP的概念及术语
二、SpringAOP的实现机制
1.JDK动态代理
//JDK动态代理
public class UserServiceFactory implements InvocationHandler {
//声明目标类接口
private UserService userService;
//使用构造方法获取目标类
public UserServiceFactory(UserService userService) {
this.userService = userService;
}
public UserServiceFactory() {
}
//代理方法
public Object createProxy(){
//类加载器
ClassLoader classLoader = UserServiceFactory.class.getClassLoader();
//被代理对象实现的接口
Class[] classes = UserImp.class.getInterfaces();
//使用代理类进行增强
UserService us = (UserService) Proxy.newProxyInstance(classLoader, classes,this);
return us;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//业务之前的方法--前增强
System.out.println("--------开起事务---------");//切入点
//目标类上调用方法,并传参数
Object invoke = method.invoke(userService, args);
//业务之后的方法--后增强
System.out.println("--------关闭事务---------");
return invoke;
}
}
获取增强后的目标对象方法如下:
//测试JDK动态代理
//只能为接口创建代理对象
@Test
public void text1(){
//获取到接口对象
UserService userService = new UserImp();
//获取动态代理对象
UserServiceFactory factory = new UserServiceFactory(userService);
//获取代理对象
UserService service = (UserService) factory.createProxy();//从代理对象对象中获取增强后的目标对象
service.find();
}
2.CGLib动态代理
JDK动态代理存在缺陷,它只能为接口创建代理对象,当需要为类创建代理对象时,就需要使用CGLib(Code Generation Library)动态代理,CGLib动态代理不要求目标类实现接口,它采用底层的字节码技术,通过继承的方式动态创建代理对象。Spring的核心包已经集成了CGLib所需要的包,所以不需要再导入。其实现如下图:
//CGLib代理类
public class UserServiceFactorys implements MethodInterceptor {
//代理方法
public Object createProxy(Object target){
//创建一个动态类对象
Enhancer enhancer = new Enhancer();
//将接收的对象进行增强,设置其父类
enhancer.setSuperclass(target.getClass());
//添加回调函数
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//业务之前的方法--前增强
System.out.println("--------开起事务---------");//切入点
//目标类上调用方法,并传参数
Object invoke = methodProxy.invokeSuper(o, objects);
//业务之后的方法--后增强
System.out.println("--------关闭事务---------");
return invoke;
}
}
获取增强后的目标对象方法如下:
//测试CGLib动态代理
//可以为类创建代理对象
@Test
public void text2(){
//获取到目标类对象
UserImp user= new UserImp();
//获取动态代理对象
UserServiceFactorys factory = new UserServiceFactorys();
//获取代理对象
UserImp service = (UserImp) factory.createProxy(user);//从代理对象对象中获取增强后的目标对象
service.find();
}
三、基于XML的AOP实现
XML实现AOP切面,其包括以下的元素:
<aop:config>:SpringAOP配置的根元素;
<aop:aspect>:配置切面;
<aop:advisor>:配置通知器;
<aop:pointcut>:配置切入点;
<aop:before>:配置前置通知,在目标方法执行前实施增强,可以应用于权限管理等功能;
<aop:after>:配置后置通知,在目标方法执行后实施增强,可以应用于关闭流、上传文件、 删除临时文件等功能;
<aop:around>:配置环绕通知,在目标方法执行前后实施增强,可以应用于日志、事务管理功能;
<aop:after-returning>:配置返回通知,在目标方法执行之后调用通知;
<aop:after-throwing>:配置异常通知,在方法抛出异常后实施增强,可以应用于处理异常记录日志等功能;
其实现如下:
<!--将通知织入到目标对象中-->
<!--1.配置目标对象-->
<bean name="user" class="com.jay.Service.UserImp"></bean>
<!--2. 配置通知对象-->
<bean name="advice" class="com.jay.advice.Advice"></bean>
<!--3.将对象织入目标对象中-->
<aop:config>
<!-- 3.1 配置切入点-->
<!-- 通配符 -->
<!--
public void com.jay.Service.UserImp.find()
* com.jay.Service.UserImp.find()
* com.jay.Service.*Imp.find()字段用*表示
* com.jay.Service.*Imp.*(..)参数用“..”表示;方法同字段一样用*表示
-->
<aop:pointcut id="pt" expression="execution(* com.jay.Service.UserImp.*())"/>
<!-- 3.2 指定通知-->
<aop:aspect ref="advice">
<aop:before method="getBefore" pointcut-ref="pt"></aop:before>
<aop:after-returning method="getAfter" pointcut-ref="pt"></aop:after-returning>
<aop:around method="getAround" pointcut-ref="pt"></aop:around>
<aop:after-throwing method="getException" pointcut-ref="pt"></aop:after-throwing>
<aop:after method="getLastException" pointcut-ref="pt"></aop:after>
</aop:aspect>
</aop:config>
四、基于注解的AOP实现
@Aspect:配置切面
@Pointcut:配置切入点
@Before:配置前置通知
@After:配置后置通知
@Around:配置环绕通知
@AfterReturning:配置返回通知
@AfterThrowing:配置异常通知