带着萌新看springboot源码8(spring ioc源码上)

  emmm.....这次先不说springboot原理,先好好回顾一下以前的注解版spring原理,先把spring原理了解清晰了,再看springboot原理更容易。

  要说起spring,最重要的就是创建ioc容器的全过程,也可以叫做生命周期。

  所谓的ioc容器就是实现类;我们常看到的,有一个最顶层的BeanFactory接口,还有一个子接口ApplicationContext,其实现类都可说是ioc容器(称呼很笼统),只是ApplicationContext功能更强大,而且可以通过配置文件来实现功能,所以我们用这个接口的实现类(比如我们测试时候ApplicationContext ctx = new ClassPathXmlApplicationContext("com/yf/context/beans.xml");)比较多;

  其实,就我感觉,ioc容器的生命周期有一条主线:ioc容器创建(其实就是类实例化,但是还没有属性赋值等操作)-------->加载所有bean的定义信息-------->创建bean的实例--------->属性赋值(调用bean的setxxx方法)---------->假如bean实现了xxxAware接口,就执行setXXX方法---------->执行初始化方法(相当于xml<bean init-method="初始化方法">)----------->ioc容器创建完成,执行一些逻辑代码------------->Web应用关闭,ioc容器销毁。

  跟着这条主线,然后再执行很多的后置处理器(xxxPostProcessor)的方法(大多是xxxBeforexxx,xxxAfterxxx,postxxx方法),换句话来说,只要我们搞清楚了这些后置处理器什么时候添加到容器内?什么时候执行?有什么效果?那么ioc容器的原理就差不多一目了然了。

提前准备(依赖,随便一个类,配置类,测试方法):

带着萌新看springboot源码8(spring ioc源码上)

带着萌新看springboot源码8(spring ioc源码上)带着萌新看springboot源码8(spring ioc源码上)

带着萌新看springboot源码8(spring ioc源码上)

  

  点开这个类AnnotationConfigApplicationContext,加载新建ioc容器,加载配置文件读取信息知道就可以了,来看看refresh方法

带着萌新看springboot源码8(spring ioc源码上)

带着萌新看springboot源码8(spring ioc源码上)

  最好可以自己亲自调试一步一步的看过程,我这里只会大概说一下。

带着萌新看springboot源码8(spring ioc源码上)

带着萌新看springboot源码8(spring ioc源码上)

带着萌新看springboot源码8(spring ioc源码上)

  下面就来简要说说这12个流程

1.刷新前的准备工作(prepareRefresh)

带着萌新看springboot源码8(spring ioc源码上)

带着萌新看springboot源码8(spring ioc源码上)

2.获取容器(obtainFreshBeanFactory())

 带着萌新看springboot源码8(spring ioc源码上)

带着萌新看springboot源码8(spring ioc源码上)

  

  点开this.beanFactory就到了如下这个类

带着萌新看springboot源码8(spring ioc源码上)

带着萌新看springboot源码8(spring ioc源码上)

  然后就是将这个新创建的容器返回,并打印日志到控制台就ok了,没啥好说的

3.对BeanFactory进行预准备工作(prepareBeanFactory)

带着萌新看springboot源码8(spring ioc源码上)

带着萌新看springboot源码8(spring ioc源码上)

带着萌新看springboot源码8(spring ioc源码上)

4.对BeanFactory准备完成后做一些进一步处理的工作

  点开这个方法,你会发现这是一个空方法,留给你自己实现的。你可以继承本类或者子类,然后在容器创建完成并且准备工作做完之后,把BeanFactory返回给你,看你还需不需要再自定义一些其他的什么鬼。

带着萌新看springboot源码8(spring ioc源码上)

5.执行BeanFactory的后置处理器(invokeBeanFactoryPostProcessors(beanFactory)   )

  带着萌新看springboot源码8(spring ioc源码上)

带着萌新看springboot源码8(spring ioc源码上)

  

  下面注意后置处理器的两个接口:BeanFactoryPostProcessor接口和它的子接口BeanDefinitionRegistryPostProcessor,先执行实现了后面的这个接口的所有后置处理器,在执行所有实现了前面的这个接口的后置处理器。

  后面就是拿到容器BeanFactory里面的所有BeanDefinitionRegistryPostProcessor,按照这三种:实现PriorityOrdered接口,实现Ordered接口,没实现这两个接口;分别进行分类,添加到中间容器(currentRegistryProcessors),然后分别排序,添加到registryProcessors的容器里面(这三种后置处理器最终都是放到这里),分别遍历中间容器,执行。(由于过程重复,就以实现PriorityOrdered接口的为例)

带着萌新看springboot源码8(spring ioc源码上)

  

  现在再执行所有实现了BeanFactoryPostProcessor这个接口的后置处理器(里面肯定是遍历,然后分别执行)

带着萌新看springboot源码8(spring ioc源码上)

  假如BeanFactory不是BeanDefinitionRegistry接口的实现类,不用什么排序啊什么的,就直接执行所有的后置处理器

带着萌新看springboot源码8(spring ioc源码上)

  

  然后,后面的代码和这上面差不多,也是拿到所有的BeanFactory的后置处理器,然后各种分类,但是我还是想不通不是应该都执行完了所有的BeanFactory的后置处理器了吗?emmmmm,.....水平有限,网上找了找,还真的找到了。

  原话是:”以上逻辑执行了所有参数传入的和以bean定义方式存在的BeanDefinitionRegistryPostProcessor,也执行了所有参数传入的BeanFactoryPostProcessor, 但是尚未处理所有以bean定义方式存在的BeanFactoryPostProcessor, 下面的逻辑处理这部分 BeanFactoryPostProcessor.“

  看来是上面这种处理还有些遗漏了BeanFactory后置处理器,后面再补充一下。对此我只想说,我勒个去,太特么严谨了。。。。小的服了@_@!

   然后继续运行就到第六步了,第六步下一节再一起看。

前面这五步也是粗略的看了看源码,有个印象,很多的细节我都略过去了(偷个懒),不然,还能再写很多。。。。。

 

上一篇:django 项目运行时static静态文件不能加载问题处理


下一篇:解决类型“System.Web.UI.UpdatePanel”不具有名为“Gridview”的公共属性,