Spring IoC原始碼解析之invokeBeanFactoryPostProcessors
一、Bean工廠的後置處理器
Bean工廠的後置處理器:BeanFactoryPostProcessor(觸發時機:bean定義註冊之後bean例項化之前)和BeanDefinitionRegistryPostProcessor(觸發時機:bean定義註冊之前),所以可以在Bean工廠的後置處理器中修改Bean的定義資訊,比如是否延遲載入、加入一些新的Bean的定義資訊等
Bean工廠的後置處理器類繼承圖:
二、呼叫Bean工廠的後置處理器
invokeBeanFactoryPostProcessors(beanFactory)方法:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { //傳入Bean工廠並獲取容器中的Bean工廠後置處理器(注意這裡Bean工廠後置處理器還沒有初始化) PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor) if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } }
進入PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())方法:
final class PostProcessorRegistrationDelegate { public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { Set<String> processedBeans = new HashSet<>(); //判斷我們的beanFactory是否實現了BeanDefinitionRegistry if (beanFactory instanceof BeanDefinitionRegistry) { //強行把beanFactory轉為BeanDefinitionRegistry BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; //儲存BeanFactoryPostProcessor型別的後置處理器 List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); //儲存BeanDefinitionRegistryPostProcessor型別的後置處理器 List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); //迴圈我們傳遞進來的beanFactoryPostProcessors for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { //判斷我們的後置處理器是不是BeanDefinitionRegistryPostProcessor if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { //進行強制轉化 BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; //呼叫它的後置方法 registryProcessor.postProcessBeanDefinitionRegistry(registry); //新增到我們用於儲存的BeanDefinitionRegistryPostProcessor的集合中 registryProcessors.add(registryProcessor); } else {//若沒有實現BeanDefinitionRegistryPostProcessor介面,那麼他就是BeanFactoryPostProcessor 把當前的後置處理器加入到regularPostProcessors中 regularPostProcessors.add(postProcessor); } } //定義一個集合使用者儲存當前準備建立的BeanDefinitionRegistryPostProcessor List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); //第一步:去容器中獲取BeanDefinitionRegistryPostProcessor的bean的處理器名稱 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); //迴圈上一步獲取的BeanDefinitionRegistryPostProcessor的型別名稱 for (String ppName : postProcessorNames) { //判斷是否實現了PriorityOrdered介面的 if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { //顯示的呼叫getBean()的方式獲取出該物件然後加入到currentRegistryProcessors集合中去 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); //同時也加入到processedBeans集合中去 processedBeans.add(ppName); } } //對currentRegistryProcessors集合中BeanDefinitionRegistryPostProcessor進行排序 sortPostProcessors(currentRegistryProcessors, beanFactory); //把他加入到用於儲存到registryProcessors中 registryProcessors.addAll(currentRegistryProcessors); /** * 在這裡典型的BeanDefinitionRegistryPostProcessor就是ConfigurationClassPostProcessor * 用於進行bean定義的載入 比如我們的包掃描,@import等 */ invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); //呼叫完之後,馬上clear currentRegistryProcessors.clear(); //下一步 又去容器中獲取BeanDefinitionRegistryPostProcessor的bean的處理器名稱 postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); //迴圈上一步獲取的BeanDefinitionRegistryPostProcessor的型別名稱 for (String ppName : postProcessorNames) { //表示沒有被處理過,且實現了Ordered介面的 if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { //顯示的呼叫getBean()的方式獲取出該物件然後加入到currentRegistryProcessors集合中去 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); //同時也加入到processedBeans集合中去 processedBeans.add(ppName); } } //對currentRegistryProcessors集合中BeanDefinitionRegistryPostProcessor進行排序 sortPostProcessors(currentRegistryProcessors, beanFactory); //把他加入到用於儲存到registryProcessors中 registryProcessors.addAll(currentRegistryProcessors); //呼叫他的後置處理方法 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); //呼叫完之後,馬上clear currentRegistryProcessors.clear(); //呼叫沒有實現任何優先順序介面的BeanDefinitionRegistryPostProcessor //定義一個重複處理的開關變數 預設值為true boolean reiterate = true; //第一次就可以進來 while (reiterate) { //進入迴圈馬上把開關變數給改為false reiterate = false; //去容器中獲取BeanDefinitionRegistryPostProcessor的bean的處理器名稱 postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); //迴圈上一步獲取的BeanDefinitionRegistryPostProcessor的型別名稱 for (String ppName : postProcessorNames) { //沒有被處理過的 if (!processedBeans.contains(ppName)) { //顯示的呼叫getBean()的方式獲取出該物件然後加入到currentRegistryProcessors集合中去 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); //同時也加入到processedBeans集合中去 processedBeans.add(ppName); //再次設定為true reiterate = true; } } //對currentRegistryProcessors集合中BeanDefinitionRegistryPostProcessor進行排序 sortPostProcessors(currentRegistryProcessors, beanFactory); //把他加入到用於儲存到registryProcessors中 registryProcessors.addAll(currentRegistryProcessors); //呼叫他的後置處理方法 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); //進行clear currentRegistryProcessors.clear(); } //呼叫實現了BeanDefinitionRegistryPostProcessor的介面 他是他也同時實現了BeanFactoryPostProcessor的方法 invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); //呼叫BeanFactoryPostProcessor invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { //若當前的beanFactory沒有實現了BeanDefinitionRegistry 直接呼叫beanFactoryPostProcessor介面的方法進行後置處理 invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } //最後一步 獲取容器中所有的 BeanFactoryPostProcessor String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); //儲存BeanFactoryPostProcessor型別實現了priorityOrdered List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); //儲存BeanFactoryPostProcessor型別實現了Ordered介面的 List<String> orderedPostProcessorNames = new ArrayList<>(); //儲存BeanFactoryPostProcessor沒有實現任何優先順序介面的 List<String> nonOrderedPostProcessorNames = new ArrayList<>(); for (String ppName : postProcessorNames) { //processedBeans包含的話,表示在上面處理BeanDefinitionRegistryPostProcessor的時候處理過了 if (processedBeans.contains(ppName)) { // skip - already processed in first phase above } //判斷是否實現了PriorityOrdered else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } //判斷是否實現了Ordered else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } //沒有實現任何的優先順序介面的 else { nonOrderedPostProcessorNames.add(ppName); } } //先呼叫BeanFactoryPostProcessor實現了PriorityOrdered介面的 sortPostProcessors(priorityOrderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); //再呼叫BeanFactoryPostProcessor實現了Ordered. List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } sortPostProcessors(orderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); //呼叫沒有實現任何方法介面的 List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); // Clear cached merged bean definitions since the post-processors might have // modified the original metadata, e.g. replacing placeholders in values... beanFactory.clearMetadataCache(); }
第一步:去容器中獲取BeanDefinitionRegistryPostProcessor的bean的處理器名稱
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false) Debug進去看到如下:為什麼就一個ConfigurationClassPostProcessor,因為我們自定的BeanDefinitionRegistryPostProcessor還沒有被加入到Spring容器中去
第一步裡面的invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry)方法:
/** * Invoke the given BeanDefinitionRegistryPostProcessor beans. */ private static void invokeBeanDefinitionRegistryPostProcessors( Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) { //獲取容器中的ConfigurationClassPostProcessor的後置處理器進行Bean定義的掃描 for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) { postProcessor.postProcessBeanDefinitionRegistry(registry); } }
接下來就會呼叫到org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry方法(很重要):
/** * Derive further bean definitions from the configuration classes in the registry. */ @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); //真正的解析我們的Bean定義 processConfigBeanDefinitions(registry); }
進入到真正的解析processConfigBeanDefinitions方法中:
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); //獲取Spring IoC容器中目前所有Bean定義的名稱 String[] candidateNames = registry.getBeanDefinitionNames(); //迴圈所有的Bean定義資訊 for (String beanName : candidateNames) { //通過Bean的名稱來獲取Bean的定義物件 BeanDefinition beanDef = registry.getBeanDefinition(beanName); //判斷是否有沒有解析過 if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) || ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) { if (logger.isDebugEnabled()) { logger.debug("Bean definition has already been processed as a configuration class: " + beanDef); } } //判斷是否是配置類 else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { //新增到候選的配置類集合中 configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); } } // 若沒有找到配置類 直接返回 if (configCandidates.isEmpty()) { return; } //對我們的配置類進行Order排序 configCandidates.sort((bd1, bd2) -> { int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition()); return Integer.compare(i1, i2); }); //建立@CompentScan、@Import匯入進來的bean名稱的生成器 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) { //設定@CompentScan匯入進來的bean的名稱生成器 this.componentScanBeanNameGenerator = generator; //設定@Import匯入進來的bean的名稱生成器 this.importBeanNameGenerator = generator; } } } if (this.environment == null) { this.environment = new StandardEnvironment(); } //建立一個配置類解析器物件 ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); //建立一個集合用於儲存我們的配置類BeanDefinitionHolder集合預設長度是配置類集合的長度 Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates); //建立一個集合用於儲存我們的已經解析的配置類,長度預設為解析出來預設的配置類的集合長度 Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size()); //do while 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); //加入到已經解析的集合中 alreadyParsed.addAll(configClasses); candidates.clear(); //判斷我們Spring IoC容器中Bean的定義數量是否 > 候選原始的bean定義的個數 if (registry.getBeanDefinitionCount() > candidateNames.length) { //獲取所有的bean定義 String[] newCandidateNames = registry.getBeanDefinitionNames(); //原始的老的候選的bean定義 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(); } }
Debug解析:
進入parser.parse(candidates)方法:
public void parse(Set<BeanDefinitionHolder> configCandidates) { //用於儲存延時的ImportSelectors this.deferredImportSelectors = new LinkedList<>(); for (BeanDefinitionHolder holder : configCandidates) { BeanDefinition bd = holder.getBeanDefinition(); try { //真正的解析我們的bean定義 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); } } //處理我們延時的DeferredImportSelectors Spring Boot就是通過這步進行spring.factories檔案中的自定裝配的物件 processDeferredImportSelectors(); }
Debug解析:
進入parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName())方法:
/** * 真正的解析我們的配置類 * @param metadata 配置類的源資訊 * @param beanName 當前配置類的beanName * @throws IOException */ protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException { //把我們的配置類源資訊和beanName包裝成一個ConfigurationClass物件 processConfigurationClass(new ConfigurationClass(metadata, beanName)); }
進入processConfigurationClass(new ConfigurationClass(metadata, beanName))方法:
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) { //傳入的配置類是通過其他配置類的Import匯入進來的 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 { //解析我們的配置類 sourceClass = doProcessConfigurationClass(configClass, sourceClass); } while (sourceClass != null); this.configurationClasses.put(configClass, configClass); }
進入解析我們的配置類的doProcessConfigurationClass(configClass, sourceClass)方法:
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) throws IOException { // Recursively process any member (nested) classes first processMemberClasses(configClass, sourceClass); //處理我們的@PropertySources註解的 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"); } } //接下來解析我們的@ComponentScans註解 //從我們的配置類上解析@ComponentScans的物件集合屬性 Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class); if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) { //迴圈解析(我們解析出來的AnnotationAttributes) for (AnnotationAttributes componentScan : componentScans) { //把我們掃描出來的類變為bean定義的集合 Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); //迴圈處理我們包掃描出來的bean定義 for (BeanDefinitionHolder holder : scannedBeanDefinitions) { BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition(); if (bdCand == null) { bdCand = holder.getBeanDefinition(); } //判斷當前掃描出來的bean定義是不是一個配置類,若是的話 直接進行遞迴解析 if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { //遞迴解析 parse(bdCand.getBeanClassName(), holder.getBeanName()); } } } } //處理@Import processImports(configClass, sourceClass, getImports(sourceClass), 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 methods獲取到我們配置類中所有標註了@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(); } } //沒有父類解析完成 return null; }
Debug解析:
① 解析@ComponentScanthis.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName())方法:
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) { ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry, componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader); //給掃描器設定beanName的生成器物件 Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator"); boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass); scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator : BeanUtils.instantiateClass(generatorClass)); //設定bean的域代理模型 ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy"); if (scopedProxyMode != ScopedProxyMode.DEFAULT) { scanner.setScopedProxyMode(scopedProxyMode); } else { Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver"); scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass)); } scanner.setResourcePattern(componentScan.getString("resourcePattern")); //設定ComponentScan物件的includeFilters包含的屬性 for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) { for (TypeFilter typeFilter : typeFiltersFor(filter)) { scanner.addIncludeFilter(typeFilter); } } //設定ComponentScan物件的excludeFilters不包含的屬性 for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) { for (TypeFilter typeFilter : typeFiltersFor(filter)) { scanner.addExcludeFilter(typeFilter); } } //是否懶載入 boolean lazyInit = componentScan.getBoolean("lazyInit"); if (lazyInit) { scanner.getBeanDefinitionDefaults().setLazyInit(true); } //包路徑 Set<String> basePackages = new LinkedHashSet<>(); String[] basePackagesArray = componentScan.getStringArray("basePackages"); for (String pkg : basePackagesArray) { String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg), ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); Collections.addAll(basePackages, tokenized); } for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) { basePackages.add(ClassUtils.getPackageName(clazz)); } if (basePackages.isEmpty()) { basePackages.add(ClassUtils.getPackageName(declaringClass)); } scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) { @Override protected boolean matchClassName(String className) { return declaringClass.equals(className); } }); //真正的進行掃描解析 return scanner.doScan(StringUtils.toStringArray(basePackages)); }
進入真正的進行掃描解析scanner.doScan(StringUtils.toStringArray(basePackages))方法:
protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); //建立bean定義的holder物件用於儲存掃描後生成的bean定義物件 Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>(); //迴圈我們的包路徑集合 for (String basePackage : basePackages) { //找到候選的@Component Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) { ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); //設定我們的beanName String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); //處理@AutoWired相關的 if (candidate instanceof AbstractBeanDefinition) { postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } //處理jsr250相關的元件 if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } //把我們解析出來的元件bean定義註冊到Spring IoC容器中 if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); //註冊到Spring IoC容器中 registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }
Debug解析:
進過org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan處理,Spring IoC容器中Bean的定義有12個了;
② 接下來處理@Import註解匯入的Bean元件:
進入處理@Import註解的processImports(configClass, sourceClass, getImports(sourceClass), true)方法:
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass, Collection<SourceClass> importCandidates, boolean checkForCircularImports) { if (importCandidates.isEmpty()) { return; } if (checkForCircularImports && isChainedImportOnStack(configClass)) { this.problemReporter.error(new CircularImportProblem(configClass, this.importStack)); } else { this.importStack.push(configClass); try { //獲取我們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(); //例項化我們的SelectImport元件 ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class); //呼叫相關的aware方法 ParserStrategyUtils.invokeAwareMethods( selector, this.environment, this.resourceLoader, this.registry); //判斷是不是延時的DeferredImportSelectors,是這個型別不進行處理 if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) { this.deferredImportSelectors.add( new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector)); } else {//不是延時的呼叫selector的selectImports String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata()); //反之SelectImport匯入進來的又是Import進來的 所以遞迴解析 Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames); 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物件 ImportBeanDefinitionRegistrar registrar = BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class); ParserStrategyUtils.invokeAwareMethods( registrar, this.environment, this.resourceLoader, this.registry); //儲存我們的ImportBeanDefinitionRegistrar物件 configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata()); } else {//就是一個普通的元件 但是防止我們普通的元件是一個配置類 所以還是直接走了processConfigurationClass()方法 this.importStack.registerImport( currentSourceClass.getMetadata(), candidate.getMetadata().getClassName()); processConfigurationClass(candidate.asConfigClass(configClass)); } } } 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(); } } }
③ 接下來處理@ImportSource比如@ImportResource("classpath:circulation-di.xml"),基於xml的(略)
④ 接下來處理@Bean:
至此解析完成,注意@Import、@ImportSource、@Bean的定義還未註冊到Spring IoC的容器中去
接下來將剩餘的Bean定義資訊註冊到Spring IoC容器中:
進入真正的把我們解析出來的配置類註冊到容器中this.reader.loadBeanDefinitions(configClasses)方法:
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) { TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator(); //註冊我們的配置類到容器中 for (ConfigurationClass configClass : configurationModel) { loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator); } }
進入loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator)方法:
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匯入進來的元件 for (BeanMethod beanMethod : configClass.getBeanMethods()) { loadBeanDefinitionsForBeanMethod(beanMethod); } //是不是通過@ImportResources匯入進來的 loadBeanDefinitionsFromImportedResources(configClass.getImportedResources()); //是不是通過ImportBeanDefinition註解匯入進來的 loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars()); }
① 通過@Import匯入進來的執行registerBeanDefinitionForImportedConfigurationClass(configClass)方法:
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) { //獲取我們的配置類的源資訊 AnnotationMetadata metadata = configClass.getMetadata(); //構建為我們的bean定義 AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata); //設定他的scope ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef); configBeanDef.setScope(scopeMetadata.getScopeName()); //獲取bean的名稱 String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry); //處理我們的JRS250元件的 AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata); BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); //註冊我們的bean定義到我們的容器中 this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition()); configClass.setBeanName(configBeanName); if (logger.isDebugEnabled()) { logger.debug("Registered bean definition for imported class '" + configBeanName + "'"); } }
② 通過@Bean匯入進來的執行loadBeanDefinitionsForBeanMethod(beanMethod)方法:
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) { ConfigurationClass configClass = beanMethod.getConfigurationClass(); MethodMetadata metadata = beanMethod.getMetadata(); String methodName = metadata.getMethodName(); // Do we need to mark the bean as skipped by its condition? if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) { configClass.skippedBeanMethods.add(methodName); return; } if (configClass.skippedBeanMethods.contains(methodName)) { return; } AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class); Assert.state(bean != null, "No @Bean annotation attributes"); // Consider name and any aliases List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name"))); String beanName = (!names.isEmpty() ? names.remove(0) : methodName); // Register aliases even when overridden for (String alias : names) { this.registry.registerAlias(beanName, alias); } // Has this effectively been overridden before (e.g. via XML)? if (isOverriddenByExistingDefinition(beanMethod, beanName)) { if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) { throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(), beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() + "' clashes with bean name for containing configuration class; please make those names unique!"); } return; } ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata); beanDef.setResource(configClass.getResource()); beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource())); if (metadata.isStatic()) { // static @Bean method beanDef.setBeanClassName(configClass.getMetadata().getClassName()); beanDef.setFactoryMethodName(methodName); } else { // instance @Bean method beanDef.setFactoryBeanName(configClass.getBeanName()); beanDef.setUniqueFactoryMethodName(methodName); } beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR); beanDef.setAttribute(RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE); AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata); Autowire autowire = bean.getEnum("autowire"); if (autowire.isAutowire()) { beanDef.setAutowireMode(autowire.value()); } String initMethodName = bean.getString("initMethod"); if (StringUtils.hasText(initMethodName)) { beanDef.setInitMethodName(initMethodName); } String destroyMethodName = bean.getString("destroyMethod"); beanDef.setDestroyMethodName(destroyMethodName); // Consider scoping ScopedProxyMode proxyMode = ScopedProxyMode.NO; AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class); if (attributes != null) { beanDef.setScope(attributes.getString("value")); proxyMode = attributes.getEnum("proxyMode"); if (proxyMode == ScopedProxyMode.DEFAULT) { proxyMode = ScopedProxyMode.NO; } } // Replace the original bean definition with the target one, if necessary BeanDefinition beanDefToRegister = beanDef; if (proxyMode != ScopedProxyMode.NO) { BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy( new BeanDefinitionHolder(beanDef, beanName), this.registry, proxyMode == ScopedProxyMode.TARGET_CLASS); beanDefToRegister = new ConfigurationClassBeanDefinition( (RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata); } if (logger.isDebugEnabled()) { logger.debug(String.format("Registering bean definition for @Bean method %s.%s()", configClass.getMetadata().getClassName(), beanName)); } this.registry.registerBeanDefinition(beanName, beanDefToRegister); }
③ 通過@ImportResources匯入進來的執行loadBeanDefinitionsFromImportedResources(configClass.getImportedResources())方法:
private void loadBeanDefinitionsFromImportedResources( Map<String, Class<? extends BeanDefinitionReader>> importedResources) { Map<Class<?>, BeanDefinitionReader> readerInstanceCache = new HashMap<>(); importedResources.forEach((resource, readerClass) -> { // Default reader selection necessary? if (BeanDefinitionReader.class == readerClass) { if (StringUtils.endsWithIgnoreCase(resource, ".groovy")) { // When clearly asking for Groovy, that's what they'll get... readerClass = GroovyBeanDefinitionReader.class; } else { // Primarily ".xml" files but for any other extension as well readerClass = XmlBeanDefinitionReader.class; } } BeanDefinitionReader reader = readerInstanceCache.get(readerClass); if (reader == null) { try { // Instantiate the specified BeanDefinitionReader reader = readerClass.getConstructor(BeanDefinitionRegistry.class).newInstance(this.registry); // Delegate the current ResourceLoader to it if possible if (reader instanceof AbstractBeanDefinitionReader) { AbstractBeanDefinitionReader abdr = ((AbstractBeanDefinitionReader) reader); abdr.setResourceLoader(this.resourceLoader); abdr.setEnvironment(this.environment); } readerInstanceCache.put(readerClass, reader); } catch (Throwable ex) { throw new IllegalStateException( "Could not instantiate BeanDefinitionReader class [" + readerClass.getName() + "]"); } } // TODO SPR-6310: qualify relative path locations as done in AbstractContextLoader.modifyLocations reader.loadBeanDefinitions(resource); }); }
④ 通過ImportBeanDefinition註解匯入進來的執行loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars())方法:
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) { registrars.forEach((registrar, metadata) -> registrar.registerBeanDefinitions(metadata, this.registry)); }
至此第一步裡面的invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry)方法執行完畢!!!!
下一步:又去容器中獲取BeanDefinitionRegistryPostProcessor的bean的處理器名稱 postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false) 此時就有了自己定義的BeanDefinitionRegistryPostProcessor了,接下來呼叫自定義的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry後置方法,然後再呼叫postProcessBeanFactory原因是BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor;
最後一步:獲取容器中所有的BeanFactoryPostProcessor的名稱 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false) 此時就有了自己定義的BeanFactoryPostProcessor了,接下來呼叫自定義的BeanFactoryPostProcessor的postProcessBeanFactory方法;
完整的Spring IoC原始碼解析見:Spring系列(三):Spring IoC原始碼解析
三、Spring IoC掃描Bean的流程圖
總結:通過呼叫我們的Bean工廠的後置處理器,第一步:ConfigurationClassPostProcessor,解析我們的配置類,將所有的Bean的定義資訊註冊到Spring IoC容器中;第二步呼叫自定義的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry後置方法,然後再呼叫postProcessBeanFactory;最後呼叫自定義的BeanFactoryPostProcessor的postProcessBeanFactory