首页 > 其他分享 >介绍Sping Boot的5个扩展点

介绍Sping Boot的5个扩展点

时间:2023-08-05 15:34:42浏览次数:48  
标签:初始化 调用 Boot Sping 扩展 监听器 Spring 方法

1、初始化器ApplicationContextInitializer

我们在启动Spring Boot项目的时候,是执行这样一个方法来启动的

介绍Sping Boot的5个扩展点_初始化

我们一层一层往下点,最终发现执行的是这个方法

介绍Sping Boot的5个扩展点_监听器_02

所以我们在启动项目的时候也可以这样启动 new SpringApplication(SpringbootExtensionPointApplication.class).run(args); 老的只是包装了一个静态方法,实际底层就是实例化一个SpringApplication对象,然后调用它的run方法。

介绍Sping Boot的5个扩展点_监听器_03

我们进到构造方法里看下,红框里面标出来的,一个是设置初始化器,一个是设置监听器。

介绍Sping Boot的5个扩展点_构造函数_04

点进去看下,这两个底层调的方法是一样,就是传入一个类型,通过Spring SPI的方式查找这个类型的实现类,SPI我在《Sping Boot启动原理精讲第二讲》 的时候介绍过,这里就不再赘述了哦。

介绍Sping Boot的5个扩展点_构造函数_05

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

介绍Sping Boot的5个扩展点_初始化_06

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

介绍Sping Boot的5个扩展点_监听器_07

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

介绍Sping Boot的5个扩展点_初始化_08

那么这时候我们再启动一下Spring Boot,发现自己创建的ApplicationContextInitializer也已经注册上来了,变成8个了。

介绍Sping Boot的5个扩展点_构造函数_09

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

介绍Sping Boot的5个扩展点_初始化_10

定义了这8个初始化器,那一定是有地方在调它们的,不然怎么会打印出来呢,那具体在什么地方调的,我们在自己的初始化器的地方打断点,看到已经进来了,然后看下方的堆栈信息,这个就是调用的地方。

介绍Sping Boot的5个扩展点_监听器_11

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

介绍Sping Boot的5个扩展点_springBoot_12

那么最后来看下我们第一个扩展点所处的位置

介绍Sping Boot的5个扩展点_构造函数_13

初始化器可以做一些事情,比如Environment对象设置一些变量配置。

2、监听器ApplicationListener

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

介绍Sping Boot的5个扩展点_构造函数_14

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

介绍Sping Boot的5个扩展点_监听器_15

和初始化器一样,现在我们自定义两个监听器,一个是Starting,一个是Started,括号里面的是泛型,这个是一定要写的,如果不写的话就是不管什么类型的Event都会监听。

介绍Sping Boot的5个扩展点_初始化_16

介绍Sping Boot的5个扩展点_构造函数_17

这个泛型是上限为ApplicationEvent类型的Event,具体的实现类有很多个,Starting和Started只是其中两个。

介绍Sping Boot的5个扩展点_构造函数_18

介绍Sping Boot的5个扩展点_监听器_19

现在我们还是把这两个监听器通过SPI的方式加到配置中去

介绍Sping Boot的5个扩展点_初始化_20

好,运行一下,我们看到这两句话已经打印出来了

介绍Sping Boot的5个扩展点_springBoot_21

和监听器一样,既然能够打印出来,那肯定是有地方在调用,所以我们在JackStartingApplicationListener打个断点,然后看下堆栈信息

介绍Sping Boot的5个扩展点_构造函数_22

我们可以看到在SpringApplication run()方法的listeners.starting()开始进去发送ApplicationStartingEvent广播事件,最后发布出去,由我们自己编写的事件监听器接收到。

介绍Sping Boot的5个扩展点_springBoot_23

介绍Sping Boot的5个扩展点_springBoot_24

那么ApplicationStartedEvent事件也是一样的道理,通过打断点的方式来找到它的调用方,最后我们再来看下此时的扩展点图

介绍Sping Boot的5个扩展点_springBoot_25

3、Runner

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

介绍Sping Boot的5个扩展点_构造函数_26

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

介绍Sping Boot的5个扩展点_springBoot_27

我们来写一个自己的Runner

介绍Sping Boot的5个扩展点_初始化_28

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

介绍Sping Boot的5个扩展点_初始化_29

那么这个Runner的一般应用场景就是资源释放清理或者做注册中心,因为执行到Runner的时候项目已经启动完毕了,这时候就可以注册到注册中心上去了。此时我们再看下扩展点图。

介绍Sping Boot的5个扩展点_springBoot_30

4、BeanFactoryPostProcessor

我们看下run方法里的refreshContext()方法

介绍Sping Boot的5个扩展点_初始化_31

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

介绍Sping Boot的5个扩展点_监听器_32

现在我们来创建一个自己的BeanFactoryPostProcessor,这个方法里面可以修改beanFactory的属性,beanfactory里面有BeanDefinition,可以修改BeanDefinition里面的值。BeanDefinition是一个bean的元数据的信息,有多少个bean就有多少个BeanDefinition。

介绍Sping Boot的5个扩展点_springBoot_33

运行一下,也打印出来了

介绍Sping Boot的5个扩展点_监听器_34

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

介绍Sping Boot的5个扩展点_监听器_35

5、BeanPostProcessor

最后介绍的是BeanPostProcessor,它在通过反射构造函数进行bean实例化之后执行,那么红框里面标出来的registerBeanPostProcessors()方法就是向BeanFactory中注册beanpostprocessor,用于后续bean创建的拦截操作。

介绍Sping Boot的5个扩展点_构造函数_36

现在我们来创建一个自己的BeanPostProcessor,一共有两个方法,postProcessBeforeInitialization和postProcessAfterInitialization,不过我们一般用postProcessAfterInitialization,在bean调用反射构造函数实例化之后执行。著名的应用场景AOP底层就是通过BeanPostProcessor来实现的。

介绍Sping Boot的5个扩展点_构造函数_37

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

介绍Sping Boot的5个扩展点_springBoot_38

是在finishBeanFactoryInitialization()方法处调用的

介绍Sping Boot的5个扩展点_初始化_39

后记

最后我来把扩展点图补充完整,如下所示,很清晰明了,在什么时候调用了什么,我们自己开发的时候结合应用场景,在什么时候要干什么事,就知道要创建什么类型的扩展点了。

介绍Sping Boot的5个扩展点_初始化_40

本文前三个讲的是Spring Boot里面自己有的扩展点,后两个因为Spring Boot底层调的是Spring的源码,所以属于Spring里面的扩展点,所以如果这么算的话Spring里面的扩展点还有很多扩展点,比如InitializeBean、Aware等等这里都没讲,等待大家去发掘,谢谢观看 ~

标签:初始化,调用,Boot,Sping,扩展,监听器,Spring,方法
From: https://blog.51cto.com/u_16205813/6975723

相关文章

  • 【Spring Boot 丨类型安全配置属性 】
    本篇来讲一讲外部化配置类型安全属性(类型安全配置属性)类型安全配置属性  使用@Value("${property}")注释来注入配置属性有时可能很麻烦,尤其是处理多个属性或您的数据本质上是层次结构的情况下。SpringBoot提供了另一种使用属性的方法,让强类型bean管理和验证应用程......
  • Springboot 3.x 集成Knife4j [踩坑日记]
    之前项目用的是SpringBoot2.x新项目用了SpringBoot3.x版本,引入Knife4j报错java.lang.TypeNotPresentException:Typejavax.servlet.http.HttpServletRequestnotpresent,以为是servlet的原因,更新了Servlet的版本,依旧报错,几番周折找到找到了在SpringBoot3中集成Knife......
  • BootstrapBlazor组件库,Menu组件NavLinkMatch导致的多个菜单项被被同时选中
    BootstrapBlazor组件库,Menu组件NavLinkMatch导致的多个菜单项被被同时选中BootstrapBlazor版本更新到7.9.0后,Menu组件出现首页同时被选中的情况默认首页/路径是选中状态,但是当选中其他路径后,首页路径还是选中状态。这是因为在BootstrapBlazor组件最新版中支持了一个新特性。可......
  • 中国剩余定理及其扩展
    $$\left{\begin{aligned}x_1=a_1\(mod\m_1)\x_2=a_2\(mod\m_2)\.\qquad\qquad\.\qquad\qquad\.\qquad\qquad\x_n=a_k\(mod\m_k)\end{aligned}\right.$$中国剩余定理算法流程计算所有模数的积M;对于第i个方程:a.计算$n_i\=......
  • Spring Boot 数据库连接池性能优化
    当涉及到SpringBoot中的性能优化时,连接池是一个非常重要的话题。连接池在数据库访问和其他外部资源访问中扮演着关键角色,可以显著提升应用程序的性能和资源利用率。在本文中,我们将深入探讨如何在SpringBoot应用中优化数据库连接池的配置,从而提升应用性能。数据库连接池是管理......
  • Spring Boot 微服务架构中的服务发现和注册
    当涉及到SpringBoot中的微服务架构时,服务发现和注册是一个至关重要的话题。在微服务架构中,各个服务需要相互通信,而服务发现和注册机制则允许服务动态地发现和定位其他服务,从而实现更好的弹性和可扩展性。在本文中,我们将深入探讨如何在SpringBoot中实现服务发现和注册,以及如何......
  • Spring Boot 中的 AOP 实践
    在SpringBoot中使用AOP(面向切面编程)可以帮助您在应用程序中更优雅地处理横切关注点,如日志、事务管理和安全性。本文将深入探讨如何在SpringBoot中使用AOP,以及如何创建自定义切面来实现特定功能。1.什么是AOP?AOP是一种编程范式,它允许您将横切关注点(如日志、安全性、事务......
  • Spring Boot 中的缓存优化
    在SpringBoot中使用缓存可以显著提升应用程序的性能和响应时间。通过合理地配置缓存,可以减少对数据库或其他外部资源的频繁访问,从而提升系统的吞吐量和性能。本文将深入探讨如何在SpringBoot中使用缓存,以及如何优化缓存配置以获得最佳性能。1.为什么使用缓存?使用缓存可以将......
  • Spring Boot 中的数据库连接池
    在SpringBoot中,使用数据库连接池是优化应用性能和资源利用的重要手段。数据库连接池允许应用程序重复使用预先创建的数据库连接,避免了频繁地创建和关闭连接,从而提升了数据库访问的效率。本文将深入探讨在SpringBoot中使用数据库连接池的优势和配置方法。1.数据库连接池的优......
  • springboot 关于servlet容器配置修改 组件注册 容器切换 使用外部tomcat
    1.嵌入式Servlet容器配置修改1.通过全局配置文件修改可以通过server.xxx来进行web服务配置,没有带服务器名称的则是通用配置通过带了具体的服务器名称则是单独对该服务器进行设置,比如server.tomcat.xxx就是专门针对tomcat的配置2.通过WebServerFactoryCus......