SpringBean的生命周期过程
Spring的Bean分为单例Bean(默认形式),多例Bean,以及懒加载的Bean,后两种Bean是在获取Bean对象的时候进行初始化,以下我总结的是Spring单例Bean的生命周期过程
首先我们需要知道两个概念:
1、spring bean——受spring容器管理的对象,可能经过了完整的spring bean生命周期(为什么是可能?难道还有bean是没有经过bean生命周期的?答案是有的,具体我们后面文章分析),最终存在spring容器(即spring单例池)当中;一个bean一定是个对象
2、对象——任何符合java语法规则实例化出来的对象,但是一个对象并不一定是spring bean;
其中SpringBean的生命周期,我们从两个层面分别来看待,第一个是源码层面,第二个是方法层面;
源码层面的SpringBean的生命周期过程
- 1:实例化一个ApplicationContext的对象;
- 2:调用bean工厂后置处理器完成扫描;
- 3:循环解析扫描出来的类信息;
- 4:实例化一个BeanDefinition对象来存储解析出来的信息;
- 5:把实例化好的beanDefinition对象put到beanDefinitionMap当中缓存起来,以便后面实例化bean;
- 6:再次调用bean工厂后置处理器;
- 7:当然spring还会干很多事情,比如国际化,比如注册BeanPostProcessor等等,如果我们只关心如何实例化一个bean的话那么这一步就是spring调用finishBeanFactoryInitialization方法来实例化单例的bean,实例化之前spring要做验证,需要遍历所有扫描出来的类,依次判断这个bean是否Lazy,是否prototype,是否abstract等等;
- 8:如果验证完成spring在实例化一个bean之前需要推断构造方法,因为spring实例化对象是通过构造方法反射,故而需要知道用哪个构造方法;
- 9:推断完构造方法之后spring调用构造方法反射实例化一个对象;注意我这里说的是对象、对象、对象 ! ! !这个时候对象已经实例化出来了,但是并不是一个完整的bean,最简单的体现是这个时候实例化出来的对象属性是没有注入,所以不是一个完整的bean;
- 10:spring处理合并后的beanDefinition
- 11:判断是否支持循环依赖,如果支持则提前把一个工厂存入singletonFactories——map(这里我们定义为三级缓存);
- 12:判断是否需要完成属性注入
- 13:如果需要完成属性注入,则开始注入属性【属性注入】
- 14:判断bean的类型回调Aware接口
- 15:调用生命周期回调方法【初始化方法init-method】
- 16:如果需要代理则完成代理
- 17:put到单例池——bean完成——存在spring容器当中
此时我们通过下面这段代码,debug走一遍X类的生命周期:
@Component
public class X {
//构造方法
public X(){
System.out.println("X create");
}
//生命周期初始化回调方法
@PostConstruct
public void zinit(){
System.out.println("call z lifecycle init callback");
}
}
第1步 : 实例化一个ApplicationContext的对象
第2步,第3步,第4步,第5步 : 调用bean工厂后置处理器完成扫描,解析类成BeanDefinition对象,并且put到beanDefinitionMap当中
其中,执行InvokeBeanDefinitionRegisterPostProcessors解析为BeanDefinition对象,并放置在beanDefinitionMap中
第6步 : 再次执行Bean工厂后置处理器完成Cglib代理【此时是BeanFactoryPostProcessor】
那么,我们的Spring是在何时进行实例化bean?
在AbstractApplicationContext中的finishBeanFactoryInitialization(beanFactory)方法中进行实例化bean的
第7步 : spring调用finishBeanFactoryInitialization方法来实例化单例的bean,实例化之前spring要做验证,需要遍历所有扫描出来的类,依次判断这个bean是否Lazy,是否prototype,是否abstract等等
这里,我们对第七步进行简单的分析一下:
第7步详解: 单例Bean的初始化过程(基于源码)—finishBeanFactoryInitialization(beanFactory)—preInstantiateSingletons()—getBean(beanName)
这里主要针对refresh()方法中的**finishBeanFactoryInitialization(beanFactory)**进行讲解,在这个方法中完成了所有单例Bean的实例化 :
而在finishBeanFactoryInitialization(beanFactory)方法内部,实现单例bean实例化的最重要的方法为preInstantiateSingletons()方法
其中该preInstantiateSingletons()方法是一个beanFactory下的一个接口方法,我们在它的实现类DefaultListableBeanFactory中进行了实现
其中,getBean(beanName)方法是抽象类AbstractBeanFactory的一个空方法,里面调用了doGetBean方法
我们进入这个doGetBean方法看看:
进入doGetBean()方法内部,我们就可以看到其中一个方法 getSingleton(beanName) :
//先从单例池中获取缓存中保存的单实例Bean。如果能获取到说明这个Bean之前被创建过(所有创建过的单实例Bean都会被缓存起来)
Object sharedInstance = getSingleton(beanName);
其中,getSingleton(beanName)方法的内部实现为:
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//首先会去我们的spring单例池中获取我们的beanName的bean实例是否存在 ?
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//首先去二级缓存中找
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//如果在我们的单例池和二级缓存均未能获取到我们的bean实例,会去三级缓存中,即singletonFactories中查找是否存在该对象
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//如果找到了该beanName的对象(此对象没有完成Bean的生命周期...)
singletonObject = singletonFactory.getObject(); //返回工厂对象,即半成品对象
this.earlySingletonObjects.put(beanName, singletonObject);//放到二级缓存中
this.singletonFactories.remove(beanName);//同时将其从singletonFactories中移除掉...
}
}
}
}
return singletonObject;
}
如果getSingleton(beanName)获取不到我们的bean实例,就会使用createBean()方法进行单例bean的创建过程,同样是在doGetBean()方法内部的
其中,createBean方法的内部实现为:
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
//通过RootBeanDefinition和beanName获取该bean实例的class类信息
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
//让BeanPostProcessors拦截返回代理对象---InstantiationAwareBeanPostProcessors提前执行
//第一次调用后置处理器
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
//使用doCreateBean创建bean(重点...)
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
我们回到生命周期的步骤上来,其中第8步,第9步就在上面的这个方法当中
doCreateBean(beanName, mbdToUse, args)方法 : 对应第8步,第9步
其中的createBeanInstance()进行了该对象的实例化
上图说明spring是通过createBeanInstance(beanName, mbd, args),完成了推断构造方法和实例化的事情
第10步:处理合并后的beanDefinition对象
第11步 : 进行了是否允许循环依赖的判断 : 如果支持则提前暴露一个工厂对象,注意是工厂对象
第12步:spring会判断是否需要完成属性注入(spring默认是需要的,但是程序员可以扩展spring,根据情况是否需要完成属性注入);如果需要则spring完成13步——属性注入,也就是所谓的自动注入;
第14,15,16步 : 判断bean的类型回调Aware接口,调用生命周期回调方法,如果需要代理则完成代理
- 第14步:判断bean的类型回调Aware接口
- 第15步:调用生命周期回调方法
- 第16步:如果需要代理则完成代理
默认情况 , 至此一个bean完成初始化,第17步被put到单例池,也是对上文说的17个步骤的一个证明;这说明一个bean在spring容器当中被创建出来是有一个过程的,这个过程就是所谓的bean的生命周期,我们的循环依赖也是在这个生命周内完成的。下面我们具体来分析这些步骤
方法层面的SpringBean的生命周期过程
首先以下从方法层面讲解Bean的生命周期还是指的是singleton bean,对prototype bean来说,没有缓存池存放,当用户getBean时,每一次获取新的原型实例对象,在获得prototype bean的实例后,IOC容器就不再对当前实例进行管理,而是把管理权交由用户,此后再getBean生成的是新的实例。对于request/session/application/websocket 这几种scope的bean我们在此不谈。
而在不同的容器中,Bean的生命周期开始的时间不同 :
- 对于ApplicationContext来说,当容器启动的时候,bean就已经实例化了。
- 对于BeanFactory来说,直到调用**getBean()**方法的时候才进行实例化。
我们以getBean(),即进行Bean的实例化开始进行Bean的生命周期的讲述 :
对于上面的方法,我们归纳为以下几类 :
- Bean自身的方法:比如构造函数、getter/setter以及init-method和destory-method所指定的方法等
- Bean级生命周期方法:可以理解为Bean类直接实现接口的方法,比如BeanNameAware、BeanFactoryAware、ApplicationContextAware、InitializingBean、DisposableBean等方法,这些方法只对当前Bean生效
容器级的方法(BeanPostProcessor一系列接口):主要是后处理器方法,比如上图的InstantiationAwareBeanPostProcessor、 - BeanPostProcessor接口方法:这些接口的实现类是独立于bean的,并且会注册到Spring容器中。在Spring容器创建任何Bean的时候,这些后处理器都会发生作用,在Bean初始化前后进行方法的调用
- 工厂后置处理器方法(BeanFactoryProcessor一系列接口):包括AspectJWeavingEnabler、CustomAutowireConfigurer、ConfigurationClassPostProcessor等。这些都是Spring框架中已经实现好的BeanFactoryPostProcessor,用来实现某些特定的功能。
其中:
BeanPostProcessor和BeanFactoryProcessor的区别
BeanFactoryProcessor :
public interface BeanFactoryPostProcessor {
//可以通过beanFactory获取bean定义信息
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
BeanFactoryPostProcessor接口是针对bean容器的,它的实现类可以在当前BeanFactory初始化(spring容器加载bean定义文件)后,bean实例化之前,即我们将BeanDefinition对象放置到beanDefinitionMap中以后修改bean的定义属性,达到影响之后实例化bean的效果。
也就是说,Spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据,并可以根据需要进行修改,例如:
可以把bean的scope从singleton改为prototype,也可以把property的值给修改掉,甚至可以修改beanClass属性等等.
可以同时配置多个BeanFactoryPostProcessor,并通过设置’order’属性来控制各个BeanFactoryPostProcessor的执行次序。
Spring内置了一些BeanFactoryPostProcessor接口实现类,如下所示:
BeanPostProcessor :
public interface BeanPostProcessor {
//bean初始化之前调用
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
//bean初始化之后调用
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
BeanPostProcessor能在spring容器实例化bean之后,在执行bean的初始化方法前后,添加一些自己的处理逻辑。
初始化定义的方法 :
- 实现InitializingBean接口的bean,对应方法为afterPropertiesSet
- xml文件中定义,使用init-method属性设置
- 注意 : 如果同时配置了,先执行接口的afterPropertiesSet方法,再执行配置文件中配置的init-method方法
如果自定义了多个的BeanPostProcessor的实现类,通过实现Ordered接口,设置order属性,可以按照顺序执行实现类的方法。
Spring内置了一些BeanPostProcessor接口实现类,如下所示:
ApplicationContext和BeanFactory的区别
区别点 | ApplicationContext | BeanFactory |
---|---|---|
检测和加载BeanPostProcessor和BeanFactoryPostProcessor | 自动检测,加载 | 调用方法手动注册和加载 |
对于后置处理器的自定义排序 | 可以根据org.springframework.core包下的PriorityOrdered和Ordered来进行自定义排序 | 只是使用默认的 |
定义及加载配置文件 | IOC容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用;加载配置文件不会创建对象,在获取对象(或者使用的时候)才去创建对象.即延迟加载 | BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用,加载配置文件时候就会把在配置文件对象进行创建 |
功能扩展 | 应用上下文,继承BeanFactory接口,它是Spring的一各更高级的容器,提供了更多的有用的功能,例如 : 国际化,访问资源,消息发送,AOP等等 | 是Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能 |
在开发中我们统一使用ApplicationContext进行加载配置文件,因为它功能更加地强大! ! !
Instantiation和Initialization
- Instantiation : 实例化,指的是调用构造函数进行实例化,即我们所说的new 对象,底层是利用反射 + 构造器实现的
- Initialization : 初始化,在Bean的声明周期中指的是init-method所指定的方法或者是InitializingBean.afterPropertiesSet()方法