前言
- 上篇博客spring 5.0.x源碼學習系列五: AnnotationConfigApplicationContext類refresh方法之invokeBeanFactoryPostProcessor(一)主要解釋的是invokeBeanFactoryPostProcessor方法的大致執行流程, 為了精通spring, 咱們除了要了解后置處理器的執行順序外,還得明白這其中的一個特殊后置處理器(ConfigurationClassPostProcessor)的作用。下面將開始對ConfigurationClassPostProcessor的第一個重要的身份
BeanDefinitionRegistryPostProcessor
進行講解(第二個身份BeanFactoryPostProcessor
在下一篇博客進行總結)
一、ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份
- 它的這個身份起到了非常重要的作用: 處理配置類并解析它們。 這句話可能有點難理解, 我們根據下面的篇幅慢慢理解。
二、流程圖
-
這里提供一張處理配置類流程圖, 結合項目demo一起看
在這里插入圖片描述
三、項目demo
3.1 項目全景圖
3.1.1 EnableProxy類
3.1.2 ImportEugene類
3.1.3 UserDaoImpl類
3.1.4 ImportEugeneImportSelector類
3.1.5 MyImportBeanDefinitionRegistrar類
3.1.6 ImportEugeneBeanFactoryProcessor類
3.1.7 JDKProxyPostProcessor類
3.1.8 MyInvocationHandler類
3.1.9 ProxyUtil類
3.1.10 UserServiceImpl類
3.1.11 UserService類
3.1.12 AppConfig類
3.1.13 Entry類
3.1.14 TestBeanInAppConfig類
3.1.15 TestDaoInUserDaoImpl類
3.2 demo運行結果
-
AppConfig類
存在
@ImportEugene和 @EnableProxy注解時, 運行結果如下:
在這里插入圖片描述
=> 打印了7句 ========ImportEugene========的原因是有7個bean要創建, 分別為如下7個bean:AppConfig, UserServiceImpl, UserDaoImpl, ImportEugeneBeanFactoryProcessor, JDKProxyPostProcessor, TestBeanInAppConfig, TestDaoInUserDaoImpl
-
AppConfig類
去除
@ImportEugene和 @EnableProxy注解時, 運行結果如下:
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
3.4 Demo運行結果總結
本demo利用了spring的兩個大擴展點: BeanPostProcessor和 @Import注解。其中自定義注解 @EnableProxy和 @ImportEugene利用了 @Import注解擴展點的兩種類型:
ImportSelector
和ImportBeanDefinitionRegistrar
來實現-
關于上述的三個點
BeanPostProcessor
,ImportSelector
,ImportSelector
的功能將以如下表格來闡述擴展點 提供api 作用 使用示例 BeanPostProcessor beanName和當前bean對象 可以動態修改bean 本案例中的為UserServiceImpl對象生成代理對象 ImportSelector AnnotationMetadata 能獲取到被導入的那個類的信息, 可以根據自定義的注解來動態寫邏輯, 返回的字符串數組為類的全類名, spring會把他們當成bean去實例化 本案例中的ImportEugeneBeanFactoryProcessor, 動態的添加指定bean ImportBeanDefinitionRegistrar AnnotationMetadata和BeanDefinitionRegistry 擁有ImportSelector的api, 同時還能獲取到BeanDefinitionRegister 本案例中的MyImportBeanDefinitionRegistrar, 動態的添加beanDefinition
四、運行原理
4.1 前言
- 本demo中的演示只有幾個部分和ConfigurationClassPostProcessor的BeanDefinitionRegistryPostProcessor身份有關, 只要涉及到bean的創建和bean的執行順序, 都不屬于本篇博客的內容, 添加一個demo演示是為了更好的說明問題, 現在開始總結原理
4.2 執行原理
4.2.1 在上篇博客中有總結到invokeBeanFactoryPostProcessors方法執行后置處理器的幾個順序。我們現在將從調用ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法開始
-
postProcessBeanDefinitionRegistry方法源碼
@Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { int registryId = System.identityHashCode(registry); if (this.registriesPostProcessed.contains(registryId)) { throw new IllegalStateException( "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry); } if (this.factoriesPostProcessed.contains(registryId)) { throw new IllegalStateException( "postProcessBeanFactory already called on this post-processor against " + registry); } this.registriesPostProcessed.add(registryId); // 開始處理配置類, registry為bean工廠 processConfigBeanDefinitions(registry); }
-
processConfigBeanDefinitions處理配置類
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { // 存儲配置類的數據結構: 很重要, 后續將解析此集合 List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); // 獲取bean工廠的所有beanDefinition的名稱, 在本次demo中, 一共有7個beanDefinition // 為spring內置的6個beanDefinition + AppConfig beanDefinition String[] candidateNames = registry.getBeanDefinitionNames(); // 遍歷beanDefinition for (String beanName : candidateNames) { // 根據beanName到bean工廠中拿到beanDefinition BeanDefinition beanDef = registry.getBeanDefinition(beanName); // 判斷是否為全注解或者部分注解 => 這里正常的spring流程下, 應該都沒標注 // 除非程序員自己利用擴展點修改了配置類對應的標識 // eg: 標識它為全配置類 // 配置類對應的beanDefinition.setAttribute( // "org.springframework.context.annotation. // ConfigurationClassPostProcessor.configurationClass", "full"); // eg: 標識它為部分配置類 // 配置類對應的beanDefinition.setAttribute( // "org.springframework.context.annotation. // ConfigurationClassPostProcessor.configurationClass", "lite"); if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) || ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) { if (logger.isDebugEnabled()) { logger.debug("Bean definition has already been processed as a configuration class: " + beanDef); } } // 正常情況下會走else, // ConfigurationClassUtils.checkConfigurationClassCandidate的核心邏輯應該為如下代碼 // if (isFullConfigurationCandidate(metadata)) { // beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL); // } // else if (isLiteConfigurationCandidate(metadata)) { // beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE); // } // 若當前遍歷的beanDefinition是一個配置類或者全配置類則給他一個標識, 并返回true // 進而將當前的beanDefinition添加到configCandidates數據結構中 // 這里總結下什么叫全配置類什么叫部分配置類 // 全配置類: 加了@Configuration注解 // 部分配置類: 類中有@Component、@Import、@ImportResource、@ComponentScan注解及方法中有@Bean注解的類 else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); } } // Return immediately if no @Configuration classes were found // 若bean工廠中無配置類, 那么將結束解析配置類的流程 if (configCandidates.isEmpty()) { return; } // Sort by previously determined @Order value, if applicable configCandidates.sort((bd1, bd2) -> { int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition()); return Integer.compare(i1, i2); }); // Detect any custom bean name generation strategy supplied through the enclosing application context // 還未總結到它的具體作用 SingletonBeanRegistry sbr = null; if (registry instanceof SingletonBeanRegistry) { sbr = (SingletonBeanRegistry) registry; if (!this.localBeanNameGeneratorSet) { BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR); if (generator != null) { this.componentScanBeanNameGenerator = generator; this.importBeanNameGenerator = generator; } } } if (this.environment == null) { this.environment = new StandardEnvironment(); } // Parse each @Configuration class // 生成一個配置類的解析器, 將使用它來對配置類進行解析 ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); // 存放在解析配置類過程中得到的新的配置類, eg: 在解析@ComponentScan注解的掃描路徑時, // 有可能掃描到其他的配置類 Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates); // 將register方法中或者使用spring擴展點手動添加到bean工廠的配置類添加到存放解析完畢的數據結構中, // 為什么這么做? 因為后續將挨個去解析candidates的配置類, 并將新掃描出來或者import進去的 // 配置類也添加到candidates里面去了, 不需要再解析一遍 Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size()); do { // 解析配置類, 執行到此, candidates中只有一個元素, // 因為在執行這個步驟的時候只有AppConfig對應的beanDefinition在bean工廠中 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()); } // 加載掃描出來的所有beanDefinition, 并在此將它們挨個注冊到spring bean工廠中 // 所以執行到這里時, configClasses中存儲元素內容應該為: // 根據candidates中的配置類解析出來的所有配置類 // (包括@Component注解的類、@Import注解導入的普通類、@Configuration的類) this.reader.loadBeanDefinitions(configClasses); alreadyParsed.addAll(configClasses); candidates.clear(); // 這里還會校驗這樣一種情況,因為所有配置類是存到candidates變量中 // 而上述this.reader.loadBeanDefinitions(configClasses);代碼 // 只是將配置類中導入的類注冊到bean工廠中去,而此時有可能 // 這些導入的類內部也會導入其他的類,所以還需要比較下當前解析的配置類 // 中導入的類的數量和原來獲取的配置類的數量。將多出來的配置類數量進行 // 匯總,然后再統一處理它們 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(); } }
-
解析器ConfigurationClassParser之parser方法
public void parse(Set<BeanDefinitionHolder> configCandidates) { this.deferredImportSelectors = new LinkedList<>(); for (BeanDefinitionHolder holder : configCandidates) { BeanDefinition bd = holder.getBeanDefinition(); try { // 這里會根據當前配置類的beanDefinition進入不同的解析邏輯, // 通過Register方法注冊的beanDefinition類型統一為AnnotatedBeanDefinition // 這個在之前的博客中有總結過 if (bd instanceof AnnotatedBeanDefinition) { // 所以解析配置類的時候,是進入這個if分支 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); } } processDeferredImportSelectors(); }
-
解析器ConfigurationClassParser之processConfigurationClass方法 => 會將處理的當前配置類存入解析器的configurationClasses集合中
protected void processConfigurationClass(ConfigurationClass configClass) 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); } } // Recursively process the configuration class and its superclass hierarchy. SourceClass sourceClass = asSourceClass(configClass); do { // 處理完當前配置類后, 會在方法中return null => 表示當前配置類被解析完成 // 進而進入下面的邏輯, 將當前配置添加到configurationClasses中 // 并在最外部 // org.springframework.context.annotation.ConfigurationClassPostProcessor類 // 中的processConfigBeanDefinitions方法中獲取configurationClasses, 并 // 解析它們(這里的解析不僅僅是注冊beanDefinition, 還包括當前配置類中的 // @Bean方法、@Import注解導入的類等等) sourceClass = doProcessConfigurationClass(configClass, sourceClass); } while (sourceClass != null); // 上面每次解析完配置類就添加到當前對象的configurationClasses屬性中 // 當前對象 => 就是在 // org.springframework.context.annotation.ConfigurationClassPostProcessor類中 // 的processConfigBeanDefinitions方法中創建出來的配置類解析器 this.configurationClasses.put(configClass, configClass); }
-
解析器ConfigurationClassParser之doProcessConfigurationClass方法 => 處理@PropertySource, @ComponentScan, @Import, @ImportResource, @Bean注解
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) throws IOException { // Recursively process any member (nested) classes first processMemberClasses(configClass, sourceClass); // Process any @PropertySource annotations // 處理@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.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment"); } } // Process any @ComponentScan annotations // 處理@ComponentScan注解, sourceClass為當前解析的配置類, 即: AppConfig, 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 // 掃描得到所有擁有@Component注解的beanDefinition, 并在 // 內部(this.componentScanParser.parse)將它們注冊到bean工廠 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(); } // 在此校驗掃描出來的@Component注解對應的beanDefinition, 因為有可能它們也被添加了配置類相關的注解, // 所以也把它們當做配置類來解析 // 又因為@Component注解標識的類屬于部分配置類, 所以肯定會將它們當做配置類再解析一遍 if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { // 這里又調用了解析配置類邏輯, 遞歸調用 parse(bdCand.getBeanClassName(), holder.getBeanName()); } } } } // Process any @Import annotations // 處理當前配置類的@Import注解 // 該方法的主要邏輯為如下: // 獲取@Import注解的值, 并挨個遍歷它們 /*for (SourceClass candidate : importCandidates) { // 若導入的類是ImportSelector的類型 if (candidate.isAssignable(ImportSelector.class)) { // Candidate class is an ImportSelector -> delegate to it to determine imports Class<?> candidateClass = candidate.loadClass(); // 使用反射創建對象, 為了調用ImportSelector的方法 ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class); ParserStrategyUtils.invokeAwareMethods( selector, this.environment, this.resourceLoader, this.registry); // 判斷是否為延遲導入, 默認為null, 所有走else if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) { this.deferredImportSelectors.add( new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector)); } else { // 調用ImportSelector的selectImports方法, 得到返回的數組 String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata()); // 將類對應的全路徑轉成Collection<SourceClass>類型, 為了下面的遞歸調用 Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames); // 針對獲取到的類的全路徑, 把它們當做Import注解導入的類進行處理, 遞歸調用 processImports(configClass, currentSourceClass, importSourceClasses, false); } } // 處理類型為ImportBeanDefinitionRegistrar的類 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 = BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class); ParserStrategyUtils.invokeAwareMethods( registrar, this.environment, this.resourceLoader, this.registry); // 將導入的ImportBeanDefinitionRegistrar類型的類添加到當前配置類存放ImportBeanDefinitionRegistrar // 類型的集合中, 方便后面處理配置類時能獲取到它們 configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata()); } else { // 非ImportSelector和ImportSelector的selectImports類型的類, 把它當成配置類處理 // 在遞歸調用處理配置類邏輯processConfigurationClass // 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)); } }*/ processImports(configClass, sourceClass, getImports(sourceClass), true); // Process any @ImportResource annotations // 基于注解的方式的spring, 很少使用此注解, 所以這塊沒有總結到 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); } } // Process individual @Bean methods // 處理配置類中的方法存在@Bean注解的情況, 挨個遍歷存放到當前配置類的數據結構中 // 方便在外部處理配置類(loadBeanDefinition)時將它們獲取出來 Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); for (MethodMetadata methodMetadata : beanMethods) { configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); } // Process default methods on interfaces // 沒總結到, 暫時忽略 processInterfaces(configClass, sourceClass); // Process superclass, if any // 沒總結到, 暫時忽略 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; }
-
加載配置類之loadBeanDefinitions方法
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) { TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator(); // 遍歷傳入的配置類集合 for (ConfigurationClass configClass : configurationModel) { loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator); } }
-
加載配置類之loadBeanDefinitionsForConfigurationClass方法
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注解導入的普通類 if (configClass.isImported()) { registerBeanDefinitionForImportedConfigurationClass(configClass); } // 處理當前配置類中的所有@Bean標識的方法, 并將它注冊到bean工廠 for (BeanMethod beanMethod : configClass.getBeanMethods()) { loadBeanDefinitionsForBeanMethod(beanMethod); } // 加載@ImportedResources注解導入的資源 loadBeanDefinitionsFromImportedResources(configClass.getImportedResources()); // 將@Import注解導入的ImportBeanDefinitionRegistrar類型的bean注冊到bean工廠 loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars()); }
4.2.2 ConfigurationClassPostProcessor做為BeanDefinitionRegistryPostProcessor后置處理器的執行結果
-
執行結果和統計
在這里插入圖片描述
在這里插入圖片描述
BeanDefinition Name | 注冊渠道 |
---|---|
org.springframework.context.annotation.internalConfigurationAnnotationProcessor | AnnotationConfigApplicationContext無參構造方法 |
org.springframework.context.event.internalEventListenerFactory | AnnotationConfigApplicationContext無參構造方法 |
userServiceImpl | 解析@ComponentScan注解 |
testDaoInUserDaoImpl | @Bean注解 |
testDao | AppConfig類的@Bean注解 |
org.springframework.context.event.internalEventListenerProcessor | AnnotationConfigApplicationContext無參構造方法 |
org.springframework.context.annotation.internalAutowiredAnnotationProcessor | AnnotationConfigApplicationContext無參構造方法 |
org.springframework.context.annotation.internalCommonAnnotationProcessor | AnnotationConfigApplicationContext無參構造方法 |
appConfig | register方法 |
userDaoImpl | 解析@ComponentScan注解 |
JDKProxyPostProcessor | 解析@Import注解 |
org.springframework.context.annotation.internalRequiredAnnotationProcessor | AnnotationConfigApplicationContext無參構造方法 |
com.eugene.sumarry.csdn.invokeBeanFactoryPostProcessor2.postprocessor.ImportEugeneBeanFactoryProcessor | 解析@Import注解 |
五、小結
5.1 黑箱理論
- ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份的主要作用為:
掃描并解析register方法注冊的配置類, 解析完成后, 所有能被掃描出來的 bean全部都以beanDefinition的形式存在于bean工廠中,為后續執行掃描 出來的后置處理器和創建bean提供了條件
5.2 建議
- 本篇博客提供的大多數為源碼注釋, 最好是能自己手動搭建與本次demo一樣的項目結構, 結合提供的注釋和運行結果一步一步的去了解ConfigurationClassPostProcessor作為BeanDefinitionRegistryPostProcessor身份的作用
- I am a slow walker, but I never walk backwards.