上一篇文章分析了除 refresh 方法外的流程,并着重分析了 load 方法,这篇文章就主要分析 refresh 方法,可以说 refresh 方法是 springboot 启动流程最重要的一环,没有之一。
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
该方法是由 AnnotationConfigServletWebServerApplicationContext 类调用的,不过它也是调用的父类的方法,所以你可以直接挪到 AbstractApplicationContext 抽象类即可。
一、invokeBeanFactoryPostProcessors
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
......
}
这里的 beanFactory 是 DefaultListableBeanFactory,它是 BeanDefinitionRegistry 是实例,至于怎么来的我想你应该清楚哈。然后在这片段代码里,我们比较注意的是 registryProcessor.postProcessBeanDefinitionRegistry(registry)。
这时你应该想到 beanFactoryPostProcessors 的值是怎么来的,如果你往前追溯的话,可以知道是在 prepareContext 方法里赋值的。这里我们选其中一个 SharedMetadataReaderFactoryContextInitializer 看看:
它会注册 SharedMetadataReaderFactoryBean 工厂并且会额外注册一个 processor,这也是后面为啥会多次遍历的原因。
另外需要注意到的是它分成了两个类型的 processor,一个是 regularPostProcessors,另一个是 registryProcessors。
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
接着我们看这段代码,这里的注释意思很清楚:不要在这里实例化 FactoryBeans,我们需要把所有的 regular beans 留给 beanFactory 的 post-processors 去处理。然后将 BeanDefinitionRegistryPostProcessors 分离为实现了 PriorityOrdered、Ordered 两类,以及剩下的为一类,然后调用 invokeBeanDefinitionRegistryPostProcessors 方法进行处理。
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
.tag("postProcessor", postProcessor::toString);
postProcessor.postProcessBeanDefinitionRegistry(registry);
postProcessBeanDefRegistry.end();
}
我们以其中一个 postProcessor 进行说明,比如 ConfigurationClassPostProcessor:
它的作用是在应用程序上下文启动时,扫描配置类(被 @Configuration 注解标记的类)并解析其中的 @Bean 注解,将其转化为对应的BeanDefinition对象,并注册到BeanDefinitionRegistry 中。这样,这些配置类中的 @Bean 方法就可以被容器识别并实例化为相应的 Bean 对象。
接着就开始调用 invokeBeanFactoryPostProcessors 来处理 regularPostProcessors 和 registryProcessors,
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
StartupStep postProcessBeanFactory = beanFactory.getApplicationStartup().start("spring.context.bean-factory.post-process")
.tag("postProcessor", postProcessor::toString);
postProcessor.postProcessBeanFactory(beanFactory);
postProcessBeanFactory.end();
}
}
它会调用这些工厂的 postProcessBeanFactory 方法,还是拿 ConfigurationClassPostProcessor 举例:
它的作用是对 BeanFactory 进行进一步的处理和配置,确保配置类中的 Bean 能够正确注册到容器中,并处理配置类之间的依赖关系和导入关系。
二、registerBeanPostProcessors
该方法和上面的步骤也差不多,registerBeanPostProcessors 方法的作用是将所有的 BeanPostProcessor(后置处理器)注册到 BeanFactory 中。在应用程序上下文启动时,会调用该方法来注册所有的 BeanPostProcessor,以便在 Bean 的创建过程中进行相应的处理。BeanPostProcessor 是 Spring 框架提供的一种机制,用于在Bean的实例化和初始化过程中对 Bean 进行额外的处理。它可以在 Bean 实例化之前和初始化之后对 Bean 进行修改、增强或进行其他操作。通常,开发人员可以通过实现 BeanPostProcessor 接口来自定义自己的后置处理器。registerBeanPostProcessors 方法的主要作用是将所有实现了 BeanPostProcessor 接口的类实例化,并添加到 BeanFactory 中的后置处理器列表中。这样,在 Bean 的创建过程中,Spring 容器会依次调用这些后置处理器的方法,对 Bean 进行相应的处理。这些处理器可以对 Bean 进行增强、修改属性值、解析注解等操作,以满足特定的需求。
三、onRefresh
该方法会创建 WebServer:
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");
ServletWebServerFactory factory = getWebServerFactory();
createWebServer.tag("factory", factory.getClass().toString());
this.webServer = factory.getWebServer(getSelfInitializer());
createWebServer.end();
getBeanFactory().registerSingleton("webServerGracefulShutdown",
new WebServerGracefulShutdownLifecycle(this.webServer));
getBeanFactory().registerSingleton("webServerStartStop",
new WebServerStartStopLifecycle(this, this.webServer));
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context", ex);
}
}
initPropertySources();
}
四、finishBeanFactoryInitialization
finishBeanFactoryInitialization 法的作用是完成 BeanFactory 的初始化过程。在应用程序上下文启动时,会调用该方法来完成 BeanFactory 的初始化工作,包括实例化和初始化所有的非延迟加载的单例 Bean。
具体来说,finishBeanFactoryInitialization 方法会按照以下步骤完成 BeanFactory 的初始化:
- 实例化所有非延迟加载的单例 Bean:根据 Bean 定义信息,通过反射或其他方式实例化所有非延迟加载的单例 Bean,并将它们放入容器中。
- 依赖注入:对所有实例化的 Bean 进行依赖注入,即将它们所依赖的其他 Bean 注入到相应的属性中。
- 初始化:对所有实例化并注入依赖的 Bean 进行初始化。这包括调用 Bean 的初始化方法(如果有定义的话),以及应用任何配置的 Bean 后置处理器对 Bean 进行处理。
- 完成 BeanFactory 的初始化:将 BeanFactory 的状态设置为已初始化完成,标记整个初始化过程的结束。
通过调用 finishBeanFactoryInitialization 方法,Spring 容器能够确保所有非延迟加载的单例 Bean 都被正确实例化、注入依赖和初始化,从而使它们可以在应用程序中被正常使用。
五、finishRefresh
finishRefresh 方法的作用是在应用程序上下文刷新完成后执行一些额外的操作。
在应用程序上下文的刷新过程中,会调用该方法来完成一些与刷新相关的收尾工作。
具体来说,finishRefresh方法会按照以下步骤完成额外的操作:
- 初始化生命周期处理器:对于实现了 Lifecycle 接口的 Bean,会调用它们的 start 方法来启动这些 Bean。
- 发布应用程序上下文已完成事件:通过 ApplicationEventPublisher,发布一个 ContextRefreshedEvent 事件,通知其他监听器应用程序上下文已完成刷新。
- 注册 ApplicationListener 的 Bean:将实现了 ApplicationListener 接口的 Bean 注册到应用程序上下文中,以便监听其他事件。
- 初始化其他单例 Bean:对于非延迟加载的单例 Bean,会调用它们的初始化方法(如果有定义的话)。
- 发布应用程序上下文已启动事件:通过 ApplicationEventPublisher,发布一个 ContextStartedEvent 事件,通知其他监听器应用程序上下文已启动。
通过调用finishRefresh方法,Spring容器能够在应用程序上下文刷新完成后执行一些额外的操作,如启动生命周期处理器、发布事件等。这些操作可以用于执行一些初始化、通知或其他自定义的逻辑,以满足特定的需求。
6、总结
refresh 方法感觉还是比较难以分析,后面部分文字内容还是借鉴了 ChatGPT,感觉如果你想知道某个函数的作用时,直接问它,它或许会告诉你正确答案,比如你这样问:finishRefresh 方法的作用是啥?
标签:初始化,SpringBoot,beanFactory,方法,应用程序,Bean,postProcessor,第二篇,追踪 From: https://www.cnblogs.com/M-Anonymous/p/17618207.html