概述
我们首先来看一下spring的大体架构图
BeanDefinition信息注册到BeanDefinitionRegistry流程
BeanDefinition在Spring中被设计为一个Bean的定义信息,其中包含是否懒加载,是否有依赖其他的Bean,是否单例等等,这些属性spring抽象出了一个类BeanDefinitionRegistry来进行管理,该类提供对BeanDefinition的增删改查功能。那我们现在来看看spring是如何用BeanDefinitionRegistry来管理BeanDefinition的
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestApp.class);
Cat bean = context.getBean(Cat.class);
System.out.println(bean);
}
Spring注册BeanDefinition的工具类
我们首先需要记住的一个最核心的点是:注册BeanDefinition到Registry是使用一个工具类的方法
在方法中其实就是调用了registry的注册方法
容器内部其实就是用一个map来保存映射关系
工具类在Spring中的注册过程
我们上面已经知道了Spring是通过一个工具类来注册,注册的本质其实也是把Bean的名称和定义信息存储在了一个map里面,那么我们现在就来看看spring是在什么时候把bean的定义信息存储到map里面去的。
- spring容器初始化之前先调用了一个初始化的方法,方法内部直接先
写死注册了几个对象注意看上图注册了一个
ConfigurationClassPostProcessor - 在refresh方法中,执行容器中所有
BeanFactoryPostProcessor的方法,其中就包含刚才硬编码进来的ConfigurationClassPostProcessor类,在该类中遍历所有的配置类然后调用自己的一个parser去解析每个配置找到这些配置包含的Bean并注册到容器中
小总结
这里需要知道spring有一个 BeanFactoryPostProcessor的生命周期接口,然后在初始化的时候会硬编码加载一个ConfigurationClassPostProcessor的对象,在refresh方法中会调用该方法的接口,在接口中就会扫描所有配置类然后去加载对应的bean到容器中。注意这里只是加载定义信息,并没有真正的初始化对象。
创建单实例Bean流程
我们刚才看的是Bean的定义信息已经被保存到spring中,我们现在来看看Spring创建实体对象的流程。
- 在
DefaultListableBeanFactory的preInstantiateSingletons方法中,遍历所有之前注册的BeanDefinition然后挨个初始化
2 spring让用户可以自定义创建bean到容器中,如果没有则spring自己创建,如果用户自己实现了InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation方法就可以自己返回bean
3. spring自己创建bean的流程会判断需不需要动态代理来不同方式创建bean(大概)
Bean创建对象总结
Bean属性赋值过程
在一开始我们看spring容器初始化的时候有看到硬编码注册了几个组件,其中还包括了AutowiredAnnotationBeanPostProcessor类,该类是用来做spring属性赋值的,该类也属于Bean后置处理器。
- 创建好bean之后调用populateBean来给bean属性赋值
- 获得bean的后置处理器找到
InstantiationAwareBeanPostProcessor对象调用方法 - 刚才注册的AutowiredAnnotationBeanPostProcessor就是属于该类,在方法中会找到每个类中的属性是否包含
@Autowired,或者@Value注解的属性,有就生成一个Metadata然后调用set方法
自定义赋值流程
在知道了spring是如何自动注入属性之后,我们还可以自定义给bean的属性赋值,还是看populateBean方法
在spring提供的后置处理器完成spring属性赋值之后,spring还提供了让用户可以自己给属性赋值的方式
如图只需要自定义
InstantiationAwareBeanPostProcessor,然后返回一个PropertyValuesspring就会自动给对象的属性赋值,内部也是invoke set方法。
属性赋值总结
spring在一开始的时候硬编码注入的组件AutowiredAnnotationBeanPostProcessor在初始化bean后开始寻找bean中属性上写了@Autowired和@value注解,然后注入对应的值,用户也可以实现自定义的后置处理器完成属性的注入
FactoryBean创建Bean流程
上面写的bean创建都是使用@Component注解然后被扫描到的创建bean,Spring还提供了FactoryBean的创建模式
FactoryBean创建的比较特殊,没有实现SmartFactoryBean并且isEagerInit为false的都是懒加载模式。回到一开始的方法,遍历所有定义信息创建bean的时候有判断是不是工厂
在真正容器获取bean的时候才开始根据类型来容器中寻找bean
spring根据类型寻找bean
spring容器提供根据类型寻找bean的名称的接口
该接口的实现是遍历所有bean的定义信息,然后判断类型是否匹配
在FactoryBean判断的时候,FactoryBean提供了一个接口返回类型用于对比