spring中的Aop是如何工作的?

467 阅读2分钟

1、切面实现的两种方式

1@Aspect注解模式
2、通过xml配置

1、入口spring.factories文件中的org.springframework.boot.autoconfigure.aop.AopAutoConfiguration

先解释两个
a、@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class,AnnotatedElement.class })
判断当前classpath下是否存在指定类,若存在则将当前的配置装载入spring容器,需要引入spring-context,aspectjweaver
b、@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
Application.properties中spring.aop.auto的值是否等于true,没有默认为true
c、@EnableAspectJAutoProxy(proxyTargetClass = false)使用JdkDynamicAutoProxyConfiguration@EnableAspectJAutoProxy(proxyTargetClass = true)使用CglibAutoProxyConfiguration@EnableAspectJAutoProxy默认值是false,所以默认使用JdkDynamicAutoProxyConfiguration
d、在EnableAspectJAutoProxy上有@Import(AspectJAutoProxyRegistrar.class),将AspectJAutoProxyRegistrar加入到容器中

企业微信20210322-171251.png

1、ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry调用了processConfigBeanDefinitions方法:
2、通过ConfigurationClassParser的parse方法,会将ImportBeanDefinitionRegistrar类型的bean加入到importBeanDefinitionRegistrars中;
3、ConfigurationClassBeanDefinitionReader的loadBeanDefinitionsForConfigurationClass方法-》loadBeanDefinitionsFromRegistrars方法;
4、AspectJAutoProxyRegistrar的registerBeanDefinitions方法;调用AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
5、调用registerOrEscalateApcAsRequired方法将AnnotationAwareAspectJAutoProxyCreator注册到容器;

企业微信20210322-174517.png

企业微信20210322-180041.png

AbstractAutoProxyCreator继承ProxyProcessorSupport,实现了SmartInstantiationAwareBeanPostProcessor;

通过registerBeanPostProcessors方法将所有的BeanPostProcessor类型的实例添加到beanPostProcessors;
SmartInstantiationAwareBeanPostProcessor中的方法:
    predictBeanType;重写
    determineCandidateConstructors
    getEarlyBeanReference重写
InstantiationAwareBeanPostProcessor中的方法:
    postProcessBeforeInstantiation重写
    postProcessAfterInstantiation
    postProcessPropertyValues
BeanPostProcessor中的方法:
    postProcessBeforeInitialization
    postProcessAfterInitialization重写

2、在创建bean的过程中doCreateBean方法中下面这段源码:

企业微信20210323-113219.png

企业微信20210323-113852.png AbstractAutoProxyCreator中实现了getEarlyBeanReference方法:

企业微信20210323-114011.png earlyProxyReferences这个map中缓存了早期代理的引用

企业微信20210323-140737.png targetSourcedBeans里如果包含这个bean,表示已经创建好了这个代理对象;

如果是基础设施的类或者原始的类,直接返回,并在第一次时缓存在advisedBeans中,value为false

通过AbstractAdvisorAutoProxyCreator的getAdvicesAndAdvisorsForBean方法获取到List

企业微信20210323-143412.png

WX20210323-143512.png findCandidateAdvisors()就是把当前容器中的所有的Advisor都创建好,过滤、排序等操作

下面就该创建一个Proxy了,首先构造一个ProxyFactory,创建AopProxy

企业微信20210323-153150.png 最终由要代理的类是不是接口类型或者Proxy决定用JDK的代理还是Cglib的

3、再说下@Aspect、@Pointcut、@Before等注解到底在哪里解析的?

企业微信20210323-172113.png

企业微信20210323-172415.png

企业微信20210323-172546.png

获取切面类下没有标@Pointcut注解的方法,并按特定的顺序排序

企业微信20210323-173632.png

获取切点表达式

企业微信20210323-174337.png

企业微信20210323-174100.png

WX20210323-174146.png

最后返回一个Advisor的实现InstantiationModelAwarePointcutAdvisorImpl

企业微信20210323-174925.png

在InstantiationModelAwarePointcutAdvisorImpl的都早函数中通过instantiateAdvice(this.declaredPointcut)方法去设置具体的Advice, 最终通过getAdvice方法实现

企业微信20210323-175505.png

4、下面就是创建Proxy的时候如何利用Aop增强的?分别在jdk代理和cglib中

企业微信20210324-101823.png

企业微信20210324-101928.png