3、SpringBoot解析启动类之初始化自动装配类的BeanDefinitions

通过SpringBoot之Spi机制加载Spring.factories 、SpringBoot之解析启动类源码分析已经得到IOC容器中所有的类的相关信息。

对于用户自定义的类在解析启动类扫描包路径下的过程中就已经完成其AnnotatedGenericBeanDefinition类型的BeanDefinitions的初始化。

public class ConfigurationClassPostProcessor{
	public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
		...
        ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator,     
                registry);
		do {
	        //ConfigurationClassParser#parse
			parser.parse(candidates);
			parser.validate();
			...
		}
        ...
        this.reader.loadBeanDefinitions(configClasses);
		while (!candidates.isEmpty());
	}
}
其实就是触发spring.factories文件中自动装配候选类【包含其利用@Bean、@Import等注解再次间接引入的候选类】对应的其BeanDefinitions的初始化,具体如下:
class ConfigurationClassBeanDefinitionReader {

	public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
		TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
		for (ConfigurationClass configClass : configurationModel) {
			loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
		}
	}

	private void loadBeanDefinitionsForConfigurationClass(
			ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {

		if (trackedConditionEvaluator.shouldSkip(configClass)) {
			String beanName = configClass.getBeanName();
			if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
				this.registry.removeBeanDefinition(beanName);
			}
			this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
			return;
		}

		if (configClass.isImported()) {
			registerBeanDefinitionForImportedConfigurationClass(configClass);
		}
		for (BeanMethod beanMethod : configClass.getBeanMethods()) {
			loadBeanDefinitionsForBeanMethod(beanMethod);
		}

		loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
		loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
	}
}
主要包括四种方式:
  1. 当前候选类是否被其他类通过@Import注解引入的。绝大部分的候选类满足。
  2. 当前候选类中利用@Bean注解引入的候选类。
  3. 当前候选类通过@Import注解引入ImportBeanDefinitionRegistrar类型的候选类。

1.处理ImportBeanDefinitionRegistrar类型的候选类

private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
    registrars.forEach((registrar, metadata) ->
		registrar.registerBeanDefinitions(metadata, this.registry));
}

参考@MapperScan引入的MapperScannerRegistrar。


2.处理候选类Bean注解引入的bean信息

private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
	ConfigurationClass configClass = beanMethod.getConfigurationClass();
	MethodMetadata metadata = beanMethod.getMetadata();
	String methodName = metadata.getMethodName();

	// 解析当前方法存在的相关Conditional相关的注解
	if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
		configClass.skippedBeanMethods.add(methodName);
		return;
	}
	if (configClass.skippedBeanMethods.contains(methodName)) {
		return;
	}

	...

	ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
	beanDef.setResource(configClass.getResource());
	beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));

	if (metadata.isStatic()) {
		// static @Bean method
		if (configClass.getMetadata() instanceof StandardAnnotationMetadata) {
			beanDef.setBeanClass(((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass());
		}
		else {
			beanDef.setBeanClassName(configClass.getMetadata().getClassName());
		}
		beanDef.setUniqueFactoryMethodName(methodName);
	}
	else {
		// instance @Bean method
		beanDef.setFactoryBeanName(configClass.getBeanName());
		beanDef.setUniqueFactoryMethodName(methodName);
	}

	if (metadata instanceof StandardMethodMetadata) {
		beanDef.setResolvedFactoryMethod(((StandardMethodMetadata) metadata).getIntrospectedMethod());
	}

	...
	AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);

	Autowire autowire = bean.getEnum("autowire");
	if (autowire.isAutowire()) {
		beanDef.setAutowireMode(autowire.value());
	}

	boolean autowireCandidate = bean.getBoolean("autowireCandidate");
	if (!autowireCandidate) {
		beanDef.setAutowireCandidate(false);
	}

	String initMethodName = bean.getString("initMethod");
	if (StringUtils.hasText(initMethodName)) {
		beanDef.setInitMethodName(initMethodName);
	}

	String destroyMethodName = bean.getString("destroyMethod");
	beanDef.setDestroyMethodName(destroyMethodName);

	...
    // 如果@Bean注解的方法满足条件,则将对应bean的定义信息添加到beanDefinitionMap
	this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}

3.BeanDefinition相关概念

BeanDefinition 描述了一个 bean 实例,它记录了bean的属性值、构造函数参数值以及其他更多信息。BeanDefinition在Spring 管理bean中至关重要,指导了Spring 如何依据BeanDefinition生成Bean,bean的作用域,是否懒加载等等。

BeanDefinition中具有设置和获取 此bean 定义的父BeanDefinition的名称(如果有),bean 类名,Bean的作用域,Bean是否懒加载,当前bean依赖的bean名称,是否Autowire候选者,是否是最主要的自动装配候选者,初始化方法名称,销毁方法名称,是否单例,是否原型,bean属性值。

传统的基于XML Spring 容器便是使用对于的BeanDefinitionReader解析XML将xml中的信息包装成BeanDefinition保存到Spring容器中,后续由Spring容器根据BeanDefinition对Bean进行管理。

BeanDefinitionReader:Bean定义信息读取器。BeanDefinitionReader的典型实现莫过于XmlBeanDefinitionReader,它负责解析xml生成BeanDefinition并注册。

BeanDefinitionRegistry:Bean定义注册中心,主要是对BeanDefinition的增删改查,自然内部会对BeanDefinition信息进行存储。

通常情况下使用BeanDefinitionBuilder完成BeanDegination接口相关子类的创建。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值