Spring?BeanDefinition收集過程示例詳解
以注解方式說明BeanDefinition的收集過程
調(diào)試代碼
以注解方式說明BeanDefinition的收集過程,調(diào)試代碼如下:
public class AnnotationACTest { public static void main(String[] args) { // new一個(gè)應(yīng)用上下文的時(shí)候,會(huì)注冊(cè)一些內(nèi)部的BeanFactoryPostProcessor的beanDefinition AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(); ac.register(BeanConfig.class); ac.refresh(); } }
BeanConfig
@Configuration @ComponentScan("com.mfy.test.bean") @EnableAspectJAutoProxy public class BeanConfig { @Bean public User getUser(){ this.getWoman(); return new User(); } @Bean("women") public Woman getWoman(){ System.out.println("測(cè)試@Configuration的類方法內(nèi)部調(diào)用"); return new Woman(); } }
掃描包下的某一個(gè)Bean
@Component public class PropertyBean { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
創(chuàng)建ApplicationContext對(duì)象
創(chuàng)建出來的AnnotationConfigApplicationContext內(nèi)部會(huì)持有DefaultListableBeanFactory(實(shí)現(xiàn)了BeanFactory接口的所有方法)
public AnnotationConfigApplicationContext() { // 隱式的會(huì)調(diào)用父類的構(gòu)造方法,this.beanFactory = new DefaultListableBeanFactory(); // 此處會(huì)添加內(nèi)部的一些beanDefinition,存儲(chǔ)到BeanFactory的beanDefinitionMap this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); }
值得注意的是,創(chuàng)建AnnotatedBeanDefinitionReader的過程,會(huì)將ConfigurationClassPostProcessor,AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor的beanDefinition加入到spring容器中;創(chuàng)建ClassPathBeanDefinitionScanner時(shí),會(huì)將@Component注解加入到includeFilters.
注入PostProcessor的代碼:
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) { DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); if (beanFactory != null) { if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) { beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); } if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) { beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); } } Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8); // 判斷BeanFactory中不存在此BeanDefinition,添加ConfigurationClassPostProcessor // ConfigurationClassPostProcessor類負(fù)責(zé)解析處理所有@Configuration類,并將BeanDefinition注冊(cè)到BeanFactory中。 if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); } // AutowiredAnnotationBeanPostProcessor類負(fù)責(zé)處理@Autowired if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } // CommonAnnotationBeanPostProcessor類負(fù)責(zé)處理@Resource,@PostConstruct,@PreDestroy if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)); } // 省略了部分代碼 return beanDefs; }
注入@Component注解
protected void registerDefaultFilters() { // 此處將Component注入,用于后面的識(shí)別 this.includeFilters.add(new AnnotationTypeFilter(Component.class)); ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader(); // 省略部分代碼 }
通過上面的步驟,只是完成了AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext()
這一行代碼的運(yùn)行.
接下來,要將配置類BeanConfig,手動(dòng)注入到創(chuàng)建出來的AnnotationConfigApplicationContext中,實(shí)際上,是委托給了AnnotatedBeanDefinitionReader來進(jìn)行配置類的解析工作
public void register(Class<?>... componentClasses) { Assert.notEmpty(componentClasses, "At least one component class must be specified"); // 解析給定的class對(duì)象,并存儲(chǔ)到beanDefinitionMap this.reader.register(componentClasses); }
this.reader.register(componentClasses)
這行代碼,會(huì)一直調(diào)用到doRegisterBean()
,才會(huì)開始真正的邏輯處理,其實(shí)只做了一件事,就是生成BeanConfig的BeanDefinition,并注入到spring容器中.
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) { AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass); if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { return; } abd.setInstanceSupplier(supplier); ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); // 設(shè)置單例還是原型 abd.setScope(scopeMetadata.getScopeName()); // 設(shè)置beanName,當(dāng)傳入的name為null,按照規(guī)則,自動(dòng)生成名稱 String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); // 解析部分公共的注解(@Lazy,@Primary,@DependsOn,@Role,@Description),并將解析出來的信息填充到beanDefinition中 AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); if (qualifiers != null) { for (Class<? extends Annotation> qualifier : qualifiers) { if (Primary.class == qualifier) { abd.setPrimary(true); } else if (Lazy.class == qualifier) { abd.setLazyInit(true); } else { abd.addQualifier(new AutowireCandidateQualifier(qualifier)); } } } if (customizers != null) { for (BeanDefinitionCustomizer customizer : customizers) { customizer.customize(abd); } } BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); // 將解析完成的beanDefinition放入beanFactory中 BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); }
此時(shí)代碼運(yùn)行完了ac.register(BeanConfig.class)
,接下來要刷新容器,即運(yùn)行ac.refresh()
,這個(gè)方法是所有bean進(jìn)行實(shí)例化和初始化的核心,需要重點(diǎn)分析,核心步驟如下:
獲取beanFactory
遍歷BeanDefinitionRegistryPostProcessor接口的實(shí)現(xiàn)類,調(diào)用postProcessBeanDefinitionRegistry()方法,將BeanConfig中@ComponentScan覆蓋的bean的beanDefinition信息注冊(cè)到spring容器中
實(shí)例化,初始化所有非懶加載的單例bean
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // 獲取BeanFactory,其實(shí)是DefaultListableBeanFactory ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 設(shè)置BeanFactory的類加載器,添加幾個(gè)BeanPostProcessor,手動(dòng)注冊(cè)幾個(gè)特殊的bean prepareBeanFactory(beanFactory); try { // 擴(kuò)展點(diǎn),可以對(duì)beanFactory做修改 postProcessBeanFactory(beanFactory); // 實(shí)例化BeanFactoryPostProcessor(new應(yīng)用上下文的時(shí)候注冊(cè)的beanDefinition)并調(diào)用,作用是修改beanDefinition的信息 // 例如internalConfigurationAnnotationProcessor,用來解析@Configuration注解類管轄的beanDefinition信息 invokeBeanFactoryPostProcessors(beanFactory); // 實(shí)例化各種BeanPostProcessors,并注冊(cè)到beanFactory的beanPostProcessors屬性中 registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // 初始化事件廣播器(給applicationEventMulticaster賦值) initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // 注冊(cè)監(jiān)聽器(非@EventListener注解方式,注冊(cè)的是實(shí)現(xiàn)了ApplicationListener接口的類) registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } // 省略部分代碼 }
分析步驟
- 收集實(shí)現(xiàn)了PriorityOrdered接口和BeanDefinitionRegistryPostProcessor接口的實(shí)現(xiàn)類并調(diào)用postProcessBeanDefinitionRegistry(),其實(shí)就是調(diào)用ConfigurationClassPostProcessor,這個(gè)類是spring中的核心類,作用是收集@Component注解的Bean信息,解析成BeanDefinition注冊(cè)到spring容器中
- 收集實(shí)現(xiàn)了Ordered接口和BeanDefinitionRegistryPostProcessor接口的實(shí)現(xiàn)類并調(diào)用postProcessBeanDefinitionRegistry()
- 死循環(huán)收集BeanDefinitionRegistryPostProcessor接口的實(shí)現(xiàn)類(排除了前面的)并調(diào)用postProcessBeanDefinitionRegistry()
- 調(diào)用前面所有BeanDefinitionRegistryPostProcessor接口的實(shí)現(xiàn)類的postProcessBeanFactory()方法
- 收集BeanFactoryPostProcessor接口的實(shí)現(xiàn)類,也是分成實(shí)現(xiàn)了PriorityOrdered接口,Ordered接口和其他的三種情況,然后調(diào)用postProcessBeanFactory()方法
public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // 已經(jīng)完成調(diào)用的后置處理器集合 Set<String> processedBeans = new HashSet<>(); // 省略部分代碼 List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); // 獲取實(shí)現(xiàn)了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor實(shí)現(xiàn)類,排序之后,按順序調(diào)用 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); // 目前是調(diào)用ConfigurationClassPostProcessor,解析“配置類”的包含的bean信息,變成beanDefinition存入map中 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); // 獲取實(shí)現(xiàn)了Ordered接口的BeanDefinitionRegistryPostProcessor實(shí)現(xiàn)類,排序之后,按順序調(diào)用 postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); // 死循環(huán)獲取其他所有的BeanDefinitionRegistryPostProcessor實(shí)現(xiàn)類,排序之后,按順序調(diào)用 // 死循環(huán)BeanDefinitionRegistryPostProcessor實(shí)現(xiàn)類的原因是,前面的BeanDefinitionRegistryPostProcessor可能會(huì)注入新的實(shí)現(xiàn)類, // 所以必須重新再獲取并調(diào)用一遍 boolean reiterate = true; while (reiterate) { reiterate = false; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); reiterate = true; } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); // 遍歷BeanDefinitionRegistryPostProcessor的實(shí)現(xiàn)類,調(diào)用postProcessBeanDefinitionRegistry() invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); } // 遍歷BeanDefinitionRegistryPostProcessor實(shí)現(xiàn)類,調(diào)用postProcessBeanFactory() // 對(duì)于ConfigurationClassPostProcessor,生成“配置”類(@Configuration)的代理類 invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); // 遍歷非BeanDefinitionRegistryPostProcessor實(shí)現(xiàn)類(自己加進(jìn)來的),調(diào)用postProcessBeanFactory(),基本不會(huì)執(zhí)行 invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { // 遍歷非BeanDefinitionRegistryPostProcessor實(shí)現(xiàn)類(自己加進(jìn)來的),調(diào)用postProcessBeanFactory(),基本不會(huì)執(zhí)行 invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, // Ordered, and the rest. List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); List<String> nonOrderedPostProcessorNames = new ArrayList<>(); for (String ppName : postProcessorNames) { // 跳過前面已經(jīng)處理過的BeanFactoryPostProcessor實(shí)現(xiàn)類 if (processedBeans.contains(ppName)) { // skip - already processed in first phase above } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { // 通過beanFactory的getBean(),實(shí)例化BeanFactoryPostProcessor priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. sortPostProcessors(priorityOrderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // Next, invoke the BeanFactoryPostProcessors that implement Ordered. List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size()); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } sortPostProcessors(orderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // Finally, invoke all other BeanFactoryPostProcessors. List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size()); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); beanFactory.clearMetadataCache(); }
下面重點(diǎn)分析一下ConfigurationClassPostProcessor,其實(shí)就是分析processConfigBeanDefinitions(),看看是如何將bean變成beanDefinition注冊(cè)到spring容器
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); // 解析@Component,@ComponentScan,@Import,@ImportResource注解 processConfigBeanDefinitions(registry); }
processConfigBeanDefinitions()實(shí)現(xiàn)邏輯
接下來,看看processConfigBeanDefinitions()的實(shí)現(xiàn)邏輯,主要流程如下:
- 獲取容器中所有已經(jīng)注冊(cè)進(jìn)來的beanName,其實(shí)此時(shí)只有一個(gè)手動(dòng)注冊(cè)進(jìn)來的BeanConfig,其他的全部都是spring自己注冊(cè)的
- 篩選出@Configuration注解的類,其實(shí)就是BeanConfig
- 創(chuàng)建ConfigurationClassParser,是個(gè)解析器,作用是解析@ComponentScan注解
- 進(jìn)行parse(),將@ComponentScan指定的包下所有@Component注解的bean變成beanDefinitiion注冊(cè)到spring容器中,同時(shí)對(duì)每一個(gè)@Component注解的bean,包裝成ConfigurationClass(封裝了注解信息metadata,beanName,beanMethods和importedResources),注冊(cè)到ConfigurationClassParser中的configurationClasses屬性
- 遍歷configurationClasses中的ConfigurationClass,處理@Bean,@Import和@ImportResource注解,其中,@Bean和@Import會(huì)生成beanDefinition注冊(cè)到spring容器中
- 找出步驟4中注冊(cè)進(jìn)來的beanDefinition,判斷這些beanDefinition是否存在@Configuration,@ComponentScan,@Component,@ImportResource和@Import注解(至于為什么沒有在步驟3中掃描到這些beanDefinition,原因是這些bean不在@ComponentScan所指定的包下),若判斷為true,則將重復(fù)步驟3~6
經(jīng)過以上步驟之后,@ComponentScan指定包下的bean都已經(jīng)變成beanDefinition注冊(cè)到spring容器中了
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); String[] candidateNames = registry.getBeanDefinitionNames(); // 篩選具有@Component,@ComponentScan,@Import,@ImportResource注解信息的BeanDefinition 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); } } else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { // 若是無xml方式配置的,此處只會(huì)篩選出@Configuration注解的類(即ac.register(BeanConfig.class)) configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); } } // Return immediately if no @Configuration classes were found 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( AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR); if (generator != null) { this.componentScanBeanNameGenerator = generator; this.importBeanNameGenerator = generator; } } } if (this.environment == null) { this.environment = new StandardEnvironment(); } // 實(shí)例化ConfigurationClassParser時(shí),會(huì)new一個(gè)ComponentScanAnnotationParser對(duì)象, // 用來解析@ComponentScan注解對(duì)應(yīng)的bean信息 ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates); Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size()); do { // 解析配置類,變成beanDefinition加入beanFactory的beanDefinitionMap中 // 最終的解析過程是委托給了一個(gè)實(shí)例化的ClassPathBeanDefinitionScanner類 // 解析出來的配置類,存儲(chǔ)在parser的configurationClasses屬性中 parser.parse(candidates); parser.validate(); // 得到所有配置類的bean信息 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()); } // 通過ConfigurationClass加載更多的BeanDefinition,通過前面parser.parse(candidates),解析了@bean注解并保存在ConfigurationClass的beanMethods // 再通過beanMethods,生成BeanDefinition信息并注冊(cè)到beanDefinitionMap中 // 將@ImportResource注解的資源引入spring // 將@Import注解的類,生成BeanDefinition信息并注冊(cè)到beanDefinitionMap中 this.reader.loadBeanDefinitions(configClasses); alreadyParsed.addAll(configClasses); candidates.clear(); // 如果進(jìn)入到下面的代碼中,則表示原工程中有@Configuration注解的配置類 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())) { // 類似遞歸,若@Configuration注解的配置類管轄了另外的@Configuration(不在oldCandidateNames集合中),再次循環(huán) 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(); } }
下面重點(diǎn)分析一下步驟4,解析@ComponentScan的過程,實(shí)際上調(diào)用的是processConfigurationClass()方法,主要是循環(huán)的調(diào)用doProcessConfigurationClass(),并且每次跳出循環(huán),都會(huì)將configClass注冊(cè)到屬性configurationClasses中
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); } } // 遞歸的處理配置類configClass及其所繼承的父類 // 從當(dāng)前配置類configClass開始向上沿著類繼承結(jié)構(gòu)逐層執(zhí)行doProcessConfigurationClass(), // 直到遇到的父類是由Java提供的類結(jié)束循環(huán) SourceClass sourceClass = asSourceClass(configClass, filter); do { sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter); } while (sourceClass != null); // 需要被處理的配置類configClass已經(jīng)被分析處理,將它記錄到已處理配置類記錄 this.configurationClasses.put(configClass, configClass); }
真正處理@ComponentScan的代碼邏輯,步驟如下:
- 收集所有被@Component注解并且在@ComponentScan指定的包下的bean,轉(zhuǎn)換成beanDefinition注冊(cè)到spring容器中
- 遍歷步驟1中的beanDefinition,找出存在@Configuration,@ComponentScan,@Component,@ImportResource和@Import注解信息的beanDefinition,調(diào)用parse()方法,實(shí)際上,再次調(diào)用主要是為了解析@Bean,@ComponentScan,@ImportResource和@Import注解,目的也是為了注冊(cè)這些注解代表的beanDefinition
- 處理@Import注解
- 處理@ImportResource注解
- 處理@Bean注解
TODO 解析的流程
protected final SourceClass doProcessConfigurationClass( ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException { if (configClass.getMetadata().isAnnotated(Component.class.getName())) { // 遞歸處理內(nèi)部類(內(nèi)部類也有@Component注解,需要注冊(cè)到容器中) 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) { // 此configClass存在@ComponentScan注解,掃描獲取basePackages的所有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(); } // 判斷通過@ComponentScan掃描新加入的bdCand,是否存在@Configuration,@ComponentScan,@Component,@ImportResource,@Import注解, // 若有,則再次進(jìn)入配置類的解析處理流程 if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { parse(bdCand.getBeanClassName(), holder.getBeanName()); } } } } // 處理@Import注解,給configClass加入ImportBeanDefinitionRegistrar,后續(xù)會(huì)調(diào)用 // getImports(),遍歷并遞歸獲取sourceClass的所有注解中包含@import注解的value值 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注解,獲取注解的方法的相關(guān)元數(shù)據(jù),比如方法名、所在類全名、返回類型、是否靜態(tài)、是否不可覆蓋等等信息 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; }
以上就是Spring BeanDefinition收集過程示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Spring BeanDefinition收集過程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java使用html2image將html生成縮略圖圖片的實(shí)現(xiàn)示例
本文主要介紹了Java使用html2image將html生成縮略圖圖片的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-12-12IntelliJ?IDEA的代碼擱置功能實(shí)現(xiàn)
本文主要介紹了IntelliJ?IDEA的代碼擱置功能實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01Java實(shí)現(xiàn)4種微信搶紅包算法(小結(jié))
微信紅包是大家經(jīng)常使用的,到現(xiàn)在為止仍然有很多紅包開發(fā)的需求,實(shí)現(xiàn)搶紅包算法也是面試??碱},本文就詳細(xì)的來介紹一下如何實(shí)現(xiàn),感興趣的可以了解一下2021-12-12springboot在filter中如何用threadlocal存放用戶身份信息
這篇文章主要介紹了springboot中在filter中如何用threadlocal存放用戶身份信息,本文章主要描述通過springboot的filter類,在過濾器中設(shè)置jwt信息進(jìn)行身份信息保存的方法,需要的朋友可以參考下2024-07-07JavaSE學(xué)習(xí)之內(nèi)部類及常用API
這篇文章主要介紹了JavaSE中的內(nèi)部類和幾個(gè)常用的API,文中的示例代碼介紹詳細(xì),對(duì)我們學(xué)習(xí)JavaSEI有一定的幫助,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2021-12-12java 調(diào)用wsdl協(xié)議接口簡(jiǎn)單實(shí)用方法最新推薦
文章介紹了如何使用POM導(dǎo)入依賴,并編寫一個(gè)測(cè)試類來調(diào)用不同的Web服務(wù)接口,通過訪問接口地址,我們可以獲取請(qǐng)求和返回的body,并進(jìn)一步解析返回的JSON結(jié)果,感興趣的朋友一起看看吧2025-03-03javabean?中使用@Transient屬性處理臨時(shí)字段
@Transient表示該屬性并非一個(gè)到數(shù)據(jù)庫(kù)表的字段的映射,ORM框架將忽略該屬性,本文給大家介紹javabean?中臨時(shí)字段的處理:@Transient,感興趣的朋友跟隨小編一起看看吧2023-08-08