您现在的位置是:首页 >其他 >Spring Bean的顺序网站首页其他

Spring Bean的顺序

小杨的博客 2023-06-16 00:00:03
简介Spring Bean的顺序

之前的文章已经讲过,Spring Bean的创建是通过动态代理实现的,防止浪费篇幅,我们直接看Bean的循环创建代码;

这里我们可以看到 Bean 的创建是通过:

List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
for (String beanName : beanNames) {
    // Create Bean Code....
}

Bean的创建顺序其实就是this.beanDefinitionNames的顺序。

可以看出this.beanDefinitionNames又是List<?>类型,所以顺序源自add(obj)的顺序。那this.beanDefinitionNames又是怎么填充的呢?

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {
    // 省略部分代码,直接进入BeanName的add过程.....
    else {
    	if (hasBeanCreationStarted()) {
    		// Cannot modify startup-time collection elements anymore (for stable iteration)
    		synchronized (this.beanDefinitionMap) {
    			this.beanDefinitionMap.put(beanName, beanDefinition);
    			List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
    			updatedDefinitions.addAll(this.beanDefinitionNames);
    			updatedDefinitions.add(beanName);
    			this.beanDefinitionNames = updatedDefinitions;
    			removeManualSingletonName(beanName);
    		}
    	}
    	else {
    		// Still in startup registration phase
    		this.beanDefinitionMap.put(beanName, beanDefinition);
    		this.beanDefinitionNames.add(beanName);
    		removeManualSingletonName(beanName);
    	}
    	this.frozenBeanDefinitionNames = null;
    }
    // 省略后续代码...
    
}

再追溯一下org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinitionorg.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForBeanMethod中使用到

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

private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
	// 省略....
	for (BeanMethod beanMethod : configClass.getBeanMethods()) {
		loadBeanDefinitionsForBeanMethod(beanMethod);
	}
    // 省略....
}

private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
    // 省略...
    this.registry.registerBeanDefinition(beanName, beanDefToRegister);
    // 省略...
}

继续向下找到具体的地方:

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    // 省略部分代码..
	processConfigBeanDefinitions(registry);
}

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    // 省略部分代码....    
    // Parse each @Configuration class
	ConfigurationClassParser parser = new ConfigurationClassParser(
	    this.metadataReaderFactory, this.problemReporter, this.environment,
		this.resourceLoader, this.componentScanBeanNameGenerator, registry);

    do {
        parser.parse(candidates);
        parser.validate();
        Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
        configClasses.removeAll(alreadyParsed);
        // Read the model and create bean definitions based on its content
        if (this.reader == null) {
            this.reader = new ConfigurationClassBeanDefinitionReader(
                registry, this.sourceExtractor, this.resourceLoader, this.environment,
                this.importBeanNameGenerator, parser.getImportRegistry());
        }
        this.reader.loadBeanDefinitions(configClasses);
        // 省略部分代码...
    }
    while (!candidates.isEmpty());
    // 省略部分代码...
}

至此,我们基本可以看出来,BeanNames的顺序是由org.springframework.context.annotation.ConfigurationClassPostProcessor决定的,而ConfigurationClassPostProcessor由实现了BeanDefinitionRegistryPostProcessor,其核心就是将代码中注册@Configuration注解的类以及经由此配置类注册的Bean解析为BeanDefinition,而这一步是在refresh()invokeBeanFactoryPostProcessors(beanFactory);完成的。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。