Spring 源码(18)Spring IOC 容器的创建总结
Spring IOC Bean对象的创建总结
根据前面的介绍,可以进行Spring IOC容器创建Bean的总结:
- 调用构造函数启动,调用过程中父类会忽略调用三个
Aware
接口,BeanNameAware
,BeanClassloaderAware
,BeanFactoryAware
。 - 环境准备,
Environment
- 实现类
StandardEnvironment
,调用System.getenv()
获取系统环境变量,比如配置的java
环境变量等,调用System.getProperties()
获取到的系统属性变量,比如当前系统的名称,版本号等。
- 实现类
- 刷新容器,
AbstractApplicationContext#refresh
- 这个类是
BeanFactory
的实现类,refresh
方法是Spring IOC
容器启动的关键 - 整个
IOC
容器的生命周期都是围绕着这10几个方法进行展开的
- 这个类是
- 创建
IOC
容器并加载BeanDefinition
,调用obtainBeanFactory
方法- 创建一个默认的
BeanFactory
,DefaultListableBeanFactory
- 加载
xml
中配置的Bean
对象,调用loadBeanDefinitions
方法 - 默认会创建一个
BeanDefinitionReader
进行读取 - 创建解析器,用于
dtd
文件和xsd
文件的,默认会加载MATE-INF/spring.schemas
文件和MATE-INF/spring.handlers
文件 - 解析传入的
xml
文件,解析过程中文件资源变化:String[] -->String --> Resource[] --> Resource
,不断的调用重载的方法loadBeanDefinitions
,最终解析成Document
- 将解析的
Document
文件遍历元素Element
,会解析两种元素,一种是默认的,调用parseDefaultElement
,比如解析bean
标签,另一种是定制的,调用parseCustomElement
,比如解析contex:compent-scan
,util:map
标签等 - 解析完之后会创建一个
GenericBeanDefinition
放入beanDefinitionMap
和beanDefinitionNames
集合中
- 创建一个默认的
- 准备容器,调用
prepareBeanFactory
方法- 创建一个默认的
Spel
表达式解析器,StandardBeanExpressionResolver
- 添加一个属性编辑器的注册器,
ResourceEditorRegistrar
- 添加一个
BeanPostProcessor
实现类,ApplicationContextAwareProcessor
,用于执行6的忽略的Aware
接口 - 忽略6个
Aware
接口,EnvironmentAware
,EmbeddedValueResolverAware
,ResourceLoaderAware
,ApplicationEventPublisherAware
,MessageSourceAware
,ApplicationContextAware
- 创建一个默认的
- 执行
BeanFactoryPostProcessor
,调用invokeBeanFactoryPostProcessors
方法- 先解析传入的
BFPP
接口实现类,在解析容器中的BFPP
- 先解析
BeanDefinitionRegistryPostProcessor
接口实现,在解析BeanFactoryPostProcessor
接口实现 - 解析到
BDRPP
,就直接调用postProcessBeanDefinitionRegistry
方法,使用集合分别存储BDRPP
的接口和BFPP
的接口 - 解析时按照
PriorityOrdered
接口,Ordered
接口,无序的顺序进行解析,执行也是按照这个顺序执行 - 循环遍历执行
BDRPP
接口方法postProcessBeanDefinitionRegistry
,BFPP
的方法postProcessBeanFactory
- 遍历解析
BDRPP
时会执行到注解的解析类ConfigurationClassPostProcessor
- 解析
@Component
注解,解析@ComponentScans
、@ComponentScan
注解,解析@PropertySources
、@PropertySource
注解,解析@ImportResouce
注解,解析@Import
注解,解析@Bean
注解 - 解析完之后将解析到的
BeanDefinition
创建为GenericBeanDefinition
,然后加入到beanDefinitionMap
和beanDefinitionNames
集合中
- 解析
- 先解析传入的
- 执行
BeanPostProcessor
的注册,调用registerBeanPostProcessors
方法- 解析过程跟解析
BFPP
逻辑类似,只是BPP
只是进行了注册,调用了addBeanPostProcessor
方法
- 解析过程跟解析
- 执行国际化设置,多播器设置,监听器注册
- 执行剩余的非懒加载的单例的初始化,调用
finishBeanFactoryInitialization
方法- 加载一个转换服务,
ConversionService
,用于类型转换使用 - 添加一个默认的占位符解析器,
PropertySourcesPlaceHolderConfigurer
- 冻结
BeanDefinition
的元数据 - 实例化所有的非懒加载的单例
Bean
,调用preInstantiateSingletons
方法- 遍历所有的
BeanDefinition
开始创建Bean
- 合并
BeanDefinition
- 判断是否是
FactoryBean
,如果是则后续通过getObject
方法进行创建Bean
,如果是的单例的然后放入缓存中,下次使用直接获取 - 调用
getBean
方法获取Bean
对象 - 调用
doGetBean
- 调用
getSingleton
获取bean
- 首先是从一级缓存
singletonObjects
中获取,如果有则直接返回 - 一级缓存中没有,并且当前
Bean
正在创建,先从一级缓存再获取一次,没有的话那么从二级缓存earlySingletonObjects
中获取,如果有则直接返回 - 二级缓存中没有,那么就从三级缓存
singletonFactories
中获取,获取到之后放在二级缓存中,然后删除三级缓存的Bean
- 首先是从一级缓存
- 如果获取到
bean
对象,那么就去检查是否是FactoryBean
对象,如果不是直接返回,否则判断是否带有&
符号,如果带了那么就直接返回,没有带&
那么就会调用缓存获取,获取不到就会执行getObject
方法进行创建对象,如果是单例的就会存入缓存中 - 判断
bean
的创建类型,如果是单例的,那么就会调用getSingleton
方法,然后入参传入一个lambda表达式进行创建,lambda
表达式是一个ObjectFactory
接口,首先将bean
加入到正在创建的集合中,然后调用getObject
方法触发lambda表达式中的createBean
方法,最终创建完之后加入到一级缓存中,并且从正在创建的集合中移除 - 调用
createBean
方法- 解析
Bean
的类型 - 判断是否进行方法覆盖,如果需要则进行方法覆盖,比如配置了
lookup-method
,replace-method
标签,方法覆盖的作用是单例对象引用多例对象的场景下使用 - 给一个机会对实现了
InstantiationAwareBeanPostProcessor
接口的Bean进行对象的创建,会调用到postprocessBeforeInstantiation
方法进行提前实例化 - 如果没有提前创建对象,那么会调用
doCreateBean
方法 - 调用
doCreateBean
方法- 先进行实例化创建对象,调用
createBeanInstance
方法- 判断
BeanDefinition
是否设置了supplier
,如果设置了那么就通过supplier
进行实例化 - 判断
BeanDefinition
是否配置了factory-method
,如果配置了那么会使用静态工厂或者实例工厂进行对象的实例化创建,静态工厂是直接调用静态方法进行对象的获取,实例工厂是需要配置factory-bean
标签进行配合,然后调用factory-bean
指定的bean
的方法进行对象的获取 - 如果上面的两种都没有,那么判断是否解析过,如果解析过就会调用反射去实例化创建
- 首先是获取一个对象实例化策略,然后调用
instantiate
方法进行反射创建 - 创建之后将对象包装到
BeanWrapper
包装器中 - 然后初始化
bean
的包装器,里面是设置了转换服务ConversionService
,还有就是对象的属性编辑器的注册PropertyEditorRegistrar
,这两个用于后面进行属性填充时对属性值进行解析
- 首先是获取一个对象实例化策略,然后调用
- 如果上面的不满足,那么就会通过
SmartInstantiationAwareBeanPostProcessor
去获取构造函数,然后进行自动构造实例化对象 - 如果也不是,那么就直接调用反射进行创建,创建的是通过无参构造函数进行创建的
- 最后会将创建的对象封装到
BeanWrapper
中,然后进行Bean
的包装,比如设置转换服务ConversionService
和属性编辑器PropertyEditorRegistrar
,这里的转换服务和属性编辑器都是可以在自定义的,不过Spring
内置了很多,大多数场景下都可以不用自己写,使用Spring
提供的都完全够用了
- 判断
- 合并
BeanDefinition
- 这里会调用
BeanPostProcessor
的子接口MergedBeanDefinitionPostProcessor
进行合并,主要是为了解析BeanDefinition
中的其他注解,比如@Value
、@Autowired
、@Resource
、@PostConstruct
、@PreDestory
等注解 MergedBeanDefinitionPostProcessor
接口的实现比较重要的有AutowiredAnnotationBeanPostProcessor
、CommonAnnotationBeanPostProcessor
、InitDestroyAnnotationBeanPostProcessor
这几各类,他们主要完成了上面提到的几个注解的解析- BeanPostProcessor接口下多个子接口:
InstantiationAwareBeanPostProcessor
、SmartInstantiationAwareBeanPostProcessor
、MergedBeanDefinitionPostProcessor
、DestructionAwarePostProcessor
,这些接口都比较重要
- 这里会调用
- 提前暴露
Bean
(主要是用于解决循环依赖)- 先判断
Bean
是否是单例的,是否允许循环依赖,是否单例Bean
正在创建 - 如果条件满足,那么就调用
addSingletonFactory
,传入一个lambda
表达式,传入的是一个ObjectFactory
接口,里面调用的是SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference
方法,这个方法会在后面的属性填充时从缓存中获取不到Bean时进行调用,如果没有进行代理,那么会直接返回,不会执行getEarlyBeanReference
方法
- 先判断
- 属性填充
populateBean
- 给机会使用
InstantiationAwareBeanPostProcessor
对Bean
进行修改,会调用postProcessAfterInstantiation
方法 - 根据注入方式进行属性注入,按类型还是按名称两种
- 判断是否存在
InstantiationAwareBeanPostProcessor
接口的实现,如果存在那么会调用postProcessProperties
方法进行属性的填充,比如属性标了@Autowired
、@Resource
注解的属性 - 属性值处理
- 获取前面步骤解析的属性字段和属性值
- 获取属性值解析器
BeanDefinitionValueResolver
- 循环遍历解析属性,使用属性值解析器解析
- 判断属性值是什么类型的,比如
RuntimeReference
、BeanDefinition
、Set
、List
、Map
、Array
、String
等类型 - 根据类型会进行类型的转换,最终会调用到前面添加的属性编辑器
PropertiesEditorRegistrar
或者转换服务ConversionService
进行类型的转换 - 也可能会调用前面添加的
Spel
表达式解析器进行解析 - 这里会存在大量的递归调用
- 判断属性值是什么类型的,比如
- 给机会使用
- 初始化
Bean
--->initializeBean
- 执行
Aware
方法,invokeAwareMethods
,这里只会执行三个Aware
方法- 执行
BeanNameAware
接口 - 执行
BeanClassLoaderAware
接口 - 执行
BeanFactoryAware
接口
- 执行
- 调用
BeanPostProcessor
的before
方法- 这里会调用到两个比较重要的类,一个是
ApplicationContextAwareProcessor
执行另外的6个Aware
接口,一个是InitDestoryAnnotationBeanPostProcessor
接口执行@PostConstruct
注解标记的方法
- 这里会调用到两个比较重要的类,一个是
- 调用初始化方法
invokeInitMethods
- 如果
bean
实现了InitializingtionBean
,那么就去调用它的afterPropertiesSet
方法 - 如果自定义了
init-method
方法,那么就去调用自定义的初始化方法
- 如果
- 调用
BeanPostProcessor
的after
方法- 主要是调用
AbstractAutoProxyCreator
进行aop
的动态代理的调用,也是实现aop
的关键
- 主要是调用
- 执行
- 先进行实例化创建对象,调用
- 解析
- 调用
- 遍历所有的
- 加载一个转换服务,