网站建设的费用包括哪些内容,手机网站 英文,服务器不支持做网站是什么意思,wordpress 图片插件1、初始化器ApplicationContextInitializer
我们在启动Spring Boot项目的时候#xff0c;是执行这样一个方法来启动的 我们一层一层往下点#xff0c;最终发现执行的是这个方法
所以我们在启动项目的时候也可以这样启动 new SpringApplication(SpringbootExtensionPointAp…1、初始化器ApplicationContextInitializer
我们在启动Spring Boot项目的时候是执行这样一个方法来启动的 我们一层一层往下点最终发现执行的是这个方法
所以我们在启动项目的时候也可以这样启动 new SpringApplication(SpringbootExtensionPointApplication.class).run(args); 老的只是包装了一个静态方法实际底层就是实例化一个SpringApplication对象然后调用它的run方法。
我们进到构造方法里看下红框里面标出来的一个是设置初始化器一个是设置监听器。
点进去看下这两个底层调的方法是一样就是传入一个类型通过Spring SPI的方式查找这个类型的实现类SPI我在《Sping Boot启动原理精讲第二讲》 的时候介绍过这里就不再赘述了哦。 打个断点启动一下此时有7个上下文初始器这是系统自带的配置在不同的spring.factories文件中。
现在我要新建一个自己的初始化器 此时为了能够让Spring Boot在启动的时候能够扫描到我创建的初始化器应该怎么办 就是在spring.factories文件中添加一下注册一下这样就能扫描到这个就是SPI。SPI 全称为 Service Provider Interface,是一种服务发现机制。 那么这时候我们再启动一下Spring Boot发现自己创建的ApplicationContextInitializer也已经注册上来了变成8个了。 把断点放掉在控制台中也打印出了这句话那么这个就是第一个扩展点ApplicationContextInitializer
定义了这8个初始化器那一定是有地方在调它们的不然怎么会打印出来呢那具体在什么地方调的我们在自己的初始化器的地方打断点看到已经进来了然后看下方的堆栈信息这个就是调用的地方。 原来是调用了run()方法中的prepareContext()方法中的applyInitializers()方法在这个方法中for循环的调用各个初始化器的initialize()方法从而我们就能看到把Jack的ApplicationContextInitializer这句话给打印出来了。那么这个查找的方法就是以结果为导向来反查调用方因为你正查的话是很难找到很难记住的这个方法希望大家学习到。 那么最后来看下我们第一个扩展点所处的位置 初始化器可以做一些事情比如Environment对象设置一些变量配置。
2、监听器ApplicationListener
在上面构造函数里我们发现除了有setInitializers还有setListeners那么这个listeners其实也是一个扩展点。 那么什么是监听器就是这样的这个其实就是观察者模式ApplicationEventMulticaster发布事件各个Listener监听事件。 和初始化器一样现在我们自定义两个监听器一个是Starting一个是Started括号里面的是泛型这个是一定要写的如果不写的话就是不管什么类型的Event都会监听。 这个泛型是上限为ApplicationEvent类型的Event具体的实现类有很多个Starting和Started只是其中两个。 现在我们还是把这两个监听器通过SPI的方式加到配置中去 好运行一下我们看到这两句话已经打印出来了 和监听器一样既然能够打印出来那肯定是有地方在调用所以我们在JackStartingApplicationListener打个断点然后看下堆栈信息 我们可以看到在SpringApplication run()方法的listeners.starting()开始进去发送ApplicationStartingEvent广播事件最后发布出去由我们自己编写的事件监听器接收到。 那么ApplicationStartedEvent事件也是一样的道理通过打断点的方式来找到它的调用方最后我们再来看下此时的扩展点图 3、Runner
我们看到在listeners.started()后面有个callRunners
我们点进去看下它其实就是从容器中获取两种类型的Runner一种是ApplicationRunner还有一种是CommandLineRunner然后for循环的对它们进行调用那么其实这个也是一个扩展点 我们来写一个自己的Runner 运行一下看下打印出来了
那么这个Runner的一般应用场景就是资源释放清理或者做注册中心因为执行到Runner的时候项目已经启动完毕了这时候就可以注册到注册中心上去了。此时我们再看下扩展点图。 4、BeanFactoryPostProcessor
我们看下run方法里的refreshContext()方法 这个方法底层会调spring里面的refresh()方法这个方法里面就会做对容器的初始化。红框里的invokeBeanFactoryPostProcessors()方法这里也有一个扩展点就是BeanFactoryPostProcessor执行对BeanFactory的后置处理。 Spring Boot解析配置成BeanDefinition的操作也是在此方法中。 现在我们来创建一个自己的BeanFactoryPostProcessor这个方法里面可以修改beanFactory的属性beanfactory里面有BeanDefinition可以修改BeanDefinition里面的值。BeanDefinition是一个bean的元数据的信息有多少个bean就有多少个BeanDefinition。 运行一下也打印出来了 此时我们再看下扩展点图越来越完善了。 5、BeanPostProcessor
最后介绍的是BeanPostProcessor它在通过反射构造函数进行bean实例化之后执行那么红框里面标出来的registerBeanPostProcessors()方法就是向BeanFactory中注册beanpostprocessor用于后续bean创建的拦截操作。 现在我们来创建一个自己的BeanPostProcessor一共有两个方法postProcessBeforeInitialization和postProcessAfterInitialization不过我们一般用postProcessAfterInitialization在bean调用反射构造函数实例化之后执行。著名的应用场景AOP底层就是通过BeanPostProcessor来实现的。 现在我在postProcessAfterInitialization上打个断点看下堆栈信息是在哪里调用的 是在finishBeanFactoryInitialization()方法处调用的
后记
最后我来把扩展点图补充完整如下所示很清晰明了在什么时候调用了什么我们自己开发的时候结合应用场景在什么时候要干什么事就知道要创建什么类型的扩展点了。 本文前三个讲的是Spring Boot里面自己有的扩展点后两个因为Spring Boot底层调的是Spring的源码所以属于Spring里面的扩展点所以如果这么算的话Spring里面的扩展点还有很多扩展点比如InitializeBean、Aware等等这里都没讲等待大家去发掘谢谢观看 ~