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的生命周期,我们从两个层面分别来看待,第一个是源码层面,第二个是方法层面;
@Component
public class X {
//构造方法
public X(){
System.out.println("X create");
}
//生命周期初始化回调方法
@PostConstruct
public void zinit(){
System.out.println("call z lifecycle init callback");
}
}
其中,执行InvokeBeanDefinitionRegisterPostProcessors解析为BeanDefinition对象,并放置在beanDefinitionMap中
在AbstractApplicationContext中的finishBeanFactoryInitialization(beanFactory)方法中进行实例化bean的
这里,我们对第七步进行简单的分析一下:
这里主要针对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步就在上面的这个方法当中
其中的createBeanInstance()进行了该对象的实例化
上图说明spring是通过createBeanInstance(beanName, mbd, args),完成了推断构造方法和实例化的事情
首先以下从方法层面讲解Bean的生命周期还是指的是singleton bean,对prototype bean来说,没有缓存池存放,当用户getBean时,每一次获取新的原型实例对象,在获得prototype bean的实例后,IOC容器就不再对当前实例进行管理,而是把管理权交由用户,此后再getBean生成的是新的实例。对于request/session/application/websocket 这几种scope的bean我们在此不谈。
而在不同的容器中,Bean的生命周期开始的时间不同 :
我们以getBean(),即进行Bean的实例化开始进行Bean的生命周期的讲述 :
对于上面的方法,我们归纳为以下几类 :
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接口实现类,如下所示:
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的初始化方法前后,添加一些自己的处理逻辑。
初始化定义的方法 :
如果自定义了多个的BeanPostProcessor的实现类,通过实现Ordered接口,设置order属性,可以按照顺序执行实现类的方法。
Spring内置了一些BeanPostProcessor接口实现类,如下所示:
区别点 | ApplicationContext | BeanFactory |
---|---|---|
检测和加载BeanPostProcessor和BeanFactoryPostProcessor | 自动检测,加载 | 调用方法手动注册和加载 |
对于后置处理器的自定义排序 | 可以根据org.springframework.core包下的PriorityOrdered和Ordered来进行自定义排序 | 只是使用默认的 |
定义及加载配置文件 | IOC容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用;加载配置文件不会创建对象,在获取对象(或者使用的时候)才去创建对象.即延迟加载 | BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用,加载配置文件时候就会把在配置文件对象进行创建 |
功能扩展 | 应用上下文,继承BeanFactory接口,它是Spring的一各更高级的容器,提供了更多的有用的功能,例如 : 国际化,访问资源,消息发送,AOP等等 | 是Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能 |
在开发中我们统一使用ApplicationContext进行加载配置文件,因为它功能更加地强大! ! !