Spring @Configuration流程概述

1. 开始

Spring核心流程梳理中我们已经介绍了,Spring的核心流程都被封装在了模板方法refresh中。

但是AnnotationConfigApplicationContext解析BeanDefinition的方式和ClassPathXmlApplicationContext还是不同。

ClassPathXmlApplicationContext是在refresh方法中通过调用prepareBeanFactory逻辑来处理。

而AnnotationConfigApplicationContext在构造逻辑中就开始处理解析BeanDefinition逻辑。

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConditionConfig.class);

从AnnotationConfigApplicationContext入口,实际解析逻辑在AnnotatedBeanDefinitionReader的doRegisterBean方法中。

主要就是解析注册BeanDefinition,包括处理@Conditional条件判断、作用域Scope、懒加载@lazy、@Primary等逻辑。

2. ConfigurationClassPostProcessor

Spring是通过BeanFactoryPostProcessor:ConfigurationClassPostProcessor来处理Configuration注解的。

我们已经知道,Spring处理BeanFactoryPostProcessor是通过refresh的invokeBeanFactoryPostProcessors方法做为入口了。

逻辑执行通过代理:PostProcessorRegistrationDelegate实现。

当然,最终的逻辑还是通过ConfigurationClassPostProcessor来执行。

其中2个重要的方法:

processConfigBeanDefinitions方法解析@Configuration的类的信息:

1public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { 2 // 这个时候BeanDefinition已经继续完了,所以这里可以获取容器中的所有BeanDefinition了 3 4 List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); 5 String[] candidateNames = registry.getBeanDefinitionNames(); 6 7 for (String beanName : candidateNames) {//找出容器中所有被@Configuration注解的类的BeanDefinition,包装成BeanDefinitionHolder 8 if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { 9 configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); 10 } 11 } 12 13 // 处理@Order注解,根据优先级排序 14 configCandidates.sort((bd1, bd2) -> { 15 int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); 16 int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition()); 17 return Integer.compare(i1, i2); 18 }); 19 20 // 通过ConfigurationClassParser解析 @Configuration 类 21 ConfigurationClassParser parser = new ConfigurationClassParser( 22 this.metadataReaderFactory, this.problemReporter, this.environment, 23 this.resourceLoader, this.componentScanBeanNameGenerator, registry); 24 25 // 解析@Import、@Bean等注解 26 this.reader.loadBeanDefinitions(configClasses); 27}

enhanceConfigurationClasses方法为Configuration设置代理类:

1public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) { 2 Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>(); 3 for (String beanName : beanFactory.getBeanDefinitionNames()) { 4 BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName); 5 Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE); 6 MethodMetadata methodMetadata = null; 7 8 // 通过cglib给Configuration生成代理类逻辑 9 ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer(); 10 for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) { 11 AbstractBeanDefinition beanDef = entry.getValue(); 12 beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE); 13 Class<?> configClass = beanDef.getBeanClass(); 14 // 最主要的方法是注册了一个BeanMethodInterceptor回调类,来处理@Bean注解 15 Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader); 16 if (configClass != enhancedClass) { 17 beanDef.setBeanClass(enhancedClass); 18 } 19 } 20}

3. 资料参考

Spring Bean生命周期

Spring核心流程梳理

点赞
收藏

评论区

加载中...

相关推荐

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Spring5.0源码学习系列之Spring AOP简述(九)

前言介绍附录:Spring源码学习专栏(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fblog.csdn.net%2Fu014427391%2Fcategory_10493299.html)在前面章节的学习中,我们对Spring框架的IOC实现源码有了一定的了解,接着

KafkaProducer Sender 线程详解(含详细的执行流程图)

\温馨提示:本文基于Kafka2.2.1版本。上文《源码分析Kafka消息发送流程》(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fblog.csdn.net%2Fprestigeding%2Farticle%2Fdetails%2F102994716)已经详细介绍

Spring Bean生命周期

1\.简介在【Spring核心流程梳理】我们介绍了Spring容器的refresh过程,但是我们并没有进入到SpringBean的创建等生命周期等内容。这里,就来梳理一下SpringBean的生命周期。我们还是关注流程,重点关注核心的入口,忽略具体实现的细节。目标也很简单:1.知道SpringBean相关的扩展点

MapReduce的逻辑切分split与合并combiner

        在之前的博客《MapReduce中shuffle阶段概述及计算任务流程》(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fblog.csdn.net%2Fweixin_44318830%2Farticle%2Fdetails%2F103044135),小菌为大家分享了Ma

Spring Boot的exit code

文章目录SpringBoot的exitcode(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fblog.csdn.net%2Fsuperfjj%2Farticle%2Fdetails%2F104290745%23Spring_Bootexit_code_5)