生产中有很多形式的的配置方式,本文仅分析注解配置。对于其他形式的配置区别主观以为主要在配置文件的解析过程不同,不一一分析了。本文以利用Dubbo框架开发rpc服务端为例详细阐述配置类的解析、数据保存、实例化以及注入到容器中。

  通常,涉及到配置参数的框架类,基本都离不开配置的解析及配置的保存;至于配置的具体使用,各框架就自行处理了。对于Spring container而言,配置参数的具体使用就是在实例化Bean的时候使用。所以本文主要分两大部分:1、配置类的解析及数据保存;2、Bean的实例化并注入。

  具体示例配置如下:

    

    

  跟踪调试Spring的工作流程:

   

  查看这个类的属性:

      

  各属性的属性如下:

  构造函数首先调用父类GenericApplicationContext构造函数初始化BeanFactory,这个类中的属性beanDefinitionMap保存bean初始化需要的相关信息。

    

  其次本类中初始化reader和scanner, 分别用于记录BeanDefinition和扫描可能的Bean。初始化之后reader和scanner后,其内部属性如下:

    

  一、配置类的解析及数据保存(register)

    通过源码跟踪分析,此过程的最终目的就是将通用的注解配置以<key,value>的形式保存在DefaultListableBeanFactory的beanDefinitionMap中,使所有的bean全部暴露以便后续使用。该暴露非依赖循环,仅最外层可识别的所有bean。

  二、Bean的实例化并注入(refresh)

    beanDefinitionMap中有很多的bean定义,本文仅关注自定义的配置类providerConfiguration的实例化注入。在模板方法设计模式的文章中,以该方法阐述了实例化注册的大致执行流程。

    refresh方法中并没有传入beanFactory的参数,那么就得在此方法中获得beanFactory,具体子流程如下:

      

    进一步跟踪调试,prepareBeanFactory方法中对beanFactory相关属性进行框架本身的初始赋值(即与具体业务无关)。其中关于beanPostProcessor的如下:

      

      

      

    进入方法invokeBeanFactoryPostProcessors(beanFactory)在context中调用Bean工厂后置处理器依赖处理beanDefinitionMap中的bean定义,将其依赖的bean注入到beanDefinitionMap中。核心方法为processConfigBeanDefinitions(registry),通过该方法即可知其为处理配置bean定义。其处理核心逻辑为:

    1、将所有的配置类列出

      

    2、配置解析对象ConfigurationClassParser解析候选配置类保存至ConfigurationClass中:按层次递归处理配置类及其子类

      

    与示例配置类相关的解析注解有@PropertySource、@Import(@EnableDubbo中包含)、@Bean。属性相关的解析不做详细说明,主要阐述@Import/@Bean的解析。

    3、@Import与@Bean的处理

    在@Enable*注解的工作原理 - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com)中,粗略涉及了@EnableDubbo。这里仅此分析@EnableDubbo中涉及动态注册Bean(导入与ImportBeanDefinitionRegistrar相关)处理。在解析器中,通过configClass.addImportBeanDefinitionRegistrar直接将ImportBeanDefinitionRegistrar作为配置类保存至ConfigClass中。

      

    对于dubbo自定义的注解也是@Import动态注册Bean的组合注解:

      

        

    同理,@Bean标记的Bean方法应该保存在beanMethos中。至此,与业务逻辑相关的bean定义全部保存到了configClasses中。最后通过loadBeanDefinitionsForConfigurationClass全部保存至beanDefinitionMap中。具体时序图如下:              

      

    接下来的处理才是真正的实例化处理:

    4、bean实例化

    非懒加载的实例化均在refresh#finishBeanFactoryInitialization中,跟踪调试大致流程如下:

      

    如果有代理实例化前利用beanPostProcessor将原有bean替换为目标对象返回,没有则直接利用反射实例化对象。关键部分如下:

      

      

      

      

      

    

Spring Bean配置加载为BeanDefinition全过程(注解配置)的更多相关文章

  1. Spring Bean 的加载过程

    Spring Bean 的加载过程 一个是populateBean,一个是initializeBean,这两个方法完成了bean的赋值与初始化. 这里有一个BeanDefinitionValueRes ...

  2. Spring Bean 的加载顺序

    一,单一Bean 装载 1. 实例化; 2. 设置属性值; 3. 如果实现了BeanNameAware接口,调用setBeanName设置Bean的ID或者Name; 4. 如果实现BeanFacto ...

  3. Spring Bean的加载

    Spring加载bean的原则:不等bean创建完成就会将创建bean的ObjectFactory提早曝光加入到缓存中.   单例bean在Spring容器里只会创建一次,后续创建时会首先从缓存中获取 ...

  4. BeanDefinitionLoader spring Bean的加载器

    spring 容器注册bean , 会把bean包装成beanDefinition 放进spring容器中,beanDefinitionLoader就是加载bean的类 . 一.源码 class Be ...

  5. spring bean容器加载后执行初始化处理@PostConstruct

    先说业务场景,我在系统启动后想要维护一个List常驻内存,因为我可能经常需要查询它,但它很少更新,而且数据量不大,明显符合缓存的特质,但我又不像引入第三方缓存.现在的问题是,该List的内容是从数据库 ...

  6. 1. Spring基于xml加载和读取properties文件配置

    在src目录下,新建test.properties配置文件,内容如下 name=root password=123456 logArchiveCron=0/5 * * * * ? 一种是使用sprin ...

  7. Java实现配置加载机制

    前言 现如今几乎大多数Java应用,例如我们耳熟能详的tomcat, struts2, netty…等等数都数不过来的软件,要满足通用性,都会提供配置文件供使用者定制功能. 甚至有一些例如Netty这 ...

  8. Spring源码加载BeanDefinition过程

    本文主要讲解Spring加载xml配置文件的方式,跟踪加载BeanDefinition的全过程. 源码分析 源码的入口 ClassPathXmlApplicationContext构造函数 new C ...

  9. 【Spring】详解Spring中Bean的加载

    之前写过bean的解析,这篇来讲讲bean的加载,加载要比bean的解析复杂些,该文之前在小编原文中有发表过,要看原文的可以直接点击原文查看,从之前的例子开始,Spring中加载一个bean的方式: ...

随机推荐

  1. Flowable实战(五)表单和流程变量

    一.流程变量   流程实例按步骤执行时,需要保存并使用一些数据,在Flowable中,这些数据称为变量(variable).   流程实例可以持有变量,称作流程变量(process variables ...

  2. 使用 Json Schema 定义 API

    本文地址:使用 Json Schema 定义 API 前面我们介绍了 Json Schema 的基本内容,这篇文章我们结合 jsonschema2pojo 工具深入分析如何使用 Json Schema ...

  3. Linux中的一些基本命令

    文章目录 ls cd Linux的目录 文件的权限 1.用户,组,权限 2.文件的权限 文件的基本操作 增:创建文件 删:删除文件 改:修改文件 查:查看 vi/vim 是一个编辑工具,主要用来编辑文 ...

  4. CentOS 7安装Odoo 15社区版的详细操作指南

    我之前的文章介绍过在Windows环境下安装Odoo 15,如果您需要在Windows部署,具体可参考我文末的微信号<10分钟教你本机电脑安装Odoo 15,并启用一个内置的项目APP应用> ...

  5. 【刷题-LeetCode】188 Best Time to Buy and Sell Stock IV

    Best Time to Buy and Sell Stock IV Say you have an array for which the i-th element is the price of ...

  6. 外观模式(Facade模式)

    外观模式的定义与特点 外观(Facade)模式又叫作门面模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式.该模式对外有一个统一接口,外部应用程序不用关心内部子系 ...

  7. golang中文件和路径用法

    package main import ( "fmt" "io/fs" "io/ioutil" "os" "p ...

  8. Nginx代理的方式(反向代理)

    目录 一:Nginx 正向代理与反向代理 1.什么是代理服务器? 2.正向代理的概念 3. 反向代理的概念 二:Nginx代理服务支持的协议 三:Nginx代理实践 1.部署web01 2.部署lb0 ...

  9. Android安卓开发一环境配置

    安卓项目开发 我采用的安卓开发软件是IDEA,IDEA功能强大,具有集成的安卓开发环境. 安卓开发的首要任务是在IDEA配置安卓开发环境 第一步新建一个安卓项目 按照提示完成操作,首次建立安卓项目它会 ...

  10. SpringBoot使用异步线程池实现生产环境批量数据推送

    前言 SpringBoot使用异步线程池: 1.编写线程池配置类,自定义一个线程池: 2.定义一个异步服务: 3.使用@Async注解指向定义的线程池: 这里以我工作中使用过的一个案例来做描述,我所在 ...