前面我们了解了 Spring 容器的刷新逻辑 和 xml的配置全链路解析 今天我们重点来看一下 注解方式的 bean 如何注册到 Spring 容器之中。
Configuration 注解启动分析
实例
创建一个注解方式的实体类
@Component
public class Device {
private String name = "device";
}
使用注解配置方式启动:
ApplicationContext context1 = new AnnotationConfigApplicationContext(Device.class);
Device bean = context1.getBean(Device.class);
System.out.println(bean);
我们看一下输出结果:
13:56:52.981 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@dcf3e99
13:56:53.004 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
13:56:53.060 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
13:56:53.063 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
13:56:53.065 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
13:56:53.066 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
13:56:53.077 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'device'
com.mrlsm.spring.demo.entity.Device@2bea5ab4
运行成功,说明 Device 类使用注解被 Spring 容器所管理了。
接下来我们之间分析一下 AnnotationConfigApplicationContext 支持 Configuration 注解启动 spring 容器的原理。
一、AnnotationConfigApplicationContext
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
//调用默认无参构造器,主要初始化 AnnotatedBeanDefinitionReader
// 以及路径扫描器 ClassPathBeanDefinitionScanner
this();
//把传入的 Class 进行注册, Class 既可以有 @Configuration注解,也可以没有 @Configuration注解
//如何注册委托给了 org.springframework.context.annotation.AnnotatedBeanDefinitionReader.register 方法进行注册
// 包装传入的 Class 生成 BeanDefinition , 注册到 BeanDefinitionRegistry
register(componentClasses);
refresh();
}
我们查看下本身的构造方法:
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
初始化了一个 BeanDefinitionReader 与 BeanDefinitionScanner 容器来为稍后通过调用其 register() 方法注册配置类,并调用 refresh() 方法刷新容器,触发容器对注解 Bean 的载入、解析和注册过程。
二、AnnotatedBeanDefinitionReader#doRegisterBean
看源码可以发现 AnnotatedBeanDefinitionReader#register 最终使用的为 doRegisterBean() 方法
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
//用于处理 Conditional 注解,在特定条件下阻断 bean 的注册
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
//用来创建 bean 的 supplier,会替代掉 bean 本身的创建方法
//instanceSupplier 一般情况下为 null
abd.setInstanceSupplier(supplier);
//此行代码处理 scope 注解,本例中 scope 是默认值 singleton
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
//获取beanName
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
//特定注解解析,本例中均没传入dependsOn,LazyInit这些注解
//这些注解就和<bean>标签里面的属性作用是一样的
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
//本例中 qualifiers 传入的是 null,qualifiers就是用来决定接口的实现类的
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
//主要提供对BeanDefinition的一些定制化操作
if (customizers != null) {
for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(abd);
}
}
// 用 BeanDefinitionHolder 包装 BeanDefinition
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
// 此行代码与动态代理和 scope 注解有关,主要看看是否依照 Spring 的 scope 生成动态代理对象
// 但是在本案例中没有做任何操作,只是返回了传入的 definitionHolder
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 向容器注册扫描到的 Bean
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
该方法主要就是使用 AnnotatedGenericBeanDefinition 对象将对应的 class 对象包装起来,之后主要是处理定义在类上的其他注解,解析属性并给实例赋值。 之后使用 BeanDefinitionHolder 包装 BeanDefinition,之后调用 AnnotationConfigUtils#applyScopedProxyMode 跟进可以发现最终调用的为 ScopedProxyUtils#createScopedProxy
三、ScopedProxyUtils#createScopedProxy
该方法主要是为提供的目标 bean 生成范围代理,使用内部名称注册目标 bean 并在范围代理上设置 "targetBeanName"。
public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
BeanDefinitionRegistry registry, boolean proxyTargetClass) {
String originalBeanName = definition.getBeanName();
BeanDefinition targetDefinition = definition.getBeanDefinition();
String targetBeanName = getTargetBeanName(originalBeanName);
// 为原始 bean 名称创建范围代理定义,
// 在内部目标定义中“隐藏”目标 bean.
RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName));
proxyDefinition.setOriginatingBeanDefinition(targetDefinition);
proxyDefinition.setSource(definition.getSource());
proxyDefinition.setRole(targetDefinition.getRole());
proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
if (proxyTargetClass) {
targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
// ScopedProxyFactoryBean 的“proxyTargetClass”默认为 TRUE,所以我们不需要在这里明确设置它。
} else {
proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
}
// 从原始 bean 定义复制自动装配设置。
proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
proxyDefinition.setPrimary(targetDefinition.isPrimary());
if (targetDefinition instanceof AbstractBeanDefinition) {
proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
}
// 应该忽略目标 bean 以支持范围代理。
targetDefinition.setAutowireCandidate(false);
targetDefinition.setPrimary(false);
// 在工厂中将目标 bean 注册为单独的 bean。
registry.registerBeanDefinition(targetBeanName, targetDefinition);
// 将作用域代理定义作为主 bean 定义返回
// (potentially an inner bean).
return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
}
完成上述操作后,AnnotatedBeanDefinitionReader#doRegisterBean 方法最后就是向容器注册扫描到的 Bean 也就是调用 BeanDefinitionReaderUtils#registerBeanDefinition 方法。 看到这,是不是感觉熟悉,没错和 xml 配置的解析 一样调用到 BeanDefinitionReaderUtils#registerBeanDefinition 方法将 beanDefinition 注册到 DefaultListableBeanFactory 实例里面。
普通注解启动分析
那么对于普通注解的 bean 呢? 我们对 main 方法做下修改:将 Device 不作为直接参数传入 AnnotationConfigApplicationContext
ApplicationContext context = new AnnotationConfigApplicationContext(DemoApplication.class);
Device bean = context.getBean(Device.class);
System.out.println(bean);
此时我们运行成功后,我们对 DefaultListableBeanFactory#registerBeanDefinition 中打上断点观察:
看他的调用栈,发现执行到 refresh 方法后才将 BeanDefinition 注册到 DefaultListableBeanFactory 实例里面。 好,看调用栈跟进 PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors 方法 我们跟进该方法:
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// 如果有 BeanDefinitionRegistryPostProcessor 的话优先执行
Set<String> processedBeans = new HashSet<>();
// 如果是 BeanDefinitionRegistry 类型的话
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 用于记录常规 BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
// 用于记录 BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 遍历所有参数传递进来的 BeanFactoryPostProcessor (它们并没有作为 bean 注册在容器中)
// 将所有参数传入的 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);
}
}
// 用于记录当前正要被执行的 BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 首先,对实现了优先级顺序接口的 Bean 形式的 BeanDefinitionRegistryPostProcessor 进行调用
// 找出所有容器中注册为 BeanDefinitionRegistryPostProcessor 的 postProcessor 名字数组
// 注意,这里不会直接实例化这个 bean(主要是这些 PostProcessor 需要按顺序初始化和调用,先调用的 PostProcessor 是可能对后初始化的 bean 造成影响的)
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 遍历容器,将 BeanDefinitionRegistryPostProcessor 类型的后置处理器 Bean 实例给添加到当前的注册处理器中
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 根据优先级排序 对所有实现了 PriorityOrdered 接口的 PostProcessor 排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 加入 registryProcessors 列表
registryProcessors.addAll(currentRegistryProcessors);
// 调用 BeanDefinitionRegistryPostProcessor 的方法,ConfigurationClassPostProcessor 的逻辑就是在这里被调用的
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 清除 currentRegistryProcessors
currentRegistryProcessors.clear();
// 其次对实现了 Ordered 接口的 BeanDefinitionRegistryPostProcessors 进行调用
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 按照 Order 排序 与 上方方法类似
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 接下来处理普通的,没实现排序接口的 BeanDefinitionRegistryPostProcessor
// 需要主要的是,这里有一个循环,主要原因是 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry 方法是传入了一个 BeanDefinitionRegistry 的实例
// 这意味着我们可以在(实际上正常实现这个接口就是为了注册 beanDefinition 的)这个 PostProcessor 注册新的 beanDefinition
// 而新注册的 beanDefinition 对应的类也是可能实现 BeanDefinitionRegistryPostProcessor 接口的,所以这里需要循环处理,直到不会注册新的 BeanDefinitionRegistryPostProcessor 为止
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// 因为 BeanDefinitionRegistryPostProcessor 继承自 BeanFactoryPostProcessor,所以这里
// 也对所有 BeanDefinitionRegistryPostProcessor 调用其方法 postProcessBeanFactory()
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// 对所有常规 BeanFactoryPostProcessor 调用其方法 postProcessBeanFactory()
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
//如果都是常规的 BeanFactoryPostProcessor,则调用其方法 postProcessBeanFactory()
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 上面逻辑执行了以参数形式传入的 BeanDefinitionRegistryPostProcessor 以及常规的 BeanFactoryPostProcessor
// 也执行了容器里面的 BeanDefinitionRegistryPostProcessor,故还剩下容器里面的 BeanFactoryPostProcessor 需要去处理
// 逻辑是一样的,也分为实现了 PriorityOrdered和Ordered 以及两个都没实现的 postProcessor
// ···
}
该方法很长,但是主要逻辑类似,主要是分情况处理不同类型的 BeanFactoryPostProcessors。
- BeanFacotryPostProcessors 主要分为两类,一类是 BeanDefinitionRegistry 的 BeanFactoryPostProcessor,另外一类是常规的 BeanFactoryPostProcessor。优先处理前者。
- 同时,这两种后置处理器又被分为从参数里传入和从容器里获取的,最终要将从参数里获取的和从容器里获取的合并在一起。合并的时候又分为实现了PriorityOrder和普通Order以及没有实现这两个接口的,实现了 PriorityOrdered 的先执行。
- 同时是按照PriorityOrdered顺序执行的,其次再到 Order,按照 Order 执行,最后才是没实现这两个接口的。
- 先执行完 BeanDefinitionRegistryPostProcessor 的 invokeBeanDefinitionRegistryPostProcessors 方法,再对 BeanDefinitionRegistryPostProcessor 执行 invokeBeanFactoryPostProcessors 方法, 之后再对常规的 BeanFacotryPostProcessors 执行 invokeBeanFactoryPostProcessors 方法。
我们可以看下里面的 invokeBeanDefinitionRegistryPostProcessors 和 invokeBeanFactoryPostProcessors 方法,具体是怎么实现的。
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
}
可以明确的看出,就是一个简单的循环调用。
总结
这篇我们主要分析了注解配置全链路分析,与上一篇 xml的配置全链路解析 有相同的部分,Spring 容器都是在 refresh 方法中完成对 bean 的注册。
本文基于 spring-framework 5.2.10.RELEASE 版本进行分析