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的关键
- 主要是调用
- 执行
- 先进行实例化创建对象,调用
- 解析
- 调用
- 遍历所有的
- 加载一个转换服务,


浙公网安备 33010602011771号