type
status
date
slug
summary
tags
category
icon
password
这里写文章的前言:
一个简单的开头,简述这篇文章讨论的问题、目标、人物、背景是什么?并简述你给出的答案。
可以说说你的故事:阻碍、努力、结果成果,意外与转折。
📝 SpringBoot 中 Initializer
最近看 SpringBoot 源码,看源码这个这个东西是真的要细心, 当你看到觉得重要的东西的时候,就一定要仔细去看,代码的走向以及走到了那个类中. 只有掌握这些,接下来才会更好理解.
然后我今天在看的时候, org.springframework.boot.SpringApplication#prepareContext ---> org.springframework.boot.SpringApplication#applyInitializers 当debug到这里的时候,就会看到 getInitializers() 方法返回的是一个集合,其中都是以Initializers 结尾的,并且都调用了相应的 initialize 方法. 所以就看下这个地方是要做写什么操作.
DelegatingApplicationContextInitializer
SharedMetadataReaderFactoryContextInitializer
ContextIdApplicationContextInitializer
ConfigurationWarningsApplicationContextInitializer
RSocketPortInfoApplicationContextInitializer
ServerPortInfoApplicationContextInitializer
ConditionEvaluationReportLoggingListener
如果我们没有进行扩展的话,这里就是默认的七个.
其中有五个是在 SpringBoot源码下的 META-INF/spring.factories 下的
org.springframework.context.ApplicationListener.
还有二个应该是在之前给添加进来的. 执行顺序是按照上面: 一次从下执行.
DelegatingApplicationContextInitializer
该方法就是获取 environment 中的 context.initializer.classes 指定的class信息
class信息也是要实现ApplicationContextInitializer接口的,然后实现完了,就会调用 initializer 方法.
也就是说该类,就是实例化配置 context.initializer.classes 中的子类,并且调用其 initializer 方法
SharedMetadataReaderFactoryContextInitializer
添加一个 CachingMetadataReaderFactoryPostProcessor 到 ApplicationContext 中去.
添加进去的 PostProcessor是其内部类,并且是私有的
ContextIdApplicationContextInitializer
可以看到该 Initializer 就是对 spring.application.name 进行获取,获取不到的话,就使用application默认值给设置到context中, 同时将 ContextId 也给注册到 beanFactory中去.
ConfigurationWarningsApplicationContextInitializer
该Initializer 也是添加一个 PostProcessor 到 context中去.
RSocketPortInfoApplicationContextInitializer
该方法主要是添加一个 Listener 到ApplicationContext 中去,其监听的event是 RSocketServerInitializedEvent
ServerPortInfoApplicationContextInitializer
该类不仅仅是一个 Initializer,而且还是一个 Listener监听器. 主要是用来监听 WebServerInitializedEvent 的
ConditionEvaluationReportLoggingListener
该 LoggingListener 虽然也是一个 Initializer, 但是其名字是没有包含任何Initializer的意思,反倒是作为监听器的,而且接受Event并不是其自身,而是内部类来接受,然后调用自己方法来处理Event来.
小战一把(自定义)
我们先自己写一个类实现 ApplicationContextInitializer 这个接口. 当然,这个initialize 中可以做的事件还是有点多的,我这里就选择注册一个bean 到 Spring的 BeanFactory 中去吧.
写一个实体类: 可以看到这个类是没什么其他的操作,就是一个方法.
最后我们在启动完成了之后,从 applicationContext 中获取出这个bean来,并且调用这个方法.
最后就可以在控制台看到打印的: GavinYang万年帅
没错,我就是万年帅.
到这里, 自己定义一个就完成了.
除了这种定义方式外,还可以看到 DelegatingApplicationContextInitializer 做的事情,也就是获取配置中context.initializer.classes的信息,然后实例化,在调用 initialize 方法.
🤗 总结归纳
可以看到, SpringBoot 中 在初始化 initialize这步的时候, 很多都是添加 postProcessor 和 listener 到 Spring 中去. 然后我们接着自己定义 initialize , 也就是添加一个对象到 beanFactory 中去. 最后获取出这个bean,然后调用其方法都是ok的.
📎 参考文章
有关文章的问题,欢迎您在底部评论区留言,一起交流~