这篇文章是对前面几篇文章做一个小节,本篇不写一行代码,单纯的文字总结。
无论是基于xml配置文件方式还是基于@Configuration注解配置类方式,spring都是将我们配置的bean解析为BeanDefinition对象的,一个BeanDefinition就是对一个bean的定义,BeanDefinition存储了一个bean的类名、实例化这个bean将使用的构造参数及参数值、实例化这个bean时需要注入的字段名和字段的值等。
BeanDefinition的是对一个对象的描述,比如说你现在想让技术员帮你组装一台电脑,技术员就会向你询问你想要怎样的一台电脑,对cpu的要求、对显卡的要求是什么,以及对内存的要求等,然后技术员就会根据你的要求去给你组装电脑,你可能是跟朋友一起组装,要求同一样的配置。这时候,你对组装电脑的要求就是对电脑的定义,spring中对bean的定义就是BeanDefinition,如果你只是想要一台,那么技术员就只会给你组装一台,这就是单例,spring中bean工厂就相当于技术员的角色,而如果你是想要一样的配置组装多台电脑这就可以理解为原型。
如果是使用xml配置文件方式,那么spring首先会读取xml配置文件,将xml文件解析为一个个节点,然后获取配置文件中的节点,根据这些bean节点创建BeanDefinition对象。默认会使用无参数构造函数实例化目标bean,但如果这个bean在配置文件中指定了构造参数,那么这些构造参数的配置也会存储在BeanDefinition对象中,在实例化的时候spring就会寻找匹配的构造函数使用配置文件中配置的参数值来实例化这个bean。在xml文件中配置bean的时候构造参数和属性注入都可以是ref引用别的bean,这就是依赖,spring会保证在实例化这个bean之前先实例化依赖的bean。
使用注解配置类方式会有些不同,如果实例化AnnotationConfigApplicationContext应用上下文的时候使用的是指定注解配置类的构造方法,那么会先注册这个注解配置类到bean工厂,也就是将这个配置类解析为一个BeanDefinition对象注册到bean工厂,然后在refresh阶段先初始化bean工厂(做一些配置)之后再调用bean工厂后置处理器。上一篇介绍重点介绍了ConfigurationClassPostProcessor这个spring自己注入的bean,这也是一个bean工厂后置处理器。在bean工厂后置处理器ConfigurationClassPostProcessor中解析配置类的BeanDefinition对象,就是处理配置类上的注解和其方法体内的@Bean方法。
如果配置类(此时配置类已经是一个BeanDefinition对象)上有扫描包的注解就去扫描指定包,扫描指定包下被@Component等注解的类将其解析为BeanDefinition对象,最后将扫描的BeanDefinition结果集注册到bean工厂。如果扫描结果中有@Configuration注解配置类,后续还会继续解析扫描到的注解配置类(被@Configuration注解的BeanDefinition对象)。如果当前配置类有@Import注解,会先处理@Import导入的bean或者注解配置类。@Bean就相对复杂一点,这里就先不提。这是一个广度优先遍历,直到所有的bean都被注册以及所有的注解配置类都被解析处理。
如果bean配置了懒初始化,那么只有在我们调用工厂的getBean方法的时候才会去实例化这个bean,当然如果这个bean是单例的且其它bean会依赖这个bean,那么在其它bean实例化的时候也会将这个bean先实例化。
bean的实例化是根据beanName获取到其BeanDefinition对象,根据BeanDefinition对象中保存的bean的ClassName并使用bean工厂的类加载器来这个ClassName的Class对象,最后才调用这个Class对象的newInstance方法实例化bean。实例化bean完成之后还会使用BeanUtil工具类为其属性赋值,就是我们配置的这个bean需要注入的属性。
在bean实例化完成且注入属性值之后会调用配置的初始化方法(如果有initMethod或者这个bean实现了InitializingBean接口)。在调用初始化方法之前会先调用bean后置处理器BeanPostProcessor的postProcessBeforeInitialization方法,且在调用初始化方法完成之后会调用BeanPostProcessor的postProcessAfterInitialization方法。这些BeanPostProcessor可以不止一个,你可以注入多个,多个BeanPostProcessor都会被调用,且bean工厂中每个bean在调用初始化方法前后都会调用这些BeanPostProcessor。
前面几篇所讲的内容基本上也就那么多了,还有很多内容是没讲到的,因为spring的复杂并不是这么简短的文字就能说完的,不复杂又怎么会这么强大呢?还有spring的aop功能的实现,如果有时间我还会继续分析,但也可能会暂停下来而去学习新的技能:spring cloud。
如果本文有说得不对的地方还望指正。