> 文章列表 > Spring Bean实例化和初始化的过程

Spring Bean实例化和初始化的过程

Spring Bean实例化和初始化的过程

承接上文Spring Bean生命周期

应用程序在运行过程中能否去读取当前系统的环境变量或系统属性?

这里涉及到一个非常重要的接口Environment,

System.getenv,System.getProperties都是获取当前系统环境变量,

Environment接口的实现类AbstractEnvironment,AbstractEnvironment的实现类StandardEnvironment,

Spring Bean实例化和初始化的过程
Spring Bean实例化和初始化的过程

在当前容器运行之前或运行前置的某些方法里面的时候,就会调用这些方法将环境变量或系统属性放到environment里面去,方便应用程序后续进行调用,比如springmvc init-param指定的初始化方法读取环境变量之后,放到environment中去,这就是environment对象存在的意义。

AbstractApplicationContext这个类refresh方法中包含13个方法,refresh是Spring框架最核心的方法之一,

执行下面的代码,debug来看下创建对象的过程,

Spring Bean实例化和初始化的过程
Spring Bean实例化和初始化的过程

super调用父类的构造方法,相当于做了一些属性值的设置,

Spring Bean实例化和初始化的过程

设置xml配置文件路径,方便后面进行读取和加载。

refresh方法调用prepareRefresh是刷新前的准备工作:设置关闭和活跃的标志位。

细节的东西不想看,没关系,但要知道这个是前期做一些准备工作,方便后面创建对象。

Spring Bean实例化和初始化的过程

配置文件经过读取之后要放到容器里面去,所以第一步先应该有对应的容器工厂或者有bean工厂,当有了BeanFactory之后,才能进行相关的加载工作,所以第一步应该先创建一个容器,当把容器创建好了之后,下一步才读取配置文件。

Spring Bean实例化和初始化的过程

obtainFreshBeanFactory.refreshBeanFactory,这个方法里面,先判断容器里面有没有bean工厂,如果有的话,销毁掉,如果没有的话,先创建一个bean工厂,因为需要先有bean工厂之后,才能完成当前对象的加载工作。

有了bean工厂之后,设置下序列化的id和自定义配置下工厂的属性值,这样就完成了整个工厂的创建工作。

当完成创建工作之后,第二步loadBeanDefinitions是加载配置文件,因为这个配置文件中有1个bean,所以当执行完这样的加载工作之后,beanDefinitionMap和beanDefinitionNames里面有一个bean,

Spring Bean实例化和初始化的过程

目前已经把bean对象转换成了bean definition了,下一步该调用beanFactoryPostProcessor进行增强处理,

Spring Bean实例化和初始化的过程

prepareBeanFactory给beanfactory做准备工作,因为刚刚new了一个对象,还没有给beanFactory做任何属性赋值操作,这个方法就是给beanFactory做一些初始化工作即给当前的beanFactory设置某些具体的属性值。

Spring Bean实例化和初始化的过程
Spring Bean实例化和初始化的过程

这是一个模版方法,留给子类进行扩展的。

Spring Bean实例化和初始化的过程

接下来执行beanFactoryPostProcessor,当这个步骤执行完了之后,下一步该实例化了,

在进行实例化的时候,相对而言会比较复杂,实例化的时候包含非常多的步骤。

在实例化之前需要做什么准备工作?

要提前把后面需要用到的beanPostProcessor准备好,如果想在整个bean的spring生命周期里面,在不同的阶段做不同的处理工作,监听器 、监听事件、多播器等这些东西都要提前准备好,只有把这些准备好之后,才能进行后续的调用工作,这是一整个流程,不可能用的时候再准备。

Spring Bean实例化和初始化的过程

这一步是注册beanPostProcessor,这是还没有执行,只是先提前准备好。

Spring Bean实例化和初始化的过程

如果是SpringMVC项目,messagesource就是用来做国际化的操作的。

Spring Bean实例化和初始化的过程

初始化当前应用程序的事件多播器,

Spring Bean实例化和初始化的过程

注册监听器。

在实例化之前所有需要做的准备工作都做完了,这几个方法都是预先的准备工作。

Spring Bean实例化和初始化的过程

接下来该实例化了,实例化所有剩下的非懒加载的单例对象,

finishBeanFactoryInitialization.preInstantiateSingletons该方法是实例化剩下的单例对象,终于要开始实例化了。

当前容器里面有一个bean,目标是把这个bean放到一个集合里面去。

首先看容器里面有没有这个bean,

getBean(beanName).doGetBean
Spring Bean实例化和初始化的过程

默认情况下都是单例的,

Spring Bean实例化和初始化的过程
Spring Bean实例化和初始化的过程

通过反射的方式创建具体的bean对象,

Spring Bean实例化和初始化的过程

获取到对应的构造器对象,

Spring Bean实例化和初始化的过程
Spring Bean实例化和初始化的过程

获取实例化的策略并且进行实例化,

Spring Bean实例化和初始化的过程
Spring Bean实例化和初始化的过程

获取到构造器并实例化,

Spring Bean实例化和初始化的过程

实例化的时候,只是在堆中开辟内存空间并没有给属性赋值,

Spring Bean实例化和初始化的过程

接下来是填充属性,

Spring Bean实例化和初始化的过程

在执行populateBean方法之前,当前bean对象这3个值都等于空,

Spring Bean实例化和初始化的过程

执行完之后,name完成了属性填充,但beanName不会填充,因为beanName是aware接口,现在还没有执行Aware接口的实现类,

Spring Bean实例化和初始化的过程

接下来执行这些实现了aware接口的方法,

Spring Bean实例化和初始化的过程

此时beanName就有了,为什么environment没有设置?

Spring Bean实例化和初始化的过程

因为在prepareBeanFactory方法中对这个Aware接口进行了忽略,

Spring Bean实例化和初始化的过程
Spring Bean实例化和初始化的过程

本身的invokeAwareMethods方法也没有对EnvironmentAware进行处理,

Spring Bean实例化和初始化的过程
Spring Bean实例化和初始化的过程

调用每个postProcessBeforeInitialization方法,

Spring Bean实例化和初始化的过程

执行到这里,此时就已经是一个完整的对象了,

Spring Bean实例化和初始化的过程

即执行完getBean(beanName)得到了一个完整的对象了。

因为当前集合里面只有一个对象,所以此时循环就结束了,当前这个bean完成了实例化且初始化。