目录
前言
本文参考大量网上博主博文,以及郝佳老师的作品总结而成
1. Spring生命周期
以XML配置方式,整个生命周期大致可分为以下几步
- 初始化容器
- Bean属性注入、更改以及初始化
- 容器、Bean初始化成功,开始调用
- 关闭容器、销毁Bean
1.1 初始化容器
该部分即为Bean提供一个容器环境,先有容器再有Bean,否则Bean将无从存放
- 准备更新容器
- ClassPathXmlApplicationContext启动,为解析XML做准备
- 加载XML配置文件
- 调用BeanFactoryPostProcessor实现类构造器
- BeanFactoryPostProcessor调用postProcessBeanFactory方法
- 调用BeanPostProcessor实现类构造器
- 调用InstantiationAwareBeanPostProcessorAdapter实现类构造器
- DefaultListableBeanFactory
- InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法
- 容器初始化成功!
1.2 Bean属性注入、更改以及初始化
- 调用Bean的构造器进行实例化
- InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法
- 属性注入
- 调用BeanNameAware.setBeanName
- 调用BeanFactoryAware.setBeanFactory()
- BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改
- 调用InitializingBean.afterPropertiesSet()
- 调用bean的init-method属性指定的初始化方法
- BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改
- InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法
- 整个容器加载Bean完成,Bean可以使用了!
1.3 Bean的使用
这部分主要依据使用者而言,暂不描述
1.4 关闭容器、销毁Bean
- 调用DiposibleBean.destory()
- 调用bean的destroy-method属性指定的初始化方法
整个Bean从生产到灭亡走完了全部流程
整个Spring生命周期可分为四个部分
- Bean自身方法调用
- Bean级生命周期接口方法调用
- 容器即生命方法调用
- 工厂后处理接口方法调用
1.5 Bean的生命周期:
- Spring 容器 从 XML 文件中读取 bean 的定义,并实例 化 bean。
- Spring 根据 bean 的定义填充所有的属性。
- 如果 bean 实现了 BeanNameAware 接口,Spring 传 递 bean 的 ID 到 setBeanName 方法。
- 如果 Bean 实现了 BeanFactoryAware 接口, Spring 传递 beanfactory 给 setBeanFactory 方法。
- 如果有任何与 bean 相关联的 BeanPostProcessors, Spring 会在 postProcesserBeforeInitialization()方法 内调用它们。
- 如果 bean 实现 IntializingBean 了,调用它的 afterPropertySet 方法,如果 bean 声明了初始化方 法,调用此初始化方法。
- 如果有 BeanPostProcessors 和 bean 关联,这些 bean 的 postProcessAfterInitialization() 方法将被调用。
- 如果 bean 实现了 DisposableBean,它将调用 destroy()方法
2. Spring如何解决bean的循环依赖
所谓的循环依赖是指在运行状态下,a调用b,b调用a的情况,即两个或者多个bean互相调用的情况。spring将循环依赖分成三部分:setter循环依赖和容器循环依赖以及构造器循环依赖。
2.1 容器循环依赖:
表示通过构造器注人构成的循环依赖,此依赖是无法解决的,只能抛出BeanCurentlyInCreationException异常表示循环依赖,对于创建完毕的bean将从当前创建bean池中删除、被清理掉。
2.2 setter循环依赖
表示通过setter方法注入构成的循环依赖。而对于setter注入造成的循环依赖是通过提前暴露钢完成构造器注入但未完成其他步骤(如setter注入)的bean来完成的,而且只能解决单力作用域bean的循环依赖。即提前暴露一个单例工厂方法,从而使其他bean能够引用到该bean
2.3 构造器循环依赖
对于“prototype" 作用域bean, Spring 容器无法完成依赖注人,因为Spring容器不进行缓存"prototype”作用域的bean,因此无法提前暴露-个创建中的bean。对于“singleton" 作用域bean,可以通过“setAllowCircularReferences(false ); "来禁用循环
3. Bean的加载过程
- 转换对应的beanName
- 尝试从缓存中加载单例,也就是说单例在Spring的同一个容器只会被创建一次,后续在获取bean的话,就直接从单例缓存中获取
- bean的实例化
- 原型模式的以来坚持
- 检测parentBeanFactory
- 将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition,因为从XML配置文件中读取到的Bean信息是存储在前者中的,但是后续Bean处理都是针对于后者的,所以要进行一个转换
- 寻找依赖
- 针对不同的scope进行bean的创建
- 类型转换
4. BeanFactory和FactoryBean的区别
顾名思义,BeanFactory是工厂,代表接口用于管理Bean
FactoryBean是Bean,即交由SpringIOC管理的对象,对FactoryBean而言,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,
5. Bean注册与使用
- 注册Bean有@Component , @Repository , @ Controller , @Service , @Configration等注解,这些注解注解都是把你要实例化的对象转化成一个Bean,放在IoC容器中,等你要用的时候,它会和上面的@Autowired , @Resource配合到一起,把对象、属性、方法完美组装。
- 使用Bean,即是把已经在xml文件中配置好的Bean拿来用,完成属性、方法的组装;比如@Autowired , @Resource,可以通过byTYPE(@Autowired)、byNAME(@Resource)的方式获取Bean
2.1 @Autowired
Autowired注解默认按类型装配(即这个注解是属于spring的),默认情况下必须要求依赖对象必须存在,如果要允许null 值,可以设置它的required属性为false,如:@Autowired(required=false)
Autowired是按照ByType注解使用的bean而ByType的意思是如果容器中存在一个与指定属性类型相同的bean,那么将与该属性自动装配。就是查找构造器或者方法中的参数,参数的类型匹配了就注入。
2.2 @Resource
Resource这个注解是属于J2EE的,默认安照名称进行装配,名称可以通过name属性进行指定,
Resource注解通过属性名称自动装配。spring会检查set方法,比如你有一个setMaster(),这个方法提供注入,那相应的Bean name或者id 为master的Bean 就会被注入到协作者(就是类里面你所定义的引用型成员)中
6. 参考:
简书,作者Chandler Qian https://www.cnblogs.com/zrtqsk/p/3735273.html
《Spring源码深度解析》,作者 郝佳