Srping框架的AOP技术底层也是采用的代理技术,代理的方式提供了两种
- 基于JDK的动态代理 必须是面向接口的,只有实现了具体接口的类才能生成代理对象
- 基于CGLIB动态代理 对于没有实现了接口的类,也可以产生代理,产生这个类的子类的方式
AOP的相关术语
1. Joinpoint(连接点) -- 在spring中,这些点指的是方法,因为spring只支持方法类型的连接点
2. Pointcut(切入点) -- 所谓切入点是指我们要对哪些Joinpoint进行拦截的定义
3. Advice(通知/增强) --通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)
4. Introduction(引介) --特殊的通知在不修改类代码的前提下, 在运行期为类动态地添加一些方法或Field
5. Target(目标对象) -- 代理的目标对象
6. Weaving(织入) -- 是指把增强应用到目标对象来创建新的代理对象的过程
7. Proxy(代理) -- 一个类被AOP织入增强后,就产生一个结果代理类
8. Aspect(切面) -- 是切入点和通知的结合,以后咱们自己来编写和配置的AOP的通知类型
1. 前置通知 在目标类的方法执行之前执行。可以对方法的参数来做校验
2. 最终通知 在目标类的方法执行之后执行,如果程序出现了异常,最终通知也会执行。例如像释放资源
3. 后置通知 方法正常执行后的通知。可以修改方法的返回值
4. 异常抛出通知 在抛出异常后通知 包装异常的信息
5. 环绕通知 方法的执行前后执行。
使用Proxy类来生成代理对象
public class MyProxyUtils {
public static UserDao getProxy(final UserDao dao) {
// 使用Proxy类生成代理对象
UserDao proxy = (UserDao) Proxy.newProxyInstance(dao.getClass().getClassLoader(),
dao.getClass().getInterfaces(), new InvocationHandler() {
// 代理对象方法一执行,invoke方法就会执行一次
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("save".equals(method.getName())){
System.out.println("记录日志...");
}
// 让dao类的save或者update方法正常的执行下去
return method.invoke(dao, args);
}
});
// 返回代理对象
return proxy;
}
}
CGLIB的代理
public static OrderDaoImpl getProxy(){
// 创建CGLIB核心的类
Enhancer enhancer = new Enhancer();
// 设置父类
enhancer.setSuperclass(OrderDaoImpl.class);
// 设置回调函数
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
if("save".equals(method.getName())){
// 记录日志
System.out.println("记录日志了...");
}
return methodProxy.invokeSuper(obj, args);
}
});
// 生成代理对象
OrderDaoImpl proxy = (OrderDaoImpl) enhancer.create();
return proxy;
}