万字+20张图剖析Spring启动时核心的12个步骤
invokeBeanFactoryPostProcessors
从这个方法的名字可以看出,是调用BeanFactoryPostProcessor,这个步骤非常重要,而且过程有点绕
前置知识:BeanFactoryPostProcessor及其子接口
BeanFactoryPostProcessor是一个接口,有一个方法,方法参数就是BeanFactory
通过这个方法就可以拿到BeanFactory,然后对BeanFactory做一些自己的调整
比如说,你想关闭循环依赖,你就可以实现这个接口,然后进行调整
他还有一个子接口BeanDefinitionRegistryPostProcessor
这个接口是对BeanDefinitionRegistry进行调整,BeanDefinitionRegistry就是存BeanDefinition的地方,真实的实现就是DefaultListableBeanFactory
所以BeanDefinitionRegistryPostProcessor的作用就是往BeanDefinitionRegistry(DefaultListableBeanFactory)中添加BeanDefinition的
再看invokeBeanFactoryPostProcessors
有了这两个前置知识之后,我们来看看invokeBeanFactoryPostProcessors方法的实现
这个方法最终会调用下面方法来真正的处理
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors;
这个方法比较长,大致分为两件事
- 调用所有的BeanDefinitionRegistryPostProcessor,解析配置类,注册BeanDefinition到DefaultListableBeanFactory中
- 从BeanFactory中获取所有的BeanFactoryPostProcessor进行调用,完成对BeanFactory一些其它的扩展
调用BeanDefinitionRegistryPostProcessor
首先第一步,先从BeanFactory中获取到所有的BeanDefinitionRegistryPostProcessor对象,调用它的postProcessBeanDefinitionRegistry方法
还记得上一节在说注册Spring内部的Bean时特地强调的一个类ConfigurationClassPostProcessor不?
他就实现了BeanDefinitionRegistryPostProcessor接口
所以此时获取到的就是ConfigurationClassPostProcessor
获取ConfigurationClassPostProcessor的时候会走Bean的生命周期,也就是会回调前面添加的BeansPostProcessor,但是也没几个
之后会调用他的postProcessBeanDefinitionRegistry方法,来处理此时BeanFactory中的配置类
配置类从哪来,前面一直没提到过
但是看一下ApplicationContext是如何使用的就知道了
比如说,下面这个demo
在创建一个ApplicationContext之后,在注册一个Bean之后再refresh
此时这个注册的Bean就是配置类。
如果你不注册,那是真没有配置类,此时也就没什么意义了。
所以,ApplicationContext一定会有一个配置类,不然没有意义。
在SpringBoot条件下,SpringBoot在启动时就会将启动引导类当做配置类给扔到BeanFactory中。
所以ConfigurationClassPostProcessor最开始处理的时候,就是处理启动引导类
我们可以在ConfigurationClassPostProcessor方法实现上打个断点验证一下
在处理之前可以看见,除了几个spring内部的BeanDefinition之外,还有一个myApplication,就是我的启动引导类
处理的时候它会解析启动引导类的注解,进行自动装配,扫描你写的代码的操作,之后生成BeanDefinition
当处理完成之后我们再看看,DefaultListableBeanFactory有了非常多的BeanDefinition了
所以到第一步就完成了,此时BeanFactory就加载了很多Bean
接下来,由于又新注册了很多BeanDefinition,而这些里面就有可能有BeanDefinitionRegistryPostProcessor接口的实现
所以之后会重复从BeanFactory中获取BeanDefinitionRegistryPostProcessor,调用postProcessBeanDefinitionRegistry
一直会循环下去,直到所有的BeanDefinitionRegistryPostProcessor都被调用为止
由于BeanDefinitionRegistryPostProcessor继承BeanFactoryPostProcessor
所以之后也会调用BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法
调用BeanFactoryPostProcessor
当调完所有的BeanDefinitionRegistryPostProcessor实现方法
之后就会从BeanFactory获取所有的BeanFactoryPostProcessor(除了BeanDefinitionRegistryPostProcessor实现之外),调用postProcessBeanFactory方法
此时就可以通过BeanFactoryPostProcessor再次对BeanFactory进制扩展
总的来说,这一步骤的核心作用就是完成对BeanFactory自定义扩展,但是由于BeanFactoryPostProcessor都是Bean,所以要第一步先加载Bean,之后才能通过BeanFactoryPostProcessor来扩展
一张图来总结上面主要干的事
这里简化了一些前面提到东西
registerBeanPostProcessors
上面一个步骤已经完成了Bean的扫描和对BeanFactory的扩展
这一节通过方法名就可以看出,是跟BeanPostProcessor相关
不过在这个方法执行之前,我们先来看看此时BeanFactory中已经有了哪些BeanPostProcessor
此时只有4个,前3个前面都提到过,但是像我们熟知的处理@Autowired、@Resource注解的BeanPostProcessor都不在里面
所以这里就有一个非常重要的小细节
在当前这个步骤执行之前如果从BeanFactory中获取Bean的话,虽然会走Bean生命周期的整个过程,但是@Autowired、@Resource注解都不会生效,因为此时BeanFactory中还没有处理这些注解的BeanPostProcessor(CommonAnnotationBeanPostProcessor等)
什么意思呢,举个例子
比如上面一节,在当前步骤执行之前会从BeanFactory中获取BeanFactoryPostProcessor
假设现在你实现了BeanFactoryPostProcessor,想注入一个ApplicationContext对象
此时是注入不成功的,@Resource注解不会生效,就是这个意思。
这时只能通过ApplicationContextAware方式获取,因为有对应的BeanPostProcessor(ApplicationContextAwareProcessor)
接下来我们再来看看registerBeanPostProcessors实现
最终也是调用下面的方法
PostProcessorRegistrationDelegate#registerBeanPostProcessors
这个过程就没上面那个步骤复杂了
其实就是从BeanFactory中获取到所有的BeanPostProcessor,然后添加到BeanFactory中
不过值得注意的是,BeanPostProcessor创建会有优先级,优先级高的会先被创建和添加到BeanFactory中
到这一步其实BeanFactory就算是准备完成了,基本上跟创建Bean相关的前置操作几乎都完成了
最后再来张图总结一下这个方法干的事
initMessageSource
这个方法是处理国际化相关的操作
这个操作比较简单,就是从BeanFactory中看看有没有Bean名称为messageSource的Bean
有的话就使用这个MessageSource,没有的话就用默认的
不过SpringBoot项目下会自动装配一个MessageSource,所以此时容器中是有的
initApplicationEventMulticaster
这个方法跟上面的差不多,也是从BeanFactory找有没有ApplicationEventMulticaster
有就用容器中的,没有就自己创建一个
ApplicationEventMulticaster是真正用来发布事件的,ApplicationEventPublisher最终也是调用他来发布事件
ApplicationEventMulticaster内部会缓存所有的监听器
当通过ApplicationEventMulticaster发布事件的时候,会去找到所有的监听器,然后调用
onRefresh
onRefresh也是一个模板方法,本身也是空实现
子类重写这个方法,会去创建一个Web服务器
registerListeners
这个方法其实也比较简单,就是将监听器给添加到ApplicationEventMulticaster中
finishBeanFactoryInitialization
这个方法首先又是老套路,就是判断容器中有没有ConversionService
ConversionService也是用来做类型转换的,跟前面提到的PropertyEditor作用差不多
如果有,就把ConversionService设置到BeanFactory中
到这一步,BeanFactory才算真的准备完成。。。
之后其实干的事就不太重要了
但是最后一行比较重要
beanFactory.preInstantiateSingletons();
从方法的命名就可以看出,实例化所有的单例对象
因为对于BeanFactory的一些配置在前面都完成了,所以这里就可以来实例化所有的单例对象了
这个方法会做两件事
第一件事就是实例化所有的非懒加载的单例Bean
实际上就是通过getBean方法来的,因为获取Bean,不存在的时候就会创,会走Bean的生命周期
第二件事就是一旦单例Bean实现了SmartInitializingSingleton接口,就会调用SmartInitializingSingleton的afterSingletonsInstantiated方法
文章转载自公众号:三友的java日记