Springboot的bean注册机制(一)

我们在写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

  1. 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
  2. beanFactory属于BeanDefinitionRegistry类型
    2.1 beanFactoryPostProcessors执行后置工厂方法postProcessBeanFactory
  3. 将还未处理的BeanFactoryPostProcessor分为三类,实现PriorityOrdered,Ordered接口的,和剩下的。依次分别调用postProcessBeanFactory方法
  4. 清空beanfactory中对于bean的元数据缓存,因为自定义的post-processors可能会修改bean属性等信息。
    在这里插入图片描述

回顾总结

这里我们可以提出几个问题自问自答。

  1. 我们自定义的一些组件,如加了@Controller注解的类是在哪里被扫描注册的?
    invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())方法的1.2步获取到的bean工厂后置处理器ConfigurationClassPostProcessor会去解析注册用户自己写的bean。

  2. 我们自定义的BeanFactoryPostProcessor是在哪里调用它的重写方法的?
    invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())
    第一阶段处理BeanDefinitionRegistryPostProcessors类型的bean工厂后置处理器,
    第二阶段处理剩下的bean工厂后置处理器。

    示例中的CustomizedBeanFactoryPostProcessor 属于第二阶段,invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())方法的第3步的最后部分调用了CustomizedBeanFactoryPostProcessor的重写方法。这个时候所有的bean都应该已经被注册了,但是还未实例化。

备注:下一篇将介绍ConfigurationClassPostProcessor这个bean工厂后置处理器是如何解析注册bean的。

  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值