Spring是如何回调Aware系列接口?

写在最前

当我们运行Web容器或是以SE的方式运行Spring程序的过程中,你有没有想过Spring是如何实现回调生命周期中的那些过程呢?今天我们就以生命周期中回调Aware接口为例,来说说Spring的回调过程。

正文

1.Aware接口

Aware接口

Aware接口在Spring的3.1版本中出现,并且beans包中,属于spring的核心。上图中的描述告诉我们,Aware是一个具有标识作用的超级接口,实现该接口的bean是具有被spring 容器通知的能力的,而被通知的方式就是通过回调。对于这段英文,我并没有直译,而是加上了自己的理解。总之,一句话也就是说:直接或间接实现了这个接口的类,都具有被spring容器通知的能力。

那我们看看spring中实现了该超级接口的子接口有哪些?

Aware的子接口

哇,多如牛毛!咦,别动,有几个好熟悉的接口。例如:ResourceLoaderAware、BeanNameAware、ApplicationContextAware、BeanNameAware... 熟悉spring生命周期的童鞋可能见过这些接口。不错,这些接口就是今天我们的主角。

2.Spring Boot的大致启动过程

我们以Spring Boot的启动过程为例,看看这些Aware接口是如何被调用到的。

Spring Boot启动入口

如上图,这里是以内嵌jetty的方式启动Spring Boot。 通常我们启动Spring boot,都是直接调用SpringApplication的run方法,再看看run方法的内部:

SpringApplication的run方法

主要看红色圈起的地方,其它的代码可以忽略。这里调用了createApplicationContext方法去创建容器上下文。再来看看createApplicationContext()方法的内部:

SpringApplication的createApplicationContext方法
SpringApplication的常量

webEnvironment是一个boolean型的变量,用来表示当前的应用类型是不是web应用。如果为false,则代表是普通应用(JavaSE);反之就是web应用(Java Web),则创建可运行web应用的上下文。我们讲述的是web应用,所以这里的contextClass是AnnotationConfigEmbeddedWebApplicationContext。createApplicationContext()方法中的最后一行代码是创建了一个context。我们跟进去看看这个context是如何创建的:

BeanUtils的instantiate()方法

上图中的第七行代码,通过反射实例化了contextClass,这里实例化的正是AnnotationConfigEmbeddedWebApplicationContext类,调用的是无参的构造器。我们再去看看AnnotationConfigEmbeddedWebApplicationContext的无参构造器:

AnnotationConfigEmbeddedWebApplicationContext的无参构造器

如上图,构造器中只是设置了reader和scanner。这里我们先忽略它们。除此之外,实例化一个类时它的直接或间接的父类也同样会被实例化。看看AnnotationConfigEmbeddedWebApplicationContext有些哪些父类:

AnnotationConfigEmbeddedWebApplicationContext的继承关系

我们耐心的一层一层的跟踪父类和间接父类的构造器到GenericApplicationContext才发现无参构造器中在做一些事情。如下图:

GenericApplicationContext

看到这里,我们终于看见曙光了。xxxBeanFactory是生成beans对象的工厂类。在DefaultListableBeanFactory的父类AbstractAutowireCapableBeanFactory中有两个很重要的方法:
initializeBean()和createBean()方法。initializeBean是用来初始化beans的,看下图代码:

AbstractAutowireCapableBeanFactory的initializeBean方法

看到这里我们就知道了,Aware系列的接口是这么被调用的了,并把需要的内部对象回传给Aware的子类实例对象,那么外部就可以获取到spring内部的一些对象了。例如:我们获取BeanFactory,然后手动创建beans对象等等。

写在最后

看完上面的过程有没有发现少了点什么东西? 是不是发现少了:Spring Boot是如何调用到initializeBean()的呢?欲知后事如何,且看下回分解。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,293评论 19 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 47,014评论 6 342
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,896评论 18 399
  • 从日本回来也快2个月了,时间过的真是太快了,始终还是念念不忘新宿,在那里逛街可以逛到精疲力尽。 新宿是东京最著名的...
    九号咖啡屋阅读 3,984评论 3 10
  • 即使时间过去了这么久,我也依然觉得这两年来自己其实没有什么长进,唯一进步的可能是在对待和别人的关系上,自己又进步了...
    面包主义阅读 3,971评论 0 0