spring 5、Aop原理
2019-11-11 14:08:47 0 举报
AI智能生成
aop原理
作者其他创作
大纲/内容
一. XMl解析
1.Advice构造参数的需要: 通知方法\ 通知实例\ pointcut
2. 对于Advice的构造参数中的通知方法\ 通知实例的 BeanDefinition, xml没有直接解析出, 对应解析出来的分别是 MethodLocationFactory和AspectInstanceFactory的类定义
MethodLocationFactory和AspectInstanceFactory与通知方法 和 通知实例的关系如图所示
3.xml中最终解析出来两个beandefinition,分别是advice和pointcut的类定义
xml解析示意图(advice\advice构造参数\ponitcut)
二.调用getBean()
1.在createBean的时候加入新方法, initializeBean(bd,bean), 目的是: (bean生命周期,初始化后做的事情) 这里是为了生成动态代理
2.initializeBean(bd,bean)方法, 首先, 为实现了BeanFactoryAware的类注册BeanFactory. 然后, 为非合成bean着手生成动态代理(调用applyBeanPostProcessorsAfterInitialization(bean,bd.getID())方法)
3.applyBeanPostProcessorsAfterInitialization(bean,bd.getID())方法, 拿到DefaultBeanFactory中的 List<BeanPostProcessor> beanPostProcessors, 并对beanPostProcessors进行遍历. 调用每个BeanPostProcessor的afterInitialization(existingBean, beanName)方法
4.插播: 为了实现3步骤, 也就是为了BeanFacotry中能够有生成动态代理功能的BeanPostProcessor存在, 在初始化ApplicationContext, 调用 registerBeanPostProcessors来注册BeanPostProcessor的时候, 要加入生成动态代理功能的BeanPostProcessor----AspectJAutoProxyCreator
5.调用AspectJAutoProxyCreator的afterInitialization(Object bean, String beanName),创建动态代理并返回
(1) getCandidateAdvices(bean)方法, 通过BeanFactory的getBeansByType方法获取到所有的符合条件的Advice的实例, --- 首先在BeanFactory中注册的Advice类的beanId, 遍历这些beanId, 调用getBean(beanId)方法, 生成Advice的实例的List列表. 遍历得到的Advice列表, 利用pointcut筛选出当前bean包括的Advice的List, 最终返回.
在生成Advice实例的过程中, 因为从xml中解析出来的Advice的BeanDefinition中, 有构造参数. 所以, 要 利用BeanDefinitionValueResolver处理这些构造参数.
参数1: AspectJExpressionPointcut 是 从xml转换后是RuntimeReference类型. 利用BeanDefinitionValueResolver直接转换
参数2:MethodLocationFactory是从xml转换后是GenericBeanDefinition类型, 需要在BeanDefinitionValueResolver中加入转化BeanDefinition的能力,
(1)MethodLocationFactory继承了BeanFactoryAware方法, 所以在getBean中调用initializeBean(bd,bean)方法的时候, 会先为生成出来的bean注入BeanFactory, 在注入的时候, 会利用BeanFactory, 和methodName及target(xml解析出来放入的属性), 为method属性赋值.
(2)当前bean继承了FactoryBean接口, 所以在把其GenericBeanDefinition解析为bean之后, 还要调用其getObject()方法, 返回method
(1)MethodLocationFactory继承了BeanFactoryAware方法, 所以在getBean中调用initializeBean(bd,bean)方法的时候, 会先为生成出来的bean注入BeanFactory, 在注入的时候, 会利用BeanFactory, 和methodName及target(xml解析出来放入的属性), 为method属性赋值.
(2)当前bean继承了FactoryBean接口, 所以在把其GenericBeanDefinition解析为bean之后, 还要调用其getObject()方法, 返回method
参数3:AspectInstanceFactory是从xml转换后也是GenericBeanDefinition类型, 它也继承了BeanFactoryAware方法, 所以在getBean中调用initializeBean()方法的时候, 也会为生成出来的bean注入BeanFactory.
(2)createProxy(advices,bean)方法, 查看当前bean的接口决定使用jdk动态代理还是cglib动态代理(这里仅仅实现了cglib动态代理)
当前类有实现接口的时候, 执行jdk动态代理
getProxy 创建动态代理,代码
其中getCallbacks(rootClass)方法为代理设置拦截器, (在执行代理类的方法的时候, 会走这些设置的拦截器, 拦截器内的逻辑在下一模块讲解)
当前类没有实现接口的时候, 执行cglib动态代理
getProxy 创建建动态代理,代码
JdkAopProxyFactory不仅实现了AopProxyFactory, 也实现了InvocationHandler. 所以需要实现invoke方法. 在创建动态代理(执行Proxy.newProxyInstance)的时候, 把JdkAopProxyFactory做为InvocationHandler的一个实例传入, 在调用动态代理的方法的时候, 就会执行JdkAopProxyFactory的invoke()方法. (同上, invoke的内在原理在下一模块中讲解)
三.调用创建了代理的类的方法
1.用户在通过代理类调用方法的时候, 自动进入该代理的拦截器,
*如果是cglib动态代理执行: DynamicAdvisedInterceptor类中的intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)方法,
*如果是jdk动态代理则执行: JdkAopProxyFactory类中的invoke()方法
他们要实现的目的是一致的
*如果是cglib动态代理执行: DynamicAdvisedInterceptor类中的intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)方法,
*如果是jdk动态代理则执行: JdkAopProxyFactory类中的invoke()方法
他们要实现的目的是一致的
1.intercept/invoke方法中, 先调用AopCOnfig的getAdvices(method)方法, 拿到当前要执行的方法, 对应的advice.(使用的是每个advice里面的pointcut对象)
2.intercept/invoke方法中, 创建ReflectiveMethodInvocation对象, 并调用其proceed()方法, 拦截器一个一个调用advice, advice根据自身的属性, 决定:
(1)先调用自己代表的通知方法-invokeAdviceMethod(),然后递归调用ReflectiveMethodInvocation的proceed方法()(beforeAdvice),
(2)还是先递归调用ReflectiveMethodInvocation的proceed方法(). 之后再调用自己代表的通知方法-invokeAdviceMethod()
(1)先调用自己代表的通知方法-invokeAdviceMethod(),然后递归调用ReflectiveMethodInvocation的proceed方法()(beforeAdvice),
(2)还是先递归调用ReflectiveMethodInvocation的proceed方法(). 之后再调用自己代表的通知方法-invokeAdviceMethod()
链式调用能够保证顺序原理:
* (1)只有最后一次递归调用, 才会进入执行目标方法
* 其他时候仅仅是去一个接着一个去调用拦截器
* (2)拦截器中如果执行了递归调用, 则自己会马上挂起, 知道所有拦截器都走完, 才会一个个的调用回来.
* (1)只有最后一次递归调用, 才会进入执行目标方法
* 其他时候仅仅是去一个接着一个去调用拦截器
* (2)拦截器中如果执行了递归调用, 则自己会马上挂起, 知道所有拦截器都走完, 才会一个个的调用回来.
AbstractAspectJAdvice implements Advice: 是一个抽象类, 里面写了继承它的advcie都要共同实现的方法
AspectJBeforeAdvice: 先调用自己代表的通知方法, 再递归调用proceed()
AspectJAfterThrowingAdvice, 直接递归调用proceed方法, 当proceed方法执行的过程中出现了异常, 被捕捉到, 回来调用自己代表的通知方法
AspectJAfterReturningAdvice: 先递归调用proceed()方法, 当proceed()方法全部走完, 进行返回后, 回来继续调用自己代表的通知方法
3.proceed方法在最后一次被adivce回调的时候, 会调用自己的invokeJoinpoint方法, 来执行真正想要执行的方法
2.涉及到的类关系图
动态代理调用期间涉及的类图
0 条评论
下一页