1、初始化器ApplicationContextInitializer

咱们在发动Spring Boot项意图时分,是履行这样一个办法来发动的

介绍Sping Boot的5个扩展点

咱们一层一层往下点,最终发现履行的是这个办法

介绍Sping Boot的5个扩展点

所以咱们在发动项意图时分也能够这样发动 new SpringApplication(SpringbootExtensionPointApplication.class).run(args); 老的只是包装了一个静态办法,实践底层便是实例化一个SpringApplication目标,然后调用它的run办法。

介绍Sping Boot的5个扩展点

咱们进到结构办法里看下,红框里边标出来的,一个是设置初始化器,一个是设置监听器。

介绍Sping Boot的5个扩展点

点进去看下,这两个底层调的办法是相同,便是传入一个类型,经过Spring SPI的方式查找这个类型的完成类,SPI我在《Sping Boot发动原理精讲第二讲》 的时分介绍过,这儿就不再赘述了哦。

介绍Sping Boot的5个扩展点

打个断点,发动一下,此刻有7个上下文初始器,这是系统自带的,装备在不同的spring.factories文件中。

介绍Sping Boot的5个扩展点

现在我要新建一个自己的初始化器

介绍Sping Boot的5个扩展点

此刻为了能够让Spring Boot在发动的时分能够扫描到我创立的初始化器应该怎么办? 便是在spring.factories文件中添加一下,注册一下,这样就能扫描到,这个便是SPI。SPI 全称为 Service Provider Interface,是一种服务发现机制。

介绍Sping Boot的5个扩展点

那么这时分咱们再发动一下Spring Boot,发现自己创立的ApplicationContextInitializer也现已注册上来了,变成8个了。

介绍Sping Boot的5个扩展点

把断点放掉,在操控台中也打印出了这句话,那么这个便是第一个扩展点ApplicationContextInitializer

介绍Sping Boot的5个扩展点

定义了这8个初始化器,那必定是有地方在调它们的,不然怎么会打印出来呢,那详细在什么地方调的,咱们在自己的初始化器的地方打断点,看到现已进来了,然后看下方的仓库信息,这个便是调用的地方。

介绍Sping Boot的5个扩展点

原来是调用了run()办法中的prepareContext()办法中的applyInitializers()办法,在这个办法中for循环的调用各个初始化器的initialize()办法,从而咱们就能看到把Jack的ApplicationContextInitializer这句话给打印出来了。那么这个查找的办法便是以结果为导向来反查调用方,由于你正查的话是很难找到,很难记住的,这个办法期望我们学习到。

介绍Sping Boot的5个扩展点

那么最终来看下咱们第一个扩展点所处的方位

介绍Sping Boot的5个扩展点

初始化器能够做一些工作,比如Environment目标设置一些变量装备。

2、监听器ApplicationListener

在上面结构函数里咱们发现除了有setInitializers,还有setListeners,那么这个listeners其实也是一个扩展点。

介绍Sping Boot的5个扩展点

那么什么是监听器,便是这样的,这个其实便是观察者形式,ApplicationEventMulticaster发布事情,各个Listener监听事情。

介绍Sping Boot的5个扩展点

和初始化器相同,现在咱们自定义两个监听器,一个是Starting,一个是Started,括号里边的是泛型,这个是必定要写的,假如不写的话便是不管什么类型的Event都会监听。

介绍Sping Boot的5个扩展点

介绍Sping Boot的5个扩展点

这个泛型是上限为ApplicationEvent类型的Event,详细的完成类有许多个,Starting和Started只是其间两个。

介绍Sping Boot的5个扩展点

介绍Sping Boot的5个扩展点

现在咱们仍是把这两个监听器经过SPI的方式加到装备中去

介绍Sping Boot的5个扩展点

好,运转一下,咱们看到这两句话现已打印出来了

介绍Sping Boot的5个扩展点

和监听器相同,已然能够打印出来,那肯定是有地方在调用,所以咱们在JackStartingApplicationListener打个断点,然后看下仓库信息

介绍Sping Boot的5个扩展点

咱们能够看到在SpringApplication run()办法的listeners.starting()开始进去发送ApplicationStartingEvent播送事情,最终发布出去,由咱们自己编写的事情监听器接收到。

介绍Sping Boot的5个扩展点

介绍Sping Boot的5个扩展点

那么ApplicationStartedEvent事情也是相同的道理,经过打断点的方式来找到它的调用方,最终咱们再来看下此刻的扩展点图

介绍Sping Boot的5个扩展点

3、Runner

咱们看到在listeners.started()后面有个callRunners

介绍Sping Boot的5个扩展点

咱们点进去看下,它其实便是从容器中获取两种类型的Runner,一种是ApplicationRunner,还有一种是CommandLineRunner,然后for循环的对它们进行调用,那么其实这个也是一个扩展点

介绍Sping Boot的5个扩展点

咱们来写一个自己的Runner

介绍Sping Boot的5个扩展点

运转一下,看下打印出来了

介绍Sping Boot的5个扩展点

那么这个Runner的一般使用场景便是资源释放整理或者做注册中心,由于履行到Runner的时分项目现已发动完毕了,这时分就能够注册到注册中心上去了。此刻咱们再看下扩展点图。

介绍Sping Boot的5个扩展点

4、BeanFactoryPostProcessor

咱们看下run办法里的refreshContext()办法

介绍Sping Boot的5个扩展点

这个办法底层会调spring里边的refresh()办法,这个办法里边就会做对容器的初始化。红框里的invokeBeanFactoryPostProcessors()办法,这儿也有一个扩展点,便是BeanFactoryPostProcessor,履行对BeanFactory的后置处理。 Spring Boot解析装备成BeanDefinition的操作也是在此办法中。

介绍Sping Boot的5个扩展点

现在咱们来创立一个自己的BeanFactoryPostProcessor,这个办法里边能够修改beanFactory的特点,beanfactory里边有BeanDefinition,能够修改BeanDefinition里边的值。BeanDefinition是一个bean的元数据的信息,有多少个bean就有多少个BeanDefinition。

介绍Sping Boot的5个扩展点

运转一下,也打印出来了

介绍Sping Boot的5个扩展点

此刻咱们再看下扩展点图,越来越完善了。

介绍Sping Boot的5个扩展点

5、BeanPostProcessor

最终介绍的是BeanPostProcessor,它在经过反射结构函数进行bean实例化之后履行,那么红框里边标出来的registerBeanPostProcessors()办法便是向BeanFactory中注册beanpostprocessor,用于后续bean创立的阻拦操作。

介绍Sping Boot的5个扩展点

现在咱们来创立一个自己的BeanPostProcessor,一共有两个办法,postProcessBeforeInitialization和postProcessAfterInitialization,不过咱们一般用postProcessAfterInitialization,在bean调用反射结构函数实例化之后履行。闻名的使用场景AOP底层便是经过BeanPostProcessor来完成的。

介绍Sping Boot的5个扩展点

现在我在postProcessAfterInitialization上打个断点,看下仓库信息是在哪里调用的

介绍Sping Boot的5个扩展点

是在finishBeanFactoryInitialization()办法处调用的

介绍Sping Boot的5个扩展点

后记

最终我来把扩展点图弥补完整,如下所示,很明晰明晰,在什么时分调用了什么,咱们自己开发的时分结合使用场景,在什么时分要干什么事,就知道要创立什么类型的扩展点了。

介绍Sping Boot的5个扩展点

本文前三个讲的是Spring Boot里边自己有的扩展点,后两个由于Spring Boot底层调的是Spring的源码,所以归于Spring里边的扩展点,所以假如这么算的话Spring里边的扩展点还有许多扩展点,比如InitializeBean、Aware等等这儿都没讲,等待我们去发掘,谢谢观看 ~