当前位置: 首页 > news >正文

厦门网站建设网页设计/弹窗广告最多的网站

厦门网站建设网页设计,弹窗广告最多的网站,网站留言板模板,做网站的思路怎么写文章目录一、源码时序图二、源码解析1. 运行案例程序启动类2. 解析AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext(Class<?>... componentClasses)构造方法3. 解析AbstractApplicationContext类的refresh()方法4. 解析AbstractApplicationC…

文章目录

  • 一、源码时序图
  • 二、源码解析
    • 1. 运行案例程序启动类
    • 2. 解析AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext(Class<?>... componentClasses)构造方法
    • 3. 解析AbstractApplicationContext类的refresh()方法
    • 4. 解析AbstractApplicationContext类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)方法
    • 5. 解析PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, ListbeanFactoryPostProcessors)方法
    • 6. 解析PostProcessorRegistrationDelegate类的invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup)方法
    • 7. 解析ConfigurationClassPostProcessor类的postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法
    • 8. 解析ConfigurationClassPostProcessor类的processConfigBeanDefinitions(BeanDefinitionRegistry registry)方法
    • 9. 解析ConfigurationClassParser类的parse(SetconfigCandidates)方法
    • 10. 解析ConfigurationClassParser类的parse(AnnotationMetadata metadata, String beanName)方法
    • 11. 解析ConfigurationClassParser类的processConfigurationClass(ConfigurationClass configClass, Predicatefilter)方法
    • 12. 解析ConfigurationClassParser类的doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicatefilter)方法
    • 13. 解析ConfigurationClassParser类的retrieveBeanMethodMetadata(SourceClass sourceClass)方法
    • 14. 回到ConfigurationClassParser类的doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicatefilter)方法。
    • 15. 回到ConfigurationClassPostProcessor类的processConfigBeanDefinitions(BeanDefinitionRegistry registry)方法
    • 16. 解析ConfigurationClassBeanDefinitionReader类的loadBeanDefinitions(SetconfigurationModel)方法
    • 17. 解析ConfigurationClassBeanDefinitionReader类的loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator)方法
    • 18. 解析ConfigurationClassBeanDefinitionReader类的loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod)方法
    • 19. 解析DefaultListableBeanFactory类的registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法

一、源码时序图

本节,就以源码时序图的方式,直观的感受下@Bean注解在Spring源码层面的执行流程。@Bean注解在Spring源码层面的执行流程如图所示:

在这里插入图片描述
在这里插入图片描述

由图可以看出,@Bean注解在Spring源码层面的执行流程会涉及到BeanTest类、AnnotationConfigApplicationContext类、AbstractApplicationContext类、PostProcessorRegistrationDelegate类、ConfigurationClassPostProcessor类、ConfigurationClassParser类、ConfigurationClassBeanDefinitionReader类和DefaultListableBeanFactory类。具体的源码执行细节参见源码解析部分。

二、源码解析

@Bean注解在Spring源码层面的执行流程,结合源码执行的时序图,会理解的更加深刻。

1. 运行案例程序启动类

在BeanTest类的main()方法中调用了AnnotationConfigApplicationContext类的构造方法,并传入了ComponentScanConfig类的Class对象来创建IOC容器。接下来,会进入AnnotationConfigApplicationContext类的构造方法。

2. 解析AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext(Class<?>… componentClasses)构造方法

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {this();register(componentClasses);refresh();
}

可以看到,在上述构造方法中,调用了refresh()方法来刷新IOC容器。

3. 解析AbstractApplicationContext类的refresh()方法

@Override
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {//############省略其他代码##############try {//############省略其他代码##############invokeBeanFactoryPostProcessors(beanFactory);//############省略其他代码##############}catch (BeansException ex) {//############省略其他代码##############}finally {//############省略其他代码##############}}
}

refresh()方法是Spring中一个非常重要的方法,很多重要的功能和特性都是通过refresh()方法进行注入的。可以看到,在refresh()方法中,调用了invokeBeanFactoryPostProcessors()方法。

4. 解析AbstractApplicationContext类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)方法

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}
}

可以看到,在AbstractApplicationContext类的invokeBeanFactoryPostProcessors()方法中调用了PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors()方法。

5. 解析PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, ListbeanFactoryPostProcessors)方法

由于方法的源码比较长,这里,只关注当前最核心的逻辑,如下所示:

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {//############省略其他代码##############List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.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);invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());currentRegistryProcessors.clear();// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.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, beanFactory.getApplicationStartup());currentRegistryProcessors.clear();// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.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);invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());currentRegistryProcessors.clear();}//############省略其他代码##############
}

可以看到,在PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, ListbeanFactoryPostProcessors)方法中,BeanDefinitionRegistryPostProcessor的实现类在执行逻辑上会有先后顺序,并且最终都会调用invokeBeanDefinitionRegistryPostProcessors()方法。

6. 解析PostProcessorRegistrationDelegate类的invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup)方法

private static void invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process").tag("postProcessor", postProcessor::toString);postProcessor.postProcessBeanDefinitionRegistry(registry);postProcessBeanDefRegistry.end();}
}

可以看到,在invokeBeanDefinitionRegistryPostProcessors()方法中,会循环遍历postProcessors集合中的每个元素,调用postProcessBeanDefinitionRegistry()方法注册Bean的定义信息。

7. 解析ConfigurationClassPostProcessor类的postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {//##########省略其他代码###################processConfigBeanDefinitions(registry);
}

可以看到,在postProcessBeanDefinitionRegistry()方法中,会调用processConfigBeanDefinitions()方法。

8. 解析ConfigurationClassPostProcessor类的processConfigBeanDefinitions(BeanDefinitionRegistry registry)方法

这里,重点关注方法中的如下逻辑:

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {//############省略其他代码#################// Parse each @Configuration classConfigurationClassParser 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 {StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");parser.parse(candidates);parser.validate();//############省略其他代码#################this.reader.loadBeanDefinitions(configClasses);alreadyParsed.addAll(configClasses);processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();//############省略其他代码#################}while (!candidates.isEmpty());//############省略其他代码#################
}

可以看到,在processConfigBeanDefinitions()方法中,创建了一个ConfigurationClassParser类型的对象parser,并且调用了parser的parse()方法来解析类的配置信息。

9. 解析ConfigurationClassParser类的parse(SetconfigCandidates)方法

public void parse(Set<BeanDefinitionHolder> configCandidates) {for (BeanDefinitionHolder holder : configCandidates) {BeanDefinition bd = holder.getBeanDefinition();try {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);}}this.deferredImportSelectorHandler.process();
}

可以看到,在ConfigurationClassParser类的parse(SetconfigCandidates)方法中,调用了类中的另一个parse()方法。

10. 解析ConfigurationClassParser类的parse(AnnotationMetadata metadata, String beanName)方法

protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}

可以看到,上述parse()方法的实现比较简单,直接调用了processConfigurationClass()方法。

11. 解析ConfigurationClassParser类的processConfigurationClass(ConfigurationClass configClass, Predicatefilter)方法

protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {//###############省略其他代码####################SourceClass sourceClass = asSourceClass(configClass, filter);do {sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);}while (sourceClass != null);this.configurationClasses.put(configClass, configClass);
}

可以看到,在processConfigurationClass()方法中,会通过do-while()循环获取配置类和其父类的注解信息,SourceClass类中会封装配置类上注解的详细信息。在在processConfigurationClass()方法中,调用了doProcessConfigurationClass()方法。

12. 解析ConfigurationClassParser类的doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicatefilter)方法

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)throws IOException {//##################省略其他代码##################// Process individual @Bean methodsSet<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);for (MethodMetadata methodMetadata : beanMethods) {configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));}//##################省略其他代码##################// No superclass -> processing is completereturn null;
}

这里,只关注与@Bean注解相关的方法,可以看到,在doProcessConfigurationClass()方法中调用了retrieveBeanMethodMetadata()方法来解析sourceClass中有关@Bean注解的属性信息。

13. 解析ConfigurationClassParser类的retrieveBeanMethodMetadata(SourceClass sourceClass)方法

private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) {AnnotationMetadata original = sourceClass.getMetadata();Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName());if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) {try {AnnotationMetadata asm = this.metadataReaderFactory.getMetadataReader(original.getClassName()).getAnnotationMetadata();Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName());if (asmMethods.size() >= beanMethods.size()) {Set<MethodMetadata> selectedMethods = new LinkedHashSet<>(asmMethods.size());for (MethodMetadata asmMethod : asmMethods) {for (MethodMetadata beanMethod : beanMethods) {if (beanMethod.getMethodName().equals(asmMethod.getMethodName())) {selectedMethods.add(beanMethod);break;}}}if (selectedMethods.size() == beanMethods.size()) {beanMethods = selectedMethods;}}}catch (IOException ex) {logger.debug("Failed to read class file via ASM for determining @Bean method order", ex);}}return beanMethods;
}

可以看到,在retrieveBeanMethodMetadata()方法中主要是解析@Bean注解,并且将解析到的方法元数据存入 Set集合中并返回。

14. 回到ConfigurationClassParser类的doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicatefilter)方法。

这里,还是重点看下方法中与@Bean注解有关的代码片段,如下所示:

Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}

调用retrieveBeanMethodMetadata()方法获取到标注了@Bean注解的方法的元数据集合后,遍历方法的元数据集合,将方法的元数据methodMetadata和配置类configClass传入BeanMethod类的构造方法,创建BeanMethod对象,并调用configClass的addBeanMethod()方法传入创建的BeanMethod对象。

configClass的addBeanMethod()方法的源码详见:org.springframework.context.annotation.ConfigurationClass#addBeanMethod(BeanMethod method),如下所示:

void addBeanMethod(BeanMethod method) {this.beanMethods.add(method);
}

可以看到,在addBeanMethod()方法中,调用了beanMethods的add()方法添加BeanMethod对象。

beanMethods的源码详见:org.springframework.context.annotation.ConfigurationClass#beanMethods,如下所示:

private final Set<BeanMethod> beanMethods = new LinkedHashSet<>();

可以看到,beanMethods是一个LinkedHashSet类型的集合。也就是说,在ConfigurationClassParser类的doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicatefilter)方法中,会将解析出的标注了@Bean注解的元数据封装成BeanMethod对象,添加到一个LinkedHashSet类型的beanMethods集合中。

15. 回到ConfigurationClassPostProcessor类的processConfigBeanDefinitions(BeanDefinitionRegistry registry)方法

此时,重点关注下如下源码片段:

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {//############省略其他代码#################do {//############省略其他代码#################this.reader.loadBeanDefinitions(configClasses);alreadyParsed.addAll(configClasses);processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();//############省略其他代码#################}while (!candidates.isEmpty());//############省略其他代码#################
}

可以看到,在processConfigBeanDefinitions()方法的do-while()循环中,调用了reader的loadBeanDefinitions()方法来加载Bean的定义信息。

16. 解析ConfigurationClassBeanDefinitionReader类的loadBeanDefinitions(SetconfigurationModel)方法

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();for (ConfigurationClass configClass : configurationModel) {loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);}
}

可以看到,在loadBeanDefinitions()方法中,会循环遍历,传入的configurationModel集合,并调用loadBeanDefinitionsForConfigurationClass()方法处理遍历的每个元素。

17. 解析ConfigurationClassBeanDefinitionReader类的loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator)方法

private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {//###############省略其他代码################for (BeanMethod beanMethod : configClass.getBeanMethods()) {loadBeanDefinitionsForBeanMethod(beanMethod);}//###############省略其他代码################
}

可以看到,在loadBeanDefinitionsForConfigurationClass()方法中,会循环遍历通过configClass获取到的BeanMethod集合,并调用loadBeanDefinitionsForBeanMethod()方法处理遍历的每个BeanMethod对象。

18. 解析ConfigurationClassBeanDefinitionReader类的loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod)方法

private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {ConfigurationClass configClass = beanMethod.getConfigurationClass();MethodMetadata metadata = beanMethod.getMetadata();String methodName = metadata.getMethodName();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");List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));String beanName = (!names.isEmpty() ? names.remove(0) : methodName);for (String alias : names) {this.registry.registerAlias(beanName, alias);}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, beanName);beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));if (metadata.isStatic()) {// static @Bean methodif (configClass.getMetadata() instanceof StandardAnnotationMetadata sam) {beanDef.setBeanClass(sam.getIntrospectedClass());}else {beanDef.setBeanClassName(configClass.getMetadata().getClassName());}beanDef.setUniqueFactoryMethodName(methodName);}else {// instance @Bean methodbeanDef.setFactoryBeanName(configClass.getBeanName());beanDef.setUniqueFactoryMethodName(methodName);}if (metadata instanceof StandardMethodMetadata sam) {beanDef.setResolvedFactoryMethod(sam.getIntrospectedMethod());}beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);boolean autowireCandidate = bean.getBoolean("autowireCandidate");if (!autowireCandidate) {beanDef.setAutowireCandidate(false);}String initMethodName = bean.getString("initMethod");if (StringUtils.hasText(initMethodName)) {beanDef.setInitMethodName(initMethodName);}String destroyMethodName = bean.getString("destroyMethod");beanDef.setDestroyMethodName(destroyMethodName);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;}}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, beanName);}if (logger.isTraceEnabled()) {logger.trace(String.format("Registering bean definition for @Bean method %s.%s()",configClass.getMetadata().getClassName(), beanName));}this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}

可以看到,在loadBeanDefinitionsForBeanMethod()方法中解析了@Bean注解中的属性信息,并将解析出的信息封装到一个BeanDefinition对象中,最终会调用registry对象的registerBeanDefinition()方法将封装的BeanDefinition对象注册到IOC容器中。

19. 解析DefaultListableBeanFactory类的registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException {//##############省略其他代码#################BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);if (existingDefinition != null) {//##############省略其他代码#################this.beanDefinitionMap.put(beanName, beanDefinition);}else {//##############省略其他代码#################if (hasBeanCreationStarted()) {// Cannot modify startup-time collection elements anymore (for stable iteration)synchronized (this.beanDefinitionMap) {this.beanDefinitionMap.put(beanName, beanDefinition);List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);updatedDefinitions.addAll(this.beanDefinitionNames);updatedDefinitions.add(beanName);this.beanDefinitionNames = updatedDefinitions;removeManualSingletonName(beanName);}}else {// Still in startup registration phasethis.beanDefinitionMap.put(beanName, beanDefinition);this.beanDefinitionNames.add(beanName);removeManualSingletonName(beanName);}this.frozenBeanDefinitionNames = null;}if (existingDefinition != null || containsSingleton(beanName)) {resetBeanDefinition(beanName);}else if (isConfigurationFrozen()) {clearByTypeCache();}
}

可以看到,Spring会解析这些标注了@Bean注解的方法,将解析出的信息封装成BeanDefinition对象注册到beanDefinitionMap中。这一点和第1章中,注册ConfigurationClassPostProcessor类的Bean定义信息有点类似。

好了,至此,@Bean注解在Spring源码中的执行流程分析完毕。

http://www.jmfq.cn/news/4865203.html

相关文章:

  • 自己做社交网站/输入关键词自动生成标题
  • 大学网站建设多少钱/网络营销案例分析
  • phpstudy做正式网站/重庆企业免费建站
  • 如何做教育网站/新闻发布平台有哪些
  • 如何提升顾客的体验和服务/小时seo
  • 施工企业环境管理体系/优化网站推广教程整站
  • 芯互联大厦做网站的/百度图片识别
  • 阜阳网站建设公司/图片优化
  • 网站自己怎么制作/怎么推广自己的微信号
  • 公司网站建设ppt/百度的代理商有哪些
  • 网站建设策划方案/百度关键词搜索排行
  • 网络规划设计师教程(第2版)/搜索引擎排名优化价格
  • 海北wap网站建设/最近一周热点新闻
  • 百度怎么收录自己的网站/nba体育新闻
  • wordpress.分页工具/seo北京
  • 站长之家网站素材/北京网站快速优化排名
  • 久久建筑网是山东省的吗/附子seo教程
  • 浚县网站建设/关键词提取工具app
  • wordpress中文评论插件/三门峡网站seo
  • 买表的网站/买卖友情链接
  • 做网站怎么添加图片/北京网络营销推广
  • 深圳网站建设10086/在线代理浏览网站免费
  • 企业网站建设的核心/百度文章收录查询
  • 网站建设设计设计/seo收费低
  • 去哪找网站建设公司/百度集团公司简介
  • 网站建设与规划总结/网上永久视频会员是真的吗
  • 长沙专业外贸网站建设/电商网站建设制作
  • 网站开发的结论/免费的短视频app大全
  • 郑州网站建设公司咨询/海外推广方法有哪些
  • 网站问卷调查系统怎么做/百度官网电话客服24小时