承接上文Spring Bean生命周期
应用程序在运行过程中能否去读取当前系统的环境变量或系统属性?
这里涉及到一个非常重要的接口Environment,
System.getenv,System.getProperties都是获取当前系统环境变量,
Environment接口的实现类AbstractEnvironment,AbstractEnvironment的实现类StandardEnvironment,
![](https://img-blog.csdnimg.cn/img_convert/558ec9d5bb65156fbfff835d93b385b0.png)
![](https://img-blog.csdnimg.cn/img_convert/d8ff0b1d625bf8d152381faa0c1f571a.png)
在当前容器运行之前或运行前置的某些方法里面的时候,就会调用这些方法将环境变量或系统属性放到environment里面去,方便应用程序后续进行调用,比如springmvc init-param指定的初始化方法读取环境变量之后,放到environment中去,这就是environment对象存在的意义。
AbstractApplicationContext这个类refresh方法中包含13个方法,refresh是Spring框架最核心的方法之一,
执行下面的代码,debug来看下创建对象的过程,
![](https://img-blog.csdnimg.cn/img_convert/f5bee32f7e16e94beda238f757f322e8.png)
![](https://img-blog.csdnimg.cn/img_convert/471212fa59f13a51af75f23bc0494ac4.png)
super调用父类的构造方法,相当于做了一些属性值的设置,
![](https://img-blog.csdnimg.cn/img_convert/3ce5e8899d6e594a1144453dcab8a1e1.png)
设置xml配置文件路径,方便后面进行读取和加载。
refresh方法调用prepareRefresh是刷新前的准备工作:设置关闭和活跃的标志位。
细节的东西不想看,没关系,但要知道这个是前期做一些准备工作,方便后面创建对象。
![](https://img-blog.csdnimg.cn/img_convert/3d46296fd8939562a391785b6d88582a.png)
配置文件经过读取之后要放到容器里面去,所以第一步先应该有对应的容器工厂或者有bean工厂,当有了BeanFactory之后,才能进行相关的加载工作,所以第一步应该先创建一个容器,当把容器创建好了之后,下一步才读取配置文件。
![](https://img-blog.csdnimg.cn/img_convert/52d68266e54c5120336cf677cd7fbd50.png)
obtainFreshBeanFactory.refreshBeanFactory,这个方法里面,先判断容器里面有没有bean工厂,如果有的话,销毁掉,如果没有的话,先创建一个bean工厂,因为需要先有bean工厂之后,才能完成当前对象的加载工作。
有了bean工厂之后,设置下序列化的id和自定义配置下工厂的属性值,这样就完成了整个工厂的创建工作。
当完成创建工作之后,第二步loadBeanDefinitions是加载配置文件,因为这个配置文件中有1个bean,所以当执行完这样的加载工作之后,beanDefinitionMap和beanDefinitionNames里面有一个bean,
![](https://img-blog.csdnimg.cn/img_convert/6441150a4038343ae7df6d2f46ed28fe.png)
目前已经把bean对象转换成了bean definition了,下一步该调用beanFactoryPostProcessor进行增强处理,
![](https://img-blog.csdnimg.cn/img_convert/b4a94034be9755658008fd7fbcc5778e.png)
prepareBeanFactory给beanfactory做准备工作,因为刚刚new了一个对象,还没有给beanFactory做任何属性赋值操作,这个方法就是给beanFactory做一些初始化工作即给当前的beanFactory设置某些具体的属性值。
![](https://img-blog.csdnimg.cn/img_convert/b3c07923876af61d06ec754541b1ac0c.png)
![](https://img-blog.csdnimg.cn/img_convert/9eb924110174c3269f8c99cf70e67949.png)
这是一个模版方法,留给子类进行扩展的。
![](https://img-blog.csdnimg.cn/img_convert/fd4b56084a675b150fcc526565ab071a.png)
接下来执行beanFactoryPostProcessor,当这个步骤执行完了之后,下一步该实例化了,
在进行实例化的时候,相对而言会比较复杂,实例化的时候包含非常多的步骤。
在实例化之前需要做什么准备工作?
要提前把后面需要用到的beanPostProcessor准备好,如果想在整个bean的spring生命周期里面,在不同的阶段做不同的处理工作,监听器 、监听事件、多播器等这些东西都要提前准备好,只有把这些准备好之后,才能进行后续的调用工作,这是一整个流程,不可能用的时候再准备。
![](https://img-blog.csdnimg.cn/img_convert/27a378e4f88e4eba5994aa12b4ed9fbb.png)
这一步是注册beanPostProcessor,这是还没有执行,只是先提前准备好。
![](https://img-blog.csdnimg.cn/img_convert/5e2614000f1098123a4a6e74db336513.png)
如果是SpringMVC项目,messagesource就是用来做国际化的操作的。
![](https://img-blog.csdnimg.cn/img_convert/eb46ecb435ba2d4c8c7e105ce35d5878.png)
初始化当前应用程序的事件多播器,
![](https://img-blog.csdnimg.cn/img_convert/01c341d494c2529e6ce588c6f4e474b5.png)
注册监听器。
在实例化之前所有需要做的准备工作都做完了,这几个方法都是预先的准备工作。
![](https://img-blog.csdnimg.cn/img_convert/d7474497802e58f039143b5aeabb7feb.png)
接下来该实例化了,实例化所有剩下的非懒加载的单例对象,
finishBeanFactoryInitialization.preInstantiateSingletons该方法是实例化剩下的单例对象,终于要开始实例化了。
当前容器里面有一个bean,目标是把这个bean放到一个集合里面去。
首先看容器里面有没有这个bean,
getBean(beanName).doGetBean
![](https://img-blog.csdnimg.cn/img_convert/d60f375f4524062bb5a4ce91fea4dfaf.png)
默认情况下都是单例的,
![](https://img-blog.csdnimg.cn/img_convert/117d7b8aa16f7301910009e88b98ef5b.png)
![](https://img-blog.csdnimg.cn/img_convert/3de47a357cb7c3a9b6ea6cdef80ccfe8.png)
通过反射的方式创建具体的bean对象,
![](https://img-blog.csdnimg.cn/img_convert/e97cd0e4a571440f68767a701b1f9b71.png)
获取到对应的构造器对象,
![](https://img-blog.csdnimg.cn/img_convert/cc22c7be18c411c1ecc57cb2a5660838.png)
![](https://img-blog.csdnimg.cn/img_convert/6ede27a9fdd72c4458bdbade4a34fd57.png)
获取实例化的策略并且进行实例化,
![](https://img-blog.csdnimg.cn/img_convert/0c1432d4e6c815d019aa34bbc8433ee9.png)
![](https://img-blog.csdnimg.cn/img_convert/c010e273c268a372ba316e9ff2cb7a36.png)
获取到构造器并实例化,
![](https://img-blog.csdnimg.cn/img_convert/2bdd3d6205f40f49dcb34e83316fa0b1.png)
实例化的时候,只是在堆中开辟内存空间并没有给属性赋值,
![](https://img-blog.csdnimg.cn/img_convert/bc49a084956904ba2c0935c644967e7b.png)
接下来是填充属性,
![](https://img-blog.csdnimg.cn/img_convert/e718c36dcc73b2ed86d20fdc556b3b15.png)
在执行populateBean方法之前,当前bean对象这3个值都等于空,
![](https://img-blog.csdnimg.cn/img_convert/335a06af76dd144db2a213b5f04f22cb.png)
执行完之后,name完成了属性填充,但beanName不会填充,因为beanName是aware接口,现在还没有执行Aware接口的实现类,
![](https://img-blog.csdnimg.cn/img_convert/f2817c17514ef52039a9270d27aecaf3.png)
接下来执行这些实现了aware接口的方法,
![](https://img-blog.csdnimg.cn/img_convert/bb1daccca9285741cad680af29d65eb9.png)
此时beanName就有了,为什么environment没有设置?
![](https://img-blog.csdnimg.cn/img_convert/b02cb8e6ef7e5f425f37f3651b759bdf.png)
因为在prepareBeanFactory方法中对这个Aware接口进行了忽略,
![](https://img-blog.csdnimg.cn/img_convert/b1650f6878bbd3de1120c7f82945e157.png)
![](https://img-blog.csdnimg.cn/img_convert/fc8aec94e5a01dc943caa7b55101872e.png)
本身的invokeAwareMethods方法也没有对EnvironmentAware进行处理,
![](https://img-blog.csdnimg.cn/img_convert/f050670dd68764be26265456837e128b.png)
![](https://img-blog.csdnimg.cn/img_convert/06afb7f55bfc832419656557446463d2.png)
调用每个postProcessBeforeInitialization方法,
![](https://img-blog.csdnimg.cn/img_convert/7e380c0c2824516167425d5114cab3b9.png)
执行到这里,此时就已经是一个完整的对象了,
![](https://img-blog.csdnimg.cn/img_convert/95c38796934e8f6722295b8bfb638d2c.png)
即执行完getBean(beanName)得到了一个完整的对象了。
因为当前集合里面只有一个对象,所以此时循环就结束了,当前这个bean完成了实例化且初始化。