我们在写springboot项目时,@Controller、@Service、@Configuration、@Component注解的类是如何被扫描到的呢?本文将逐步揭开springboot组件扫描机制的面纱。
示例项目
先以一个demo展示一个普通的springboot项目在启动的过程中,注册了哪些bean。项目示例图如下:
代码github地址
主要看下自定义的bean工厂后置处理器类
@Component
public class CustomizedBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
System.out.println("自定义BeanFactoryPostProcessor查看已注册的beanDef");
for (String beanDef : beanDefinitionNames) {
System.out.println(beanDef);
}
System.out.println("beanDef共计" + beanDefinitionNames.length);
}
}
自定义bean工厂后置处理器的postProcessBeanFactory方法在abstractApplicationContext.refresh()====> PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory,beanFactoryPostProcessors)
处调用
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
......
// 一般地,自定义的BeanFactoryPostProcessor的重写方法会在此处调用
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
我们的自定义bean工厂后置处理器中的方法就是在invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory)
这里执行的。
需要注意的是,代码执行到此处时,我们demo示例中的bean已经全被注册。在日志中我们可以看到目前已经注册了哪些bean
自定义BeanFactoryPostProcessor查看已注册的beanDef
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
application
org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory
customizedBeanFactoryPostProcessor
appConfig
testController
staffService
testService
user
com.gsonkeno.springbootbean.bean.Staff
org.springframework.boot.autoconfigure.AutoConfigurationPackages
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
org.springframework.boot.autoconfigure.condition.BeanTypeRegistry
propertySourcesPlaceholderConfigurer
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration
mbeanExporter
objectNamingStrategy
mbeanServer
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration
springApplicationAdminRegistrar
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor
org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration
spring.info-org.springframework.boot.autoconfigure.info.ProjectInfoProperties
beanDef共计30
bean注册流程简析
abstractApplicationContext.refresh()
方法会去更新(刷新)context上下文,这其中就包括了bean的扫描注册。
refresh方法内部会调用invokeBeanFactoryPostProcessors(beanFactory)
方法,该方法会调用
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())
方法。
这里就要简短说明一下PostProcessorRegistrationDelegate这个类的作用,这是一个委托类,专门为AbstractApplicationContext类的xxxPostProcessorsxxx方法逻辑提供代理。
那么我们再次看下invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())
方法做了什么事?
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
// 1 如果beanFactory是BeanDefinitionRegistry类型,也就是关于bean注册的bean工厂时,
// 会进入该分支,进行bean的扫描、解析、注册
// SpringBoot启动时,beanFactory是DefaultListableBeanFactory类型,会进入该分支
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 1.1 这里分离出两种BeanFactoryPostProcessor,一种是关于bean注册的registryProcessors,
// 剩下的是另外一种正规的,regularPostProcessors
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 1.2 First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// 实现BeanDefinitionRegistryPostProcessors接口与PriorityOrdered接口的bean注册工厂后置处理器
// 先发挥作用,这里获取到的就是ConfigurationClassPostProcessor
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
//如果ppName实现了PriorityOrdered接口,则优先于Ordered接口处理
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 这里就是ConfigurationClassPostProcessor发挥作用解析配置类的时候
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 1.3 Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
//如果ppName实现了Ordered接口,则次于PriorityOrdered接口处理
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 1.4 Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
// 与上面类似,找到剩下的所有的BeanDefinitionRegistryPostProcessors,执行其重写方法 postProcessBeanDefinitionRegistry
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();
}
// 1.5 Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// 执行BeanFactoryPostProcessor接口的postProcessBeanFactory方法,执行该方法前,上下文中的
// bean应该都已经被加载,但是还未初始化,在这个方法中,你可以对这些bean增加或者重写属性
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
// 2
else {
// 2.1 Invoke factory processors registered with the context instance.
// 执行BeanFactoryPostProcessor接口的postProcessBeanFactory方法,执行该方法前,上下文中的
// bean应该都已经被加载,但是还未初始化,在这个方法中,你可以对这些bean增加或者重写属性
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 3 Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// 将还未处理的BeanFactoryPostProcessor分为三类,实现PriorityOrdered,Ordered接口的,和剩下的
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
// 一般地,自定义的BeanFactoryPostProcessor会在此处调用
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// 4 Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
这个方法主要做了以下几件事。
输入参数beanFactory, beanFactoryPostProcessors
- beanFactory属于BeanDefinitionRegistry类型
1.1 定义两种BeanFactoryPostProcessor,registryProcessors关于bean注册,regularPostProcessors属于正常规范类别。
1.2 实现BeanDefinitionRegistryPostProcessors接口与PriorityOrdered接口的bean注册工厂后置处理器ConfigurationClassPostProcessor先调用bean注册相关方法postProcessBeanDefinitionRegistry
1.3 实现BeanDefinitionRegistryPostProcessors接口与PriorityOrdered接口的bean注册工厂后置处理器同上
1.4 找到剩下的所有的BeanDefinitionRegistryPostProcessors,同上
1.5 registryProcessors,regularPostProcessors执行后置工厂方法postProcessBeanFactory - beanFactory属于BeanDefinitionRegistry类型
2.1 beanFactoryPostProcessors执行后置工厂方法postProcessBeanFactory - 将还未处理的BeanFactoryPostProcessor分为三类,实现PriorityOrdered,Ordered接口的,和剩下的。依次分别调用postProcessBeanFactory方法
- 清空beanfactory中对于bean的元数据缓存,因为自定义的post-processors可能会修改bean属性等信息。
回顾总结
这里我们可以提出几个问题自问自答。
-
我们自定义的一些组件,如加了@Controller注解的类是在哪里被扫描注册的?
invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())
方法的1.2
步获取到的bean工厂后置处理器ConfigurationClassPostProcessor会去解析注册用户自己写的bean。 -
我们自定义的BeanFactoryPostProcessor是在哪里调用它的重写方法的?
invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())
第一阶段处理BeanDefinitionRegistryPostProcessors类型的bean工厂后置处理器,
第二阶段处理剩下的bean工厂后置处理器。示例中的CustomizedBeanFactoryPostProcessor 属于第二阶段,
invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())
方法的第3
步的最后部分调用了CustomizedBeanFactoryPostProcessor
的重写方法。这个时候所有的bean都应该已经被注册了,但是还未实例化。
备注:下一篇将介绍ConfigurationClassPostProcessor
这个bean工厂后置处理器是如何解析注册bean的。