接 springIOC - ConfigurationClassPostProcessor - full / lite
代碼塊:
org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions
do { parser.parse(candidates); parser.validate(); //map.keyset 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()); } /** * 這里值得注意的是掃描出來的bean當中可能包含了特殊類 * 比如ImportBeanDefinitionRegistrar那么也在這個方法里面處理 * 但是并不是包含在configClasses當中 * configClasses當中主要包含的是importSelector * 因為ImportBeanDefinitionRegistrar在掃描出來的時候已經被添加到一個list當中去了 */ //將 bd 放到 map 中 this.reader.loadBeanDefinitions(configClasses); alreadyParsed.addAll(configClasses); candidates.clear(); //由于我們這里進行了掃描,把掃描出來的BeanDefinition注冊給了factory //但是 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());
parse 決議完后, 就會呼叫 loadBeanDefinitions方法.
這方法會將 StartConfig.java 決議出來的一些 bd, 注冊到spring容器中.
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) { TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator(); for (ConfigurationClass configClass : configurationModel) { loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator); } }
這個方法里面, 就會對組態檔中的 @Bean 進行注冊,
然后會呼叫 前面決議到的 ImportBeanDefinitionRegistrar.registerBeanDefinitions 方法.
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; } // 注冊 @Import 匯入的普通 bean , 或者 ImportSelector 匯入的普通bean if (configClass.isImported()) { registerBeanDefinitionForImportedConfigurationClass(configClass); } //@Bean 的注冊 for (BeanMethod beanMethod : configClass.getBeanMethods()) { loadBeanDefinitionsForBeanMethod(beanMethod); } //xml loadBeanDefinitionsFromImportedResources(configClass.getImportedResources()); //注冊Registrar loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars()); }
這里需要特別注意一下 loadBeanDefinitionsForBeanMethod
他是對 @Bean 進行注冊的, 有一段代碼比較重要
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata); beanDef.setResource(configClass.getResource()); beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource())); //如果 method 是靜態的 if (metadata.isStatic()) { // static @Bean method
// static時, 設定的是 BeanClassName 屬性 beanDef.setBeanClassName(configClass.getMetadata().getClassName()); beanDef.setFactoryMethodName(methodName); } else { //非static的 method, 設定了一個 FactoryBeanName 屬性 // instance @Bean method beanDef.setFactoryBeanName(configClass.getBeanName()); beanDef.setUniqueFactoryMethodName(methodName); } beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
這里配置了建構式自動注入模式
實體代碼:
@Configuration public class AppConfig { @Bean public static A a(){ return new A(); } @Bean public B b(){ a(); return new B(); } }
這里對 A 和 B 都進行了決議, 轉化成了 ConfigurationClassBeanDefinition
1.靜態方法時, 設定的
BeanClassName = "xxx.xxx.xxx.AppConfig"
FactoryMethodName = "a"
創建的時候, 會來找 AppConfig的a()
2.非靜態方法時, 設定的
FactoryBeanName = "xxx.xxx.xxx.AppConfig"
UniqueFactoryMethodName = "b"
創建 b 的時候, 會來這里找 b() 方法
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/131427.html
標籤:Java
上一篇:BeanFactory后置處理器 - ConfigurationClassPostProcessor - Import
下一篇:BeanFactory后置處理器 - ConfigurationClassPostProcessor#postProcessBeanFactory
