前言
- 上篇博客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办法源码
@Overridepublic 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.