spring AOP简版

梳理AOP核心脉络

  1. 生成代理对象
    目标对象实现了接口,则默认采用JDK动态代理
    目标对象没有实现接口,则使用Cglib代理
    doCreateBean 的初始化 bean 的地方,就是在这个 initializeBean 方法中,生成并返回代理对象的
    applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    invokeInitMethods(beanName, wrappedBean, mbd);
    applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    生成代理对象就是在这个 afterInitialization 中做的,
    循环遍历所有 BeanPostProcessor,调用它的 postProcessAfterInitialization
    一路点进入AbstractAutoProxyCreator. wrapIfNecessary 发现
    Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
    proxyFactory.getProxy(classLoader);
    createAopProxy().getProxy(classLoader);
    首先是获取 AopProxy 对象,发现默认使用的是 cglib 代理
    接下来就是调用 AopProxy 类的 getProxy 获取代理类

一步步返回,exposedObject 就是代理类
如果有循环依赖,会触发getSingleton,此时在缓存中查询不到,方法结束
回到 doCreateBean,返回exposedObject ,回到那个带回调函数的 getSingleton 方法中会将当前的代理对象放入缓存, 此时单例缓存池中就真正存放的是一个 cglib 代理对象

  1. 使用代理对象来调用方法

调用目标方法,发现进入的是 cglib 的代理类 ,会先获取拦截器链,就是在 LogAspect 类中前置和后置通知对应的拦截器。

首先进入 advised.getInterceptorsAndDynamicInterceptionAdvice 方法
首先获取 advice 适配器,用来将我们定义的 advice 转换成 intercepter
然后获取所有的通知,就是在 LogAspect 中配置的前置和后置通知
然后遍历上面获取的所有通知, 判断当前调用的方法,是否跟 pointcut 的 execution 表达式匹配

当确定当前调用的方法需要被拦截时,将 advice 转化为 intercepter ,这个 advice 就是 before 和 after 通知
之后将拦截器放入拦截器链。

然后 获取了拦截器链后,就真正开始执行拦截器中的方法,并调用目标方法
首先创建一个 CglibMethodInvocation,然后调用 proceed,实际调用的是它的父类 ReflectiveMethodInvocation 中的 proceed

proceed有个判断:调用的是拦截器,还是目标方法
currentInterceptorIndex(初始为 -1) 是否等于 interceptorsAndDynamicMethodMatchers 的 (size - 1)

循环这个 interceptorsAndDynamicMethodMatchers,一次调用拦截器的 invoke 方法
比如当前是 MethodBeforeAdviceInterceptor, 进入它的 invoke 方法查看。它在调用目标方法之前,首先调用了拦截器中的方法, 具体是在这个 advice.before 方法中调用, 执行完前置通知后,继续调用 proceed 方法,重新进入前面 proceed 方法
然后执行目标方法 , 调用后置方法 invokeAdviceMethod
到这里为止,一个拦截方法的流程就全部走完了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值