做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1

上次分析refresh这块spring IoC的时候,时间比较仓促,只是debug了部分源码,大家分析起来不是很好~

今天我们还是先总结一下吧~

spring在实例化bean的时候,根据bean实现的接口不同,bean的实例化也是有先后顺序的

由于此块代码太多,贴图给大家的学习的效果不好,现在以spring 3.2.5源代码为例,大家再一份“温故”一下,然后“知新”

①:打开AbstractApplicationContext.java中refresh()先初始化好beanFactory(DefaultListableBeanFactory.java)【第445行~第496行】:

《做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1》

这边先对beanFactory做好初始化,关于beanFactory的初始化前面已经讲过了,链接如下:

http://blog.csdn.net/linuu/article/details/50829981


②初始化好了beanfactory之后,就先开始处理实现BeanFactoryPostProcessor.java的bean,说明BeanFactoryPostProcessor的实例化的优先级最高

《做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1》

    2.1 原因:实现了BeanFactoryPostProcessor.java这个接口的bean需要具体的实现BeanFactoryPostProcessor中定义的接口postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)这个接口。

        而这个接口可以直接修改beanDefinitionMap中beanDefinition中保存的bean的信息,而beanDefinition是所有bean初始化的依据,也就是说所有bean依赖于beanDefinition,所以实现BeanFactoryPostProcessor的接口的bean优先初始化,这样如果该bean修改了其他bean的beanDefinition,其他bean在后面初始化的时候才能按照用户给的正确参数实例化,例如org.springframework.beans.factory.config.PropertyPlaceholderConfigurer这个类(该类具体作用参照链接:http://blog.csdn.net/linuu/article/details/50853687)

 

   2.2 如果打开461行的代码,你会发现,如果有多个bean实现了BeanFactoryPostProcessor接口,那么这些bean的初始化顺序也是有讲究的

       AbstractApplicationContext.java 【605行~685行中】

     2.2.1首先实例化的是实现BeanDefinitionRegistryPostProcessor这个接口的bean(很好理解,看字面就知道,这个接口要修改的就是BeanDefinition,不先正确的实例化好它,实例化好,因为这个也许是其他bean的依赖注入呢),官方注释

 《做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1》

  (if any,说明了什么,说明了它比谁都的优先级都高)

   

    2.2.2 接着看注释:

《做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1》

接着按照字面的理解,同样,如果多个bean实现了BeanFactoryPostProcessor的情况下,谁实现了PriorityOrdered接口,谁也是优先执行,当然在实现BeanDefinitionRegistryPostProcessor这个之后


然后是实现了Ordered.java的接口,最后就是没有实现这2个特殊接口的普通实现BeanFactoryPostProcessor的bean了

《做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1》

 

    2.3 实现了BeanFactoryPostProcessor这个接口的bean,实例化的时候,第一件事情就是先把自己实例化,把自己实例化后才可以去做实现BeanFactoryPostProcessor这个接口定义的事情,这就是为什么下图中①模块比②模块先打印的原因了:

《做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1》

③ 现在我们开始分析上图中①的执行顺序,首先①模块执行的入口是

《做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1》

追踪getBean这个方法,我们会追踪到AbstractBeanFactory.java 的第230行doGetBean()这个方法

这块代码的执行顺序是:

3.1 首先先去实例化好的bean中去找,如果找到,直接返回【234行~250行】

3.2 然后去当前beanfactory中父类factory找,如果能找到父类的factory,则叫父类去返回,(与jvm的classloader的双亲加载比较像~)【260行~272行】

3.3 如果都没有找到,则开始初次实例化,先标记开始实例化【274~276行】

3.4 开始查看当前要实例化的bean是否依赖于其他的bean,如果依赖,则先实例化依赖的bean,如果依赖的bean还依赖于其他的bean,则接着递归创建

3.5如果创建的bean是单例(spring默认单例)接着创建

《做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1》



打开createBean,一直追踪到AbstractAutowireCapableBeanFactory.java的1030行,此时已经对该bean在spring的名片beandefinition中的class已经做了初步的校验,例如该类是否是private是否是abstract是否有默认的构造函数等等,符合校验后直接根据java的反射进行创建(当然此类不是接口),创建的对象经过spring包装返回一个BeanWrapper

因为此时bean已经创建了,所以下图中红色框框已经打印出来:

《做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1》

我们接着看AbstractAutowireCapableBeanFactory.java这个方法的第480行doCreateBean()这个方法的

《做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1》

此时我们已经创建好了bean了,我们要做的事还有Setter值,beanNameAware beanFactoryAware,initMethod(这些前几篇博客有介绍)这些创建后的“动作”


好的,接着看519行:populateBean这个方法(开始setter值)

《做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1》

因为setter可以根据多个属性setter注入,我们这边就不分析了,我们追踪到AbstractAutowireCapableBeanFactory.java的1368行applyPropertyValues这边的代码块


setter好后,执行521行代码,进入initializeBean这个方法

《做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1》

这个方法一开始if else都要执行invokeAwareMethods这个方法,对Aware我们很熟悉,进入查看

《做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1》

是的,首先执行实现BeanNameAware接口的setBeanName方法,然后是实现BeanClassLoaderAware的setBeanClassLoader方法,最后是实现BeanFactoryAware这个bean的方法

好了,跟我们打印的顺序是一致的:

《做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1》


我们接着看initializeBean这个方法

《做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1》

BeanPostProcessor需要注册才能运行,这边暂不分析,所以先看1509行代码invokeInitMethods,进入看:

《做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1》


如果该bean实现了InitializingBean接口,则先执行afterPropertiesSet()方法,最后

《做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1》


最后执行了我们在spring-init.xml中自定义的

《做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1》

所以最后打印了:

《做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1》

如上图中①模块所示,关于②模块下次再解析,这篇主要是对上篇日记的补充,不好意思,上次解析太多粗糙了,希望这篇对大家有帮助,END~

  


  

 

   

 



    原文作者:Spring Cloud
    原文地址: https://blog.csdn.net/linuu/article/details/50886872
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞