SpringAOP实现:(一)横切逻辑的加载与解析

横切逻辑的加载与解析:

  即Aspect和Advice的加载阶段,在后续创建动态代理的时候, 根据之前开发自研框架AOP的经验,需要拿着所有的Aspect去尝试与容器的业务Bean去做匹配,只有匹配的Aspect才会去创建对应的动态代理,SpringAOP也不例外。

  而进行匹配前势必要把IOC容器所有的Aspect和对应的Advice都加载好并缓存起来,随后才可以遍历所有的横切逻辑去做相关的匹配工作。

 

 

 

 

 

 

 TargetSource:

 

TargetSource关系图:

 

 

首先可以看到TargetSource类实现了TargetClassAware接口,使之能够获取到对象实例。

SingletonTargetSource:用来确保被代理的实例是单例的。被代理的对象会被缓存到Object类型的target成员变量中。

PrototypeTargetSource:被代理的实例是多例的。

 

 

AbstractAutoProxyCreator:

  横切逻辑的加载主要是在postProcessBeforeInstantiation方法中。该方法的调用时机是在bean的实例化之前调用的(详细可打上断点debug查看)

 

AbstractAutoProxyCreator.postProcessBeforeInstantiation():

  方法是针对容器里的每个bean都会执行的,会去判断bean是否是Aspect。为了防止重复执行Aspect的加载,一般情况下都会引入缓存。缓存一般就是通过键位来定位到对应的缓存,这里也不例外。

  (1)计算出键位来,调用了getCacheKey()方法去获取缓存里的key

  (2)查看传入的beanName为空 || targetSourcedBeans不包含beanName则进入if(这里的targetSourcedBeans是类内部的缓存,只提供类自己使用)

      (A)判断如果beanName已经做过解析了则跳过

      (B)判断当前bean是基础类型  || shouldSkip()    shouldSkip()会调用findCandidateAdvisors()获取到容器中所有被@Aspect标记的bean然后逐一遍历如果是AspectJ的且名字跟我们传入的相符返回true

          findCandidateAdvisors()方法:当你在使用注解方式配置AOP的时候该方法使之能够支持对XML配置的AOP的支持的(会将从注解方式获取到的Advisor和父类中获取到的xml配置的Advisor合并在一起)(找到所有Advisor的实例Bean们)

          (a)调用父类的findCandidateAdvisors()从父类中获取Advisors

          (b)调用成员变量aspectJAdvisorsBuilder的buildAspectJAdvisors()方法提取所有的Advisors然后跟(1)中获取的进行合并后返回所有的Advisors

           findCandidateAdvisors方法下的buildAspectJAdvisors方法执行流程

            (1)从容器获取所有的beanName(2)遍历beanName,解析出被@Aspect标记的类

            (3)提取Aspect类的Advisors(这里调用了getAdvisors()方法,该方法会对Aspect里的所有方法除了pointcut,进行顺序的排序)(4)将提取的结果加入缓存

               跟进到getAdvisors()方法中,该方法会对Aspect里的方法除了pointcut进行解析排序。

                 (A)获取到Aspect的类Class和类名字 (B)校验切面类  (C)创建出懒加载单例切面实例化工厂装饰者类  (D)获取到切面类中的所有方法(除@PointCut注解的方法) (排序过的) 

                 (E)对获取到的方法进行循环解析。循环解析的getAdvisor().getPointcut().AspectJExpressionPointcut类,该类中提供了对Class级别和Method的匹配支持

 

  (3)获取用户自定义的targetSource,如果存在则直接在对象实例化之前进行代理创建,避免了目标对象不必要的实例化(用户自定义的bean替代掉即将创建的bean)

     如果获取到了用户自定义的targetSource实例,那么会去走后续的AOP的创建动态代理流程:

      (A)获取到该bean对应的Advisors对象列表

      (B)调用createProxy()创建除代理实例后返回代理的对象

 

posted @ 2021-03-01 12:01  _kerry  阅读(275)  评论(0编辑  收藏  举报