Spring AOP原理
参考示例源代码:
https://github.com/huangzhenshi/SpringFreamworkDemo/tree/master
https://zhuanlan.zhihu.com/p/29483023
- JDK动态代理(运行时编译)
- CGLib字节码加强(运行时编译)
- AspectJ(编译时增强的AOP框架)
- Spring代理模式的运用场景: 操作日志、事务控制、异常处理(AOP ThrowsAdvice)、权限认证、缓存
JDK动态代理模式 VS CGLIB
- JDK动态代理 反射原理的类依赖其接口,代理接口的实现方法
- CGLIB,字节码增强技术,根据代理类实现一个增强的子类采用方法拦截的技术拦截所有父类方法的调用,并顺势织入横切逻辑
Spring AOP会根据配置动态选择
proxy-target-class=true,全部都用CGLIB,false则接口类用反射,非接口类用CGLIB
使用
- Pointcut(切点):指定在哪些类的哪些方法上织入横切逻辑
- Advice(增强):描述横切逻辑和方法的具体织入点(方法前、方法后、方法的两端等)
- Advisor(切面):将Pointcut和Advice两者组装起来。有了Advisor的信息,Spring就可以利用JDK或CGLib的动态代理技术采用统一的方式为目标Bean创建织入切面的代理对象了
|
JDK动态代理实现
https://www.cnblogs.com/MOBIN/p/5597215.html
通过实现InvocationHandler接口的invoke方法,来实现代理编程
- 被代理类通过反射获取被代理类的接口和ClassLoader
- 获取接口代理类
- 根据接口代理类获取接口的构造函数
- 根据构造函数引入被代理类,最终获取代理类//获取动态代理类Class proxyClazz = Proxy.getProxyClass(Hello.class.getClassLoader(),Hello.class.getInterfaces());//获得代理类的构造函数,并传入参数类型InvocationHandler.classConstructor constructor = proxyClazz.getConstructor(InvocationHandler.class);//通过构造函数来创建动态代理对象,将自定义的InvocationHandler实例传入IHello iHello = (IHello) constructor.newInstance(new HWInvocationHandler(new Hello()));//通过代理对象调用目标方法iHello.sayHello();
通过实现InvocationHandler接口的invoke方法,来实现代理编程
CGLib实现
- 通过实现MethodInterceptor的intercept方法,来对所有的代理类进行代理操作。
- 具体涉及到继承的增强类子类Enhancer类。并设置子类的方法调用触发器public class CglibProxy implements MethodInterceptor {// 被代理对象Object targetObject;//参数为被代理类,返回结果为代理类public Object getProxyObject(Object object) {this.targetObject = object;//增强器,动态代码生成器Enhancer enhancer=new Enhancer();//回调方法enhancer.setCallback(this);//设置生成类的父类类型enhancer.setSuperclass(targetObject.getClass());//动态生成字节码并返回代理对象return enhancer.create();}// 拦截方法public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {System.out.println("方法调用前");// 调用方法Object result = methodProxy.invoke(targetObject, args);System.out.println("方法调用后");return result;}}
自定义注解的使用
https://www.jianshu.com/p/7dcd59bdbb0a
- 通过元注解给注解做修饰
- 在对应的地方使用注解(可以是类上加注解、方法上加注解、属性上加注解)
- 通过反射获取到目标(类、方法、属性),并调用 *.getAnnotation(),从而获取注解类
|
Aspect
https://www.cnblogs.com/magicalSam/p/7161942.html
原理:通过自定义注解+Aspect技术实现AOP代理
- 通过@Aspect注解使该类成为切面类
- 通过@Pointcut 指定切入点 ,这里指定的切入点为MyLog注解类型,也就是被@MyLog注解修饰的方法,进入该切入点。
- @Before 前置通知:在某连接点之前执行的通知,但这个通知不能阻止连接点之前的执行流程(除非它抛出一个异常)。
- @Around 环绕通知:可以实现方法执行前后操作,需要在方法内执行point.proceed(); 并返回结果。
- @AfterReturning 后置通知:在某连接点正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。
- @AfterThrowing 异常通知:在方法抛出异常退出时执行的通知。
- @After 后置通知:在某连接点正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回
|