本文已参与「新人创作礼」活动,一起开启掘金创作之路。
11.refreshContext
4.postProcessBeanFactory
方法上注释:Allows post-processing of the bean factory in context subclasses. 翻译过来就是:允许在上下文子类中对 bean 工厂进行后处理。
进入postProcessBeanFactory()方法,该方法在 AbstractApplicationContext 是默认空方法,在 SpringBoot 中对其进行了扩展。
进入子类AnnotationConfigServletWebServerApplicationContext的postProcessBeanFactory()方法如下:
首先是调用了父类中的 postProcessBeanFactory() 方法,其父类为 ServletWebServerApplicationContext,进入其 postProcessBeanFactory() 方法如下:
1.向 beanFactory 中添加了一个叫WebApplicationContextServletContextAwareProcessor的 bean 后置处理器。
2.向 beanFactory 的 ignoredDependencyInterfaces 中添加了一个 ServletContextAware 类型。
3.注册作用域
进入registerWebApplicationScopes()方法如下:
3.1 首先创建了ExistingWebApplicationScopes对象,在其构造方法中,首先判断了 beanFactory 的 scopes 中是否存在 request 和 session 的 scope,若存在,则保存在 ExistingWebApplicationScopes 的 scopes 属性中返回。从 beanFactory 中拿到指定 scope.
这里 DEBUG 是不存在,所以 ExistingWebApplicationScopes 的 scopes 属性为空。
3.2 调用 WebApplicationContextUtils 的 registerWebApplicationScopes() 方法来注册 scope。
进入 registerWebApplicationScopes() 方法如下:
在该方法里面注册了 request 和 session 两个 scope。
向 beanFactory 中 resolvableDependencies 添加了 4 个类型。
3.3 将 3.1 中从 beanFactory 中拿到的 scope 重新保存到 beanFactory 中。
由于 3.1 中没有拿到任何 scope,所以这里不会执行。
然后是判断了basePackages和annotatedClasses是否有值:
经过 DEBUG 发现,basePackages 和 annotatedClasses 此时都无值,所以不进行操作。
5.invokeBeanFactoryPostProcessors
Invoke factory processors registered as beans in the context. 翻译过来就是:调用在上下文中注册为 bean 的工厂处理器。
进入invokeBeanFactoryPostProcessors()方法如下:
方法上注释:Instantiate and invoke all registered BeanFactoryPostProcessor beans, respecting explicit order if given. Must be called before singleton instantiation.
翻译过来就是:实例化并调用所有注册的 BeanFactoryPostProcessor bean,如果给出,则尊重明确的顺序。必须在单例实例化之前调用。( 最后这个没明白啥意思 )
首先调用getBeanFactoryPostProcessors()方法,获取了所有的 beanFactoryPostProcessor 后置处理器,将其传入PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()方法,PostProcessorRegistrationDelegate 是 AbstractApplicationContext 的后置处理器处理的委托操作类。
这里getBeanFactoryPostProcessors()获取到的 beanFactory 后置处理器有如下三个:
前两个是在 10.3 步骤中加载的,第三个是在 10.9 步骤加载的。
这几个类的继承关系如下:
BeanFactoryPostProcessor 接口中只有一个postProcessBeanFactory()方法。
BeanDefinitionRegistryPostProcessor 接口中只有一个postProcessBeanDefinitionRegistry()方法。
\
进入invokeBeanFactoryPostProcessors()方法如下:
\
1.创建了一个 set 类型的 processedBeans,用来存放处理过的 bean。
2.判断当前 beanFactory 是否实现了 BeanDefinitionRegistry 接口。
我们知道,这里传入的 beanFactory 类型为 DefaultListableBeanFactory,查看其类定义,实现了该接口。
3.创建了两个 List
一个是List<BeanFactoryPostProcessor>和List<BeanDefinitionRegistryPostProcessor>。
regularPostProcessors存放的是 常规的 PostProcessor,即直接实现 BeanFactoryPostProcessor接口的。
而 registryProcessors存放的是 注册的 PostProcessor,即直接实现 BeanDefinitionRegistryPostProcessor接口的。
4.然后 for 循环对传入的 beanFactoryPostProcessors 进行处理。
在循环里面,判断当前的 postProcessor 是否实现了 BeanDefinitionRegistryPostProcessor 接口:
如果是,则对其进行类型转换,然后调用其postProcessBeanDefinitionRegistry()方法,这里传入的参数 registry,其实就是 beanFactory。然后添加到 registryProcessors 中。
如果不是,则不执行任何操作,直接添加到 regularPostProcessors 中。
这里有三个 beanFactoryPostProcessors,我们分别来看:
4.1 CachingMetadataReaderFactoryPostProcessor
首先遍历的是 CachingMetadataReaderFactoryPostProcessor,其实现了 BeanDefinitionRegistryPostProcessor 接口。所以会进入它的postProcessBeanDefinitionRegistry()方法如下:
首先是 register() 方法,如下:
将SharedMetadataReaderFactoryBean注册到了 beanDefinitionMap 中,key 见上图。
然后是 configureConfigurationClassPostProcessor() 方法,如下:
从 beanDefinitionMap 中获取指定 key 的 beanDefinition,并为其propertyValues属性设置 metadataReaderFactory 属性的值。
propertyValues 是个 List,而每个元素,又是一个 Map.
运行后,beanDefinitionMap 如下:
4.2 ConfigurationWarningsPostProcessor
接着遍历的是 ConfigurationWarningsPostProcessor,其实现了 BeanDefinitionRegistryPostProcessor 接口。所以会进入它的postProcessBeanDefinitionRegistry()方法如下:
遍历 checks,并调用其 getWarning()方法,进行校验,如果存在 warn 信息,则输出日志。
这里的 checks 只有一个,是 ComponentScanPackageCheck。
它是在 创建 ConfigurationWarningsPostProcessor 对象时,创建了 ComponentScanPackageCheck 对象,并赋值给 checks 的。
进入 ComponentScanPackageCheck 的 getWarning() 方法如下:
方法里面首先调用getComponentScanningPackages()方法获取了需要扫描的包 scanedPackages。然后调用 getProblematicPackages()方法,过滤出有问题的扫描包路径 problematicPackages,最后判断如果真的存在,给出日志。
getComponentScanningPackages() 方法如下:
遍历 beanDefinitionMap,此时有 7 个元素,而启动类就包含在其中。如果是 AnnotatedBeanDefinition 类型的 BeanDefinition 时,就获取该类上的 @ComponentScan注解,得到扫描包路径。这里可能得到多个扫描路径。
getProblematicPackages() 方法如下,就是判断了这些扫描的包路径是否存在问题。
PROBLEM_PACKAGES 则是静态代码块中加载的。
4.3 PropertySourceOrderingPostProcessor
没有实现 BeanDefinitionRegistryPostProcessor 接口,未执行。
5.处理实现了 PriorityOrdered 接口的 BeanDefinitionRegistryPostProcessor
创建了一个List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors用来保存当前需要处理的 BeanDefinitionRegistryPostProcessor。每处理完一种分类的就清空。
根据 BeanDefinitionRegistryPostProcessors 实现的接口,将其划分为三类:实现了 PriorityOrdered 接口的、实现了 Ordered 接口的,一个都没实现的。其处理的先后顺序为:PriorityOrdered > Ordered > No
先来看处理 PriorityOrdered 的:
5.1 从 beanFactory 中获取 BeanDefinitionRegistryPostProcessor 类型的 beanName 数组。
此时的 beanDefinitionMap 中依旧是只有 7 个 bean,如下:
而符合条件的 beanName 只有一个:
其对应的 bean 的 class 类型为:
该 ConfigurationClassPostProcessor 类定义如下:
5.2 判断获取到的 指定 key 的 bean 是否实现了 PriorityOrdered 接口
如果是,则从 beanFactory 中获取该 bean,然后添加到 currentRegistryProcessors 当前处理的 processor 列表中,并添加到 processedBeans 已处理的列表中。
此时 currentRegistryProcessors 中的元素如下:
5.3 对 currentRegistryProcessors 按照优先级进行排序
5.4 将其添加到 registryProcessors 列表中。
registryProcessors 存放的是直接实现 BeanDefinitionRegistryPostProcessor 接口的。
5.5 传入 currentRegistryProcessors,循环调用其postProcessBeanDefinitionRegistry()方法
这里只有 ConfigurationClassPostProcessor,其 postProcessBeanDefinitionRegistry() 方法调用见单独文章,ConfigurationClassPostProcessor
这个 PostProcessor 可以说是 SpringBoot 中最重要的一个 BeanFactoryPostProcessor,它负责将项目中所有注册的 bean 解析为 beanDefinition,当该 后置处理器执行完毕后,此时查看 beanFactory 中的 beanDefinitionMap 如下:
可以看到,现在已经有 900+ 个 beanDefinition 了,而在 ConfigurationClassPostProcessor 的 postProcessBeanDefinitionRegistry() 方法执行之前,只有 7 个。
需要注意的是:这里只是创建了 BeanDefinition 对象,并没有创建其对应的 Bean 对象。
5.6 清空 currentRegistryProcessors 列表。
6..处理实现了 Ordered 接口的 BeanDefinitionRegistryPostProcessor
代码如下:
和处理实现了 PriorityOrdered 接口的逻辑基本一致,不同的是:
6.1 这里再次通过 beanFactory 获取了 postProcessorNames,为什么再次获取呢,之前不是已经获取过了吗?这是因为,前面处理的时候有可能又加入了新的 BeanDefinitionRegistryPostProcessor,所以这里重新进行了获取。
6.2 在循环时,判断了是否被处理,只有没有被处理,并且实现了 Ordered 接口,才会进行后续操作。
这里在 DEBUG 时发现,获取到的 postProcessorNames 依旧只有 ConfigurationClassPostProcessor,而其已经处理过了,所以这块实际上没有执行任何操作。
\
7.最后是处理没有实现上面两个接口的 BeanDefinitionRegistryPostProcessor
代码如下:
使用一个 while 循环来处理,因为每次处理,都有可能增加 BeanDefinitionRegistryPostProcessor。
这里在 DEBUG 时发现,获取到的 postProcessorNames 依旧只有 ConfigurationClassPostProcessor,而其已经处理过了,所以这块实际上没有执行任何操作。
8.调用 postProcessBeanFactory() 方法
两个列表中的元素如下:
进入invokeBeanFactoryPostProcessors()方法,
内部循环调用了 postProcessBeanFactory() 方法。( 注意和前面区分,调用的方法不同 )
首先调用了直接实现 BeanDefinitionRegistryPostProcessor接口的。因为BeanDefinitionRegistryPostProcessor 继承了 BeanFactoryPostProcessor,也具有 postProcessBeanFactory() 方法的,所以也需要执行。
然后调用了直接实现 BeanFactoryPostProcessor接口的。
下面来看看具体每个 postProcessBeanFactory() 方法执行的操作:
1.CachingMetadataReaderFactoryPostProcessor 的 postProcessBeanFactory() 方法是个空方法。
2.ConfigurationWarningsPostProcessor 的 postProcessBeanFactory() 方法是个空方法。
3.ConfigurationClassPostProcessor 的 postProcessBeanFactory() 方法,则是和自动配置有关。
4.PropertySourceOrderingPostProcessor 的 主要作用是对默认的配置文件进行排序,如果存在的话,就将其放在最后一位。这里 DEBUG 是没有的。
9.处理 BeanFactoryPostProcessor
在前面的逻辑执行后,已经有 900+ 个 beanDefinition 了,可能会添加新的 BeanDefinitionRegistryPostProcessor 接口的实现,在上面已经处理过了,但是还没有处理可能会增加的 BeanFactoryPostProcessor 的实现,这里的逻辑便是进行这个操作的。
代码如下:
9.1 从 beanFactory 中获取 BeanFactoryPostProcessor 的实现。
DEBUG 结果如下,共 7 个元素:
9.2 创建了三个 List
priorityOrderedPostProcessors存放实现了 PriorityOrdered 接口的 bean 对象,
orderedPostProcessorNames 存放实现了 Ordered 接口的 beanName
nonOrderedPostProcessorNames 存放没有实现上面两个接口的 beanName
至于为什么,有的存放 bean,有的存放 beanName,暂且不知。
9.3 循环处理,对已经处理过的 processedBeans,不再执行。
DEBUG 结果如下:
10.和上面一样,也是先执行实现了 PriorityOrdered 接口的 BeanFactoryPostProcessor,对其排序后,循环调用其 postProcessBeanFactory() 方法。
PropertySourcesPlaceholderConfigurer 的 postProcessBeanFactory() 方法。具体流程见:PropertySourcesPlaceholderConfigurer
11.执行实现了 Ordered 接口的 BeanFactoryPostProcessor
从 beanFactory 中获取其 bean 对象,排序后,循环执行 postProcessBeanFactory() 方法。
\
12.执行未实现这两个接口的 BeanFactoryPostProcessor
从 beanFactory 中获取其 bean 对象,循环执行 postProcessBeanFactory() 方法。
没有执行排序操作?为什么?
\
13.清空缓存
清空缓存的 merged beanDefinition
进入clearMetadataCache()方法如下:
首先调用了父类 AbstractBeanFactory的clearMetadataCache()方法,如下:
从 mergedBeanDefinitions 中,移除不存在于 alreadyCreated 中的元素。
DEBUG 可知,在清除之前,mergedBeanDefinitions 存在 926 个元素:
alreadyCreated 中存在 12 个元素如下:
所以最后 mergedBeanDefinitions 只剩余 12 个元素。
然后调用 clearByTypeCache() 方法:
这里的 allBeanNamesByType,singletonBeanNamesByType 都为空。