SpringBoot自动装配源码
为什么要使用自动装配
为了简化配置,向SpringBoot问世前,一般都使用XML的方式来配置bean,而非常臃肿的配置文件,配置不方便。而SpringBoot提出了约定大于配置,所以通过约定大于配置的方式来加载不同的bean。
自动装配过程
加载BeanFactory后置处理器,createApplicationContext()方法,注册@Configuration、@Autowired等注解后置处理器到BeanFactory(beanDefinitionMap)
在run方法中,使用SpringApplication.createApplicationContext();方法注入,委派给AnnotatedBeanDefinitionReader构造器注入。
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
- 注册ConfigurationClassPostProcessor类(@Configuration后置处理器)
- 将ConfigurationClassPostProcessor类放到了beanDefinitionMap
代码
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
// BeanDefinition是bean定义,判断是否继承自AbstractBeanDefinition类
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
// beanDefinitionMap存放bean的容器、
// 先获取看是否已经存在了
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
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 {
// 将Bean封装的对象放入容器beanDefinitionMap
this.beanDefinitionMap.put(beanName, beanDefinition);
// 将beanName添加到容器
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}
说明:@Configuration的后置处理器放到beanDefinitionMap中,key为internalConfigurationAnnotationProcessor,value为ConfigurationClassPostProcessor。
refresh方法:invokeBeanFactoryPostProcessors()方法,执行BeanFactory后置处理器的方法
- invokeBeanFactoryPostProcessors();方法入口。
- invokeBeanFactoryPostProcessors()方法委托PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法。
- 遍历beanFactoryPostProcessors集合,找到ConfigurationClassPostProcessor,执行postProcessBeanDefinitionRegistry方法。
- postProcessBeanDefinitionRegistry方法委派给processConfigBeanDefinitions方法,加载bean,将bean放到beanDefinitionMap中。
1. AbstractApplicationContext.invokeBeanFactoryPostProcessors();方法入口。
2. 委托给PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法。
3. 遍历beanFactoryPostProcessors集合,找到ConfigurationClassPostProcessor,执行postProcessBeanDefinitionRegistry方法
processConfigBeanDefinitions方法,加载bean,将bean放到beanDefinitionMap中
核心方法:
-
parse方法,扫描@ComponentScan路径下的所有的BeanDefinition,以及@Import的BeanDefinition,使用递归方法扫描,最终放入this.configurationClasses。
-
this.deferredImportSelectorHandler.process();方法, 将MEATA-INF/spring.factories文件中配置的EnableAutoConfiguration键对应的@Configuration配置的类中的bean加载出来,存放到this.configurationClasses。
- 转化this.configurationClasses为configClasses对象(Set集合)
- loadBeanDefinitions方法
processConfigBeanDefinitions方法入口
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
// 获取所有的BeanDefinition
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
// 检查是否配置了@Configuration注解
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
// 配置了@Configuration注解的bean添加到configCandidates集合中
// 肯定有@SpringBootApplication注解的类,因为@SpringBootApplication本身包含@Configuration
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
.........................
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
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);
alreadyParsed.addAll(configClasses);
processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
processConfigBeanDefinitions方法,核心方法1,parser.parse方法递归方式使用注解@ComponentScan扫描路径下的bean,将扫描到的bean存放到this.configurationClasses
1. parser.parse方法
判断当前的BeanDefinition是否为AnnotatedBeanDefinition类型(已经注解的BeanDefinition)
public void parse(Set<BeanDefinitionHolder> configCandidates) {
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
// 调用了AutoConfigurationGroup#selectImports,从而实现加载其他配置
this.deferredImportSelectorHandler.process();
}
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
// 执行@Configuration注解标识的类
processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}
2. 执行@Configuration注解标识的类
// 执行@Configuration配置的类
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
// Otherwise ignore new imported config class; existing non-imported class overrides it.
return;
}
else {
// Explicit bean definition found, probably replacing an import.
// Let's remove the old one and go with the new one.
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
}
SourceClass sourceClass = asSourceClass(configClass, filter);
do {
// 递归处理配置类及其超类
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
}
while (sourceClass != null);
this.configurationClasses.put(configClass, configClass);
}
3. doProcessConfigurationClass方法,递归调用parse方法,处理@ComponentScan扫描路径下面的类等。
@Nullable
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// 递归处理嵌套类
processMemberClasses(configClass, sourceClass, filter);
}
// 执行@PropertySource注解
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// 执行@ComponentScan注解
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
// 扫描路径下的BeanDefinition
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
// 递归调用这些扫描的子类
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// 执行@Import注解
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
// 执行@ImportResource注解
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// 执行单个@bean标识的方法
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// 处理接口上的默认方法
processInterfaces(configClass, sourceClass);
// 如果超类存在,处理超类
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
// No superclass -> processing is complete
return null;
}
递归调用加载@ComponentScan扫描路径下面的类
4. ConfigurationClassParser.processImports(configClass, sourceClass, getImports(sourceClass), filter, true),执行@Import注解
代码
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
boolean checkForCircularImports) {
if (importCandidates.isEmpty()) {
return;
}
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
this.importStack.push(configClass);
try {
for (SourceClass candidate : importCandidates) {
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass();
ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
this.environment, this.resourceLoader, this.registry);
Predicate<String> selectorFilter = selector.getExclusionFilter();
if (selectorFilter != null) {
exclusionFilter = exclusionFilter.or(selectorFilter);
}
if (selector instanceof DeferredImportSelector) {
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
else {
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
}
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
this.environment, this.resourceLoader, this.registry);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
}
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]", ex);
}
finally {
this.importStack.pop();
}
}
}
5. ConfigurationClassParser.getImports方法,返回@Import注入的类
private Set<SourceClass> getImports(SourceClass sourceClass) throws IOException {
Set<SourceClass> imports = new LinkedHashSet<>();
Set<SourceClass> visited = new LinkedHashSet<>();
collectImports(sourceClass, imports, visited);
return imports;
}
6. @Import注入的类,collectImports方法递归方式收集所有声明的@Import导入的类。
private Set<SourceClass> getImports(SourceClass sourceClass) throws IOException {
Set<SourceClass> imports = new LinkedHashSet<>();
Set<SourceClass> visited = new LinkedHashSet<>();
collectImports(sourceClass, imports, visited);
return imports;
}
1. AutoConfigurationPackage注解导入的AutoConfigurationPackages.Registrar
- AutoConfigurationPackages.Registrar作用:批量导入一系列类,放入beanDefinitionMap(在processImports方法中加载BeanDefinition,在loadBeanDefinitionsForConfigurationClass方法中实例化这些BeanDefinition)。
- 额外,@AutoConfigurationPackage注解的主要作用就是将主程序类所在包及所有子包下的组件到扫描到spring容器中)。
其中AutoConfigurationPackages.Registrar作用:在核心方法2中会介绍processImport方法,将配置类导入,放入beanDefinitionMap。
2. EnableAutoConfiguration注解导入的AutoConfigurationImportSelector
其中AutoConfigurationImportSelector作用:在核心方法2中会介绍processImport方法,将配置类导入,放入beanDefinitionMap。
核心方法2的开始位置:
3. AutoConfigurationPackages.Registrar类、AutoConfigurationImportSelector类的证据如下:
搜集入口类VisualWebApplication上面的@Import注解注入的bean
总结核心方法1,parse方法
-
parse方法,主要作用实际上就是解析我们扫描到的注解。
-
可以看到我们在使用SpringBoot的时候,所谓的@SpringBootApplication注解,实际上就是@Configuration注解 + @ComponentScan注解 + @Import注解,这几种组合注解。
processConfigBeanDefinitions方法,核心方法2,this.deferredImportSelectorHandler.process();方法加载META-INF/spring.factories文件中过滤后的bean,存放到this.importBeanDefinitionRegistrars中
过滤方式通过@ConditionalOnClass注解来判断该类是否加载
1. 委派给processGroupImports方法来加载
2. grouping.getImports()方法内部会调用 this.group.process方法。
自动装配委派给getAutoConfigurationEntry方法
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector)deferredImportSelector).getAutoConfigurationEntry(annotationMetadata);
3. getAutoConfigurationEntry方法,springboot自动装配的核心
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
// 通过 SpringFactoriesLoader 类提供的方法加载类路径中的 META-INF 目录下的
// spring.factories 文件中针对 EnableAutoConfiguration 的注册配置类
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
// 对获得的注册配置类集合进行去重处理,防止多个项目引入同样的配置类
configurations = this.removeDuplicates(configurations);
// 获得注解中被 exclude 或 excludeName 所排除的类的集合
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
// 检查被排除类是否可实例化,是否被自动注册配置所使用,不符合条件则抛出异常
this.checkExcludedClasses(configurations, exclusions);
// 从自动配置类集合中去除被排除的类
configurations.removeAll(exclusions);
// 检查配置类的注解是否符合 spring.factories 文件中 AutoConfigurationImportFilter 指定的注解检查条件
configurations = this.getConfigurationClassFilter().filter(configurations);
// 将筛选完成的配置类和排查的配置类构建为事件类,并传入监听器。监听器的配置在于 spring.factories 文件中
// 通过 AutoConfigurationImportListener 指定
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
}
}
4. getCandidateConfigurations 方法中会通过 SpringFactoriesLoader 类来加载类路径中的 META-INF 目录下的 spring.factories 文件中针对 EnableAutoConfiguration 的注册配置类。
5. 将getAutoConfigurationEntry方法的返回值autoConfigurationEntry,遍历bean存放到this.entries
6. 将this.entries遍历之后将其中的值entry,解析然后存放到this.configurationClasses对象中
processConfigBeanDefinitions方法,核心方法3,loadBeanDefinitions方法,将@Import注解的bean注册到beanDefinitionMap
- 委派给loadBeanDefinitionsForConfigurationClass方法:
- 委派给registerBeanDefinitionForImportedConfigurationClass方法:
- 委派给registerBeanDefinition方法,关键的注册bean的方法,注册beanDefinition到beanDefinitionMap
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
// beanDefinitionMap是否存在beanName
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
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 {
// 如果没有beanName,将beanDefinition注册到beanDefinitionMap
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}
参考
https://mp.weixin.qq.com/s?__biz=MzU2MDg5NzYzNA==&mid=2247486519&idx=1&sn=cdc881a7620b5ad6db4b79886c442e44&chksm=fc00473acb77ce2c2d057a6d0991af40ea5c601acdfba7a8098d528df14db8029cc847a9e134&scene=27
https://blog.csdn.net/qq_39482039/article/details/120491648
https://blog.csdn.net/qq_39482039/article/details/125766388
https://blog.csdn.net/u011523825/article/details/126990788
https://www.jianshu.com/p/dbc1b2d3105d