1)入口是初始化 ApplicationContext 中的 initializeBean() 对 bean 进行初始化,在 initializeBean() 中会走到 后置处理器 BeanPostProcessor。
注:initializeBean() 位于 createBeanInstance() 创建 bean 实例和 populateBean() 依赖注入 之后
-
创建封装了配置信息的 AopConfig(切点表达式、切面类、前置/后置/环绕通知)
-
将 AopConfig 再封装成 AdvisedSupport(包括了上面的配置文件信息,目标类,被代理对象)
-
在调用 AdvisedSupport#setTargetClass() 保存目标类信息时,会调用自己的 parse() 方法
- 根据切点表达式,提取并构造目标类特征表达式
- 获取切面类的所有方法(LogAspect)并遍历,将通知方法保存
- 获取目标类所有方法并遍历,寻找符合切点表达式的切入点方法,按照 befor/after/throw 的顺序(从上面保存的通知方法中取出相应方法),为该切入点构造拦截器链
List<Object> advices - 将所有符合的方法及他们的拦截器链,保存到 AdvisedSupport 的
Map<Method, List<Object>> methodCache中
上面创建的拦截器实例是 MethodBeforeAdviceInterceptor/AfterReturningAdviceInterceptor 等,它们继承了 AbstractAspectAdvice 抽象类,实现了 MethodInterceptor 接口,表示有两种不同作用
- AbstractAspectAdvice:实现了 Advice 接口,封装了通知方法、切面实例,以及当前拦截器的执行逻辑 invokeAdviceMethod();表示该类是个通知类
- MethodInvocation 接口:拦截器链统一接口;表示通知类的组织方式是拦截器链(按照before/after排序)
-
还是在 initializeBean() 方法中,根据提取的目标类特征,判断该目标类是否符合;如果符合,就通过 JDK 动态代理,为该目标类创建一个新的代理对象,然后放入缓存容器(singletonObjects)
注意:创建代理对象时,如果没有目标类没有接口就得使用 Cglib 代理了
2)对于被代理对象,当有请求到来,要执行某个某个方法时,就会走到动态代理 JdkDynamicAopProxy 的 invoke() 方法
-
通过 AdvisedSupport 获取该方法的执行器链
List<Object> interceptorsAndDynamicMethodMatchers -
通过拦截器链、代理对象实例等,构造 MethodInvocation (拦截器链执行器)。MethodInvocation 实现了 MYJoinPoint 接口,封装了拦截器链执行逻辑 proceed()
-
调用 proceed() 方法,它会不断按顺序执行 MethodBeforeAdviceInterceptor/AfterReturningAdviceInterceptor 等封装的方法,并将结果返回
注意:proceed() 方法并不是通过遍历 List 来执行所有通知方法的,而是通过递归(自顶向下)






还没有评论,来说两句吧...