一、Springboot AOP自动装配原理
- 了解Springboot自动装配原理的同学一定会知道,Springboot在启动容器的时候会去扫描所有jar包类路径下 META‐INF/spring.factories 文件,然后会把把扫描到的这些文件的内容包装成properties对象,从properties中获取到EnableAutoConfiguration类对应的值,然后把他们添加到Spring容器中【不了解也没关系,后续博客会陆续更新Springboot自动配置相关的知识】。
- 本次AOP源码分析我使用的Springboot版本是2.1.3.RELEASE,需要看源码的同学请到上一篇博客【Spring AOP源码分析(一)】中获取。下面我们来看一下Springboot自动装配文件中装载的信息。
- 根据自动装配文件中配置的数据,我们可以很清楚的看到Spring AOP的自动装配类为AopAutoConfiguration,其源码如下:
@Configuration
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class, AnnotatedElement.class })
/**
* prefix:配置文件中的前缀
* name:配置的名字
* havingValue:havingValue是与配置的值对比值,当两个值相同返回true,配置类生效。
* matchIfMissing:matchIfMissing = true表示如果没有在application.properties设置该属性,则默认为条件符合
*/
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {
// AOP动态代理---》JDK动态代理方式(需要有接口方式进行代理)
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
public static class JdkDynamicAutoProxyConfiguration {}
// AOP动态代理---》Cglib代理方式(不需要接口,以子类方式,但是无法代理final方法),根据@ConditionalOnProperty注解
// 可以看出,Spring自动配置AOP时默认采用Cglib的方式代理
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
public static class CglibAutoProxyConfiguration {}
}
- @Configuration 说明这是一个配置类
- @ConditionalOnClass 当前classpath下面,有EnableAspectJAutoProxy、Aspect、Advice、AnnotatedElement 这几个类才会去加载该类,通俗说就是有spring-aop 依赖才会加载。
- @ConditionalOnProperty 在上一步的基础上,再一步对配置进行条件判断,即判断是否有spring.aop.auto=true 配置,若有则开启配置(设置为false会关闭自动配置)。matchIfMissing = true表示,如果没有在application.yml设置该属性,则默认为条件符合。
- 配置类中的两个子配置类JdkDynamicAutoProxyConfiguration 、CglibAutoProxyConfiguration 为SpringAop的两种代理方式,根据其标注的@ConditionalOnProperty注解信息可以看出,如果Spring没有显示的在application.yml中指定那种代理方式时,系统会默认采用Cglib代理的方式。
二、AOP核心组件注册原理
- EnableAspectJAutoProxy 这个注解是AopAutoConfiguration 的两个子配置类共有的注解(Spring注册子配置类时会注册这个注解)。这个注解除了两个属性外,还使用了@Import注解向容器中引入了AspectJAutoProxyRegistrar 类,这个类实现了ImportBeanDefinitionRegistrar接口,然后通过这个接口向Spring容器中注册了AnnotationAwareAspectJAutoProxyCreator 类的BeanDefinition信息(Spring容器刷新的时候会根据BeanDefinition创建对应的类),这个类接下来将是我们研究的重点了,我们先来看一下这个类是怎么通过EnableAspectJAutoProxy注解注册到Spring容器中的。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
// 使用@Import注解注册AspectJAutoProxyRegistrar类
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
- AspectJAutoProxyRegistrar类
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 向容器中注册AnnotationAwareAspectJAutoProxyCreator的BeanDefinetion信息
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
// 获取@EnableAspectJAutoProxy注解的属性信息
AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
// 如果proxyTargetClass属性为true,强制使用Cglib代理模式
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
- AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary()
.....AopConfigUtils类.....
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 返回注册AnnotationAwareAspectJAutoProxyCreator的BeanDefinition对象
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
// BeanDefinitionRegistry中是否已经注册了该组件,初始化时显然这里是没有创建的
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
// 将传入的AnnotationAwareAspectJAutoProxyCreator封装为beanDefinition,Spring容器初始化的时候会装载该组件
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
// 设置优先级
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 定义AnnotationAwareAspectJAutoProxyCreator组件在Spring容器中的别名
// 我们可以通过这个名字从Spring容器中获取该组件,类似于xml配置中指定的标签id
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
到这里我们已经知道了AnnotationAwareAspectJAutoProxyCreator的BeanDefinition信息是如何被注册到Spring容器中的了,其实大家还是会对AspectJAutoProxyRegistrar类的加载时机存在疑问的,那接下来我们大致的分析一下AspectJAutoProxyRegistrar的加载流程。
- 首先我们进入到Spring Ioc容器启动的核心方法AbstractApplicationContext#refresh()方法,其定义如下:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 记录容器的启动时间、标记“已启动”状态、检查环境变量
prepareRefresh();
// 初始化BeanFactory容器(DefaultListableBeanFactory)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
prepareBeanFactory(beanFactory);
try {
// 扩展点,具体逻辑由子类去实现
postProcessBeanFactory(beanFactory);
// 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
invokeBeanFactoryPostProcessors(beanFactory);
// 注册 BeanPostProcessor 的实现类
registerBeanPostProcessors(beanFactory);
// 初始化MessageSource
initMessageSource();
// 初始化事件广播器
initApplicationEventMulticaster();
// 扩展点,交由子类实现
onRefresh();
// 注册事件监听器
registerListeners();
// 初始化所有的 singleton beans
finishBeanFactoryInitialization(beanFactory);
// 广播事件
finishRefresh();
}catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 销毁已经初始化的的Bean
destroyBeans();
// 设置 'active' 状态
cancelRefresh(ex);
throw ex;
}finally {
// 清除缓存
resetCommonCaches();
}
}
}
- 这里我们重点关注invokeBeanFactoryPostProcessors(beanFactory)方法,该方法会调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法;这其中包含了一个重要的后置处理器ConfigurationClassPostProcessor,这个后置处理器会解析加了@Configuration的配置类,还会解析@ComponentScan、@ComponentScans注解扫描的包,以及解析@Import等注解。在我们前面的分析中,我们可以清晰的看到AspectJAutoProxyRegistrar类是通过@Import注解导入的,那我们通过源码来分析一下流程吧。
refresh()#invokeBeanFactoryPostProcessors方法
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 调用并执行实现了BeanFactoryPostProcessor接口的子类的postProcessBeanFactory(factory)方法
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
这里我们要详细的看一下invokeBeanFactoryPostProcessors()方法的执行,该方法会调用ConfigurationClassPostProcessor类后置处理方法,后置处理方法会去解析并调用AspectJAutoProxyRegistrar类,并将AnnotationAwareAspectJAutoProxyCreator的BeanDefinition信息注册到容器中。接下来我们看一下ConfigurationClassPostProcessor后置处理器的继承关系图:
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
Set<String> processedBeans = new HashSet<>();
// 首先执行实现了BeanDefinitionRegistryPostProcessors后置处理器的组件
if (beanFactory instanceof BeanDefinitionRegistry) {
// BeanDefinition注册管理器,托管了所有的BeanDefinition信息
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 保存常规BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
// 保存BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
/**
* 遍历所有传进来的BeanFactoryPostProcessor,并其将分成两组 :
* BeanDefinitionRegistryPostProcessor 和常规 BeanFactoryPostProcessor
* 1.如果是BeanDefinitionRegistryPostProcessor,现在执行postProcessBeanDefinitionRegistry(),
* 2.否则记录为一个常规 BeanFactoryPostProcessor,现在不执行处理
*/
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
} else {
regularPostProcessors.add(postProcessor);
}
}
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 从BeanFactory中获取实现了BeanDefinitionRegistryPostProcessor接口的组件,这里我们关心的是ConfigurationClassPostProcessor
// ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor接口
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 根据是否实现了PriorityOrdered、Ordered接口进行排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 执行后置处理器的后置处理方法,接下来我们重点分析这个方法的调用链
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
......省略非必要代码.........
}
}
/**
* Invoke the given BeanDefinitionRegistryPostProcessor beans.
*/
private static void invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
// 调用实现类的postProcessBeanDefinitionRegistry后置处理方法,最终调用到
// AspectJAutoProxyRegistrar的registerBeanDefinitions方法,实现AOP相关的组件注册,具体的细节就交由各个同学自己去分析了
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
到这里我们的组件就完成了,接下来我们将会去分析AnnotationAwareAspectJAutoProxyCreator类怎样去增强我们需要增强的类,谢谢大家的观看。