写在最前
当我们运行Web容器或是以SE的方式运行Spring程序的过程中,你有没有想过Spring是如何实现回调生命周期中的那些过程呢?今天我们就以生命周期中回调Aware接口为例,来说说Spring的回调过程。
正文
1.Aware接口
![](https://img.haomeiwen.com/i2280774/61b5407c5c945d81.png)
Aware接口在Spring的3.1版本中出现,并且beans包中,属于spring的核心。上图中的描述告诉我们,Aware是一个具有标识作用的超级接口,实现该接口的bean是具有被spring 容器通知的能力的,而被通知的方式就是通过回调。对于这段英文,我并没有直译,而是加上了自己的理解。总之,一句话也就是说:直接或间接实现了这个接口的类,都具有被spring容器通知的能力。
那我们看看spring中实现了该超级接口的子接口有哪些?
![](https://img.haomeiwen.com/i2280774/d667ae811ee91f66.png)
哇,多如牛毛!咦,别动,有几个好熟悉的接口。例如:ResourceLoaderAware、BeanNameAware、ApplicationContextAware、BeanNameAware... 熟悉spring生命周期的童鞋可能见过这些接口。不错,这些接口就是今天我们的主角。
2.Spring Boot的大致启动过程
我们以Spring Boot的启动过程为例,看看这些Aware接口是如何被调用到的。
![](https://img.haomeiwen.com/i2280774/aa8e01395b80fb04.png)
如上图,这里是以内嵌jetty的方式启动Spring Boot。 通常我们启动Spring boot,都是直接调用SpringApplication的run方法,再看看run方法的内部:
![](https://img.haomeiwen.com/i2280774/1c234d054443149d.png)
主要看红色圈起的地方,其它的代码可以忽略。这里调用了createApplicationContext方法去创建容器上下文。再来看看createApplicationContext()方法的内部:
![](https://img.haomeiwen.com/i2280774/4fcd407a1c2104a0.png)
![](https://img.haomeiwen.com/i2280774/b073cb40b53dd03d.png)
webEnvironment是一个boolean型的变量,用来表示当前的应用类型是不是web应用。如果为false,则代表是普通应用(JavaSE);反之就是web应用(Java Web),则创建可运行web应用的上下文。我们讲述的是web应用,所以这里的contextClass是AnnotationConfigEmbeddedWebApplicationContext。createApplicationContext()方法中的最后一行代码是创建了一个context。我们跟进去看看这个context是如何创建的:
![](https://img.haomeiwen.com/i2280774/4da2a164fafc0d58.png)
上图中的第七行代码,通过反射实例化了contextClass,这里实例化的正是AnnotationConfigEmbeddedWebApplicationContext类,调用的是无参的构造器。我们再去看看AnnotationConfigEmbeddedWebApplicationContext的无参构造器:
![](https://img.haomeiwen.com/i2280774/6000aea435cb0215.png)
如上图,构造器中只是设置了reader和scanner。这里我们先忽略它们。除此之外,实例化一个类时它的直接或间接的父类也同样会被实例化。看看AnnotationConfigEmbeddedWebApplicationContext有些哪些父类:
![](https://img.haomeiwen.com/i2280774/0e34dffcb2f59684.png)
我们耐心的一层一层的跟踪父类和间接父类的构造器到GenericApplicationContext才发现无参构造器中在做一些事情。如下图:
![](https://img.haomeiwen.com/i2280774/243b618eb6c16cb8.png)
看到这里,我们终于看见曙光了。xxxBeanFactory是生成beans对象的工厂类。在DefaultListableBeanFactory的父类AbstractAutowireCapableBeanFactory中有两个很重要的方法:
initializeBean()和createBean()方法。initializeBean是用来初始化beans的,看下图代码:
![](https://img.haomeiwen.com/i2280774/0a4e83ab3bd1489a.png)
看到这里我们就知道了,Aware系列的接口是这么被调用的了,并把需要的内部对象回传给Aware的子类实例对象,那么外部就可以获取到spring内部的一些对象了。例如:我们获取BeanFactory,然后手动创建beans对象等等。
写在最后
看完上面的过程有没有发现少了点什么东西? 是不是发现少了:Spring Boot是如何调用到initializeBean()的呢?欲知后事如何,且看下回分解。
网友评论