SpringBoot启动方法分析
SpringBoot启动run方法分析
1.场景引入
在项目启动的时候,有时候我们需要在启动的时候,执行一些逻辑。
比如说,项目启动的时候,我想把一些热门商品的数据加载到缓存中去;
比如说,自定义了一个netty服务,我想在项目启动的时候,自动开启这个netty服务;
比如说,................
反正,这个场景大家肯定或多或少会碰到的吧。
下面就按照先后顺序依次介绍各种方式。
// 这个是示例初始化的方法
@Slf4j
public class InitCode {
public static void startMethod( String str) {
log.info("========================【{}】 就是这个~~~~~~~######", str);
}
}
下面的六个方法参考了 https://blog.csdn.net/QIU176161650/article/details/118087254
这篇文章。其中的Servlet相关的,没有作细致分析,故打了**做标记。
①.实现ServletContextListener接口contextInitialized方法**
@Component
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
InitCode.startMethod("ServletContextListener");
}
}
②.@PostConstruct注解方式
这里顺便比较一下InitializingBean接口的方法。
@Component
public class NettyStarter implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
InitCode.startMethod("InitializingBean接口");
}
@PostConstruct
public void init() {
InitCode.startMethod("@PostConstruct");
}
}
③.实现ServletContextAware接口setServletContext 方法**
@Component
public class MyServletContextAware implements ServletContextAware {
@Override
public void setServletContext(ServletContext servletContext) {
InitCode.startMethod("ServletContextAware");
}
}
④.@EventListener方式
@Component
public class MyEventListener {
// 监听ContextRefreshedEvent事件
@EventListener
public void onApplicationEvent(ContextRefreshedEvent event) {
InitCode.startMethod("EventListener");
}
}
⑤.实现ApplicationRunner接口run 方法
@Component
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
InitCode.startMethod("ApplicationRunner");
}
}
⑥.实现CommandLineRunner接口run 方法
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
InitCode.startMethod("CommandLineRunner");
}
}
⑦.顺序演示

通过debug,我们发现前四个打印的是在springBoot的refreshContext(context);之后的。后面两个Runner是callRunners(context, applicationArguments);之后打印的
2.run(args )
这要从SpringBoot的启动流程讲起了。在这篇文章【springboot】【https://www.cnblogs.com/jackjavacpp/p/18653391】中,对run的方法没有作分析,现在我们来看一下run方法。
Spring Boot的启动流程可划分为以下阶段:
- 环境准备:加载配置文件、初始化环境变量。
- 容器创建:创建
ApplicationContext,加载Bean定义。 - Bean实例化:实例化Bean并完成依赖注入。
- 启动完成:执行后置任务,如缓存预热、定时任务启动。
每个阶段均提供扩展点供开发者介入自己的逻辑。
下面以SpringBoot2.7.18源码为例子
//Spring Boot应用启动入口方法,返回已初始化的应用上下文。
public ConfigurableApplicationContext run(String... args) {
// 1.启动计时与引导上下文
long startTime = System.nanoTime();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
// 2.事件监听器初始化
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
// 3.环境准备阶段
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
// 4.Banner打印与上下文创建
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
// 5.上下文准备阶段
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// 6.容器刷新(!!!最核心阶段!!!)
refreshContext(context);
// 7.启动后处理
afterRefresh(context, applicationArguments);
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
listeners.started(context, timeTakenToStartup);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
// 8.应用就绪阶段
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady); // ready事件
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
根据上面的源码结构大致总结出以下流程:
graph TD
A[run()启动] --> B[初始化引导上下文]
B --> C[配置Headless模式]
C --> D[初始化事件监听器]
D --> E[发布ApplicationStartingEvent]
E --> F[准备环境变量]
F --> G[打印Banner]
G --> H[创建应用上下文]
H --> I[准备上下文]
I --> J[刷新上下文]==================最核心
J --> K[发布ApplicationStartedEvent]
K --> L[执行ApplicationRunner]
L --> M[发布ApplicationReadyEvent]
M --> N[返回上下文]
下面对run方法中重要的部分作分析。
①事件监听器初始化
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
// getRunListeners(args)
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),
this.applicationStartup);
}
// getSpringFactoriesInstances(xxx)
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
//SpringFactoriesLoader.loadFactoryNames----
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
通过spring.factories加载所有SpringApplicationRunListener实现类,发布ApplicationStartingEvent事件(最早触发的生命周期事件)
// 发布starting事件
void starting(ConfigurableBootstrapContext bootstrapContext, Class<?> mainApplicationClass) {
doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext),
(step) -> {
if (mainApplicationClass != null) {
step.tag("mainApplicationClass", mainApplicationClass.getName());
}
});
}
②容器刷新
refreshContext(context);
private void refreshContext(ConfigurableApplicationContext context) {
// Spring Boot 扩展点:应用上下文刷新前的处理
if (this.registerShutdownHook) {
shutdownHook.registerApplicationContext(context);
}
refresh(context);
}
// 核心逻辑:调用 Spring Framework 的 refresh() 方法
protected void refresh(ConfigurableApplicationContext applicationContext) {
applicationContext.refresh();
}
// 到抽象类AbstractApplicationContext.java这里来了
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
prepareRefresh(); // 1.准备刷新
// 2. 获取BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
resetCommonCaches();
contextRefresh.end();
}
}
}
refreshContext(context) 是 Spring Boot 启动过程中最核心的阶段之一,负责 Spring 容器的创建、配置和初始化。它直接调用了 Spring Framework 的 AbstractApplicationContext.refresh() 方法,由于我们demo引入了web依赖, Spring Boot 在此基础上进行了扩展(故会有内嵌 Web 容器的启动)。
1) 准备刷新
2) 获取BeanFactory
// AbstractApplicationContext.java
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 销毁旧 BeanFactory(如果存在)
refreshBeanFactory();
// 创建新的 BeanFactory(默认实现为 DefaultListableBeanFactory)
return getBeanFactory();
}
3) 配置BeanFactory
// AbstractApplicationContext.java
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar());
// 添加 BeanPostProcessor(如处理 @Autowired)
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
// 注册环境变量等内置 Bean
beanFactory.registerSingleton("environment", getEnvironment());
}
核心操作:注册内置 Bean(如 Environment)和基础 BeanPostProcessor。
4) 后处理BeanFactory(扩展点)
// 子类可覆盖此方法(如 WebApplicationContext)
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}
5) 执行BeanFactoryPostProcessor
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null &&
beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
// PostProcessorRegistrationDelegate.java
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// 处理 BeanDefinitionRegistryPostProcessor(优先级高)
invokeBeanDefinitionRegistryPostProcessors(postProcessors, registry);
// 处理 BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
}
- 关键扩展点:
- BeanDefinitionRegistryPostProcessor:动态注册 Bean 定义(如
@Configuration类的解析)。 - BeanFactoryPostProcessor:修改 Bean 定义(如属性占位符替换
PropertySourcesPlaceholderConfigurer)。
- BeanDefinitionRegistryPostProcessor:动态注册 Bean 定义(如
- Spring Boot 应用:
ConfigurationClassPostProcessor在此阶段解析@ComponentScan、@Import(包括@EnableAutoConfiguration)等注解。
6) 注册 BeanPostProcessor
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
// PostProcessorRegistrationDelegate.java
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// 获取所有 BeanPostProcessor 并排序
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class);
for (String ppName : postProcessorNames) {
beanFactory.addBeanPostProcessor(beanFactory.getBean(ppName, BeanPostProcessor.class));
}
}
- 作用:将
BeanPostProcessor实例注册到容器,后续 Bean 初始化时会经过这些处理器。 - 关键处理器:
AutowiredAnnotationBeanPostProcessor:处理@Autowired和@Value。CommonAnnotationBeanPostProcessor:处理@PostConstruct、@PreDestroy。AnnotationAwareAspectJAutoProxyCreator:AOP 代理生成。
7) 初始化事件广播器
// AbstractApplicationContext.java
protected void initApplicationEventMulticaster() {
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
} else {
// 默认使用 SimpleApplicationEventMulticaster
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
}
}
初始化事件发布机制,用于后续发布 ContextRefreshedEvent 等事件。
8) 模板方法(onRefresh())--内嵌web容器
protected void onRefresh() throws BeansException {
// For subclasses: do nothing by default.
}
//我们是 ServletWebServerApplicationContext.java
@Override
protected void onRefresh() {
super.onRefresh();
try {
// 创建并启动内嵌的 Web 服务器(如 Tomcat)
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
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());
// ServletWebServerFactory 创建 WebServer
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();
}
// 经过调试发现运行到了StandardContext.java 不是spring框架范围了
public boolean listenerStart() {
...
ServletContextEvent event = new ServletContextEvent(getServletContext());
ServletContextEvent tldEvent = null;
....
ServletContextListener listener = (ServletContextListener) instance;
try {
fireContainerEvent("beforeContextInitialized", listener);
if (noPluggabilityListeners.contains(listener)) {
// ServletContextListener接口contextInitialized
listener.contextInitialized(tldEvent);
} else {
// ServletContextListener接口contextInitialized
listener.contextInitialized(event);
}
} ......
}

- Spring Boot 核心扩展:在此方法中启动内嵌的 Web 容器(如 Tomcat),这是 Spring Boot 与 Spring Framework 的重要区别。
- 流程:
- 通过
ServletWebServerFactory创建WebServer。 - 初始化
DispatcherServlet并注册到 Servlet 容器。
- 通过
9) 注册监听器
// AbstractApplicationContext.java
protected void registerListeners() {
// 添加静态指定的监听器
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 注册 Bean 形式的监听器
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// 发布早期事件(如果有)
publishEarlyApplicationEvents();
}
将 ApplicationListener 注册到事件广播器,确保后续事件能被监听。
10) 【重要】初始化所有单例 Bean
// AbstractApplicationContext.java
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
// DefaultListableBeanFactory.java
public void preInstantiateSingletons() throws BeansException {
...
Object singletonInstance = getSingleton(beanName);
...
}
// DefaultSingletonBeanRegistry.java
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
- 核心逻辑:
DefaultListableBeanFactory.preInstantiateSingletons()方法会遍历所有 Bean 定义,实例化并初始化非懒加载的单例 Bean。 - 关键过程:
- 调用
BeanPostProcessor的前置处理(如 AOP 代理生成)。 - 执行
@PostConstruct方法。 - 调用
InitializingBean.afterPropertiesSet()。
- 调用
getSingleton(String beanName, boolean allowEarlyReference) 如果allowEarlyReference是true的话,就用三级缓存来解决循环依赖【见后续文章】的问题。
debug源码得知,在DefaultListableBeanFactory::preInstantiateSingletons()中,调用了AbstractBeanFactory::getBean(String name)方法,接着往下是,AbstractBeanFactory::doGetBean(xx)方法,在该方法中有这样一个片段
// AbstractBeanFactory.java
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args); //==========这里往下
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// AbstractAutowireCapableBeanFactory.java
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
....
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
}
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
... // 有如下片段
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}.....
}
// AbstractAutowireCapableBeanFactory.java
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 调用 Aware 接口回调
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 1.调用BeanPostProcessors
// ---触发BeanPostProcessor的前置处理
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 2.调用初始化的方法
/*
在这个里面
先((InitializingBean) bean).afterPropertiesSet();
接着
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.hasAnyExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
*/
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 触发BeanPostProcessor的后置处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
initializeBean 方法是 Spring 框架中 Bean 生命周期的核心方法之一,负责:
- 调用 Aware 接口回调(如
BeanNameAware、BeanFactoryAware等)。 - 触发
BeanPostProcessor的前置处理(postProcessBeforeInitialization)。 - 执行 Bean 的初始化方法(
InitializingBean-->invokeInitMethods::afterPropertiesSet或自定义init-method)。 - 触发
BeanPostProcessor的后置处理(postProcessAfterInitialization)。
对于场景引入的例子②中,发现@PostConstruct注解标注的方法,在applyBeanPostProcessorsBeforeInitialization()调用的,也就是在bean的InitializingBean之前就执行了。也就是说@PostConstruct 注解先执行 、 InitializingBean 接口方法 次之。


// 由上面可见,我们可以推断执行顺序如下:
Bean本身的构造函数
BeanPostProcessor的postProcessBeforeInitialization方法
类中添加了注解@PostConstruct 的方法 【上图中的CommonAnnotationBeanPostProcessor】
InitializingBean的afterPropertiesSet方法
initMethod
BeanPostProcessor的postProcessAftrInitialization方法
11) 完成刷新
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
clearResourceCaches();
// Initialize lifecycle processor for this context.
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// Publish the final event.
// 发布一个ContextRefreshed的事件-----------
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
if (!NativeDetector.inNativeImage()) {
LiveBeansView.registerApplicationContext(this);
}
}
可以看到,在容器刷新完成之后,会发布一个ContextRefreshed的事件,所以下面的监听器会监听到。
// 监听ContextRefreshedEvent事件
@EventListener
public void onApplicationEvent(ContextRefreshedEvent event) {
InitCode.startMethod("EventListener");
}
从这里可以看出来,我们框架使用者可以扩展的位置如下:
- BeanFactoryPostProcessor:动态修改 Bean 定义。
- BeanPostProcessor:干预 Bean 的初始化过程(如 AOP)。
- ApplicationListener:监听容器刷新完成事件。
- 自定义 ServletWebServerFactory:修改内嵌服务器配置。
容器刷新这一小节目前就分析到这里了。
③callRunners()
执行所有ApplicationRunner和CommandLineRunner的实现类。执行顺序:通过@Order注解或Ordered接口控制。
//SpringApplication.java
private void callRunners(ApplicationContext context, ApplicationArguments args) {
context.getBeanProvider(Runner.class).orderedStream().forEach((runner) -> {
if (runner instanceof ApplicationRunner) {
callRunner((ApplicationRunner) runner, args);
}
if (runner instanceof CommandLineRunner) {
callRunner((CommandLineRunner) runner, args);
}
});
}
// 执行run方法了,就是我们重写的run
private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
try {
(runner).run(args);
}
catch (Exception ex) {
throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
}
}
private void callRunner(CommandLineRunner runner, ApplicationArguments args) {
try {
(runner).run(args.getSourceArgs());
}
catch (Exception ex) {
throw new IllegalStateException("Failed to execute CommandLineRunner", ex);
}
}
3.总结
经过第二大节的整体分析,我们大致可以知道
- 在容器刷新之前,由于是Servlet的Application,故由模板方法运行创建Servlet容器,ServletContextListener接口contextInitialized会先执行。
- 调用构造方法创建bean对象,实例化
- aware接口
- BeanPostProcessor :: postProcessBeforeInitialization()
- @PostConstruct ---- 【CommonAnnotationBeanPostProcessor】
- InitializingBean接口的afterPropertiesSet()
- 自定义的initMethod
- BeanPostProcessor :: postProcessAfterInitialization()
- Runners
对于Spring的容器创建、bean的创建、以及事件等内容的详细分析,请见后续文章。本文通过对SpringBoot一个使用场景,在参考了别人的方法之后,想要探究其原理,对其启动过程作了一个大致的分析。
4.思考题
对上面作了大致分析后,其实还有其他方法,可以在需要在启动的时候,执行一些逻辑。
监听 ApplicationReadyEvent 事件.
@Component
public class StartupListener {
@EventListener(ApplicationReadyEvent.class)
public void onApplicationReady() {
InitCode.startMethod("ApplicationReadyEventListener");
}
}
这个在什么阶段执行呢?
第二个问题?上面的4种方法【去掉**的】 + 思考题中的方法 = 5种方法。他们各自有什么优劣呢?
end. 参考
- https://blog.csdn.net/QIU176161650/article/details/118087254
- https://blog.csdn.net/weixin_53287520/article/details/139484810
- https://blog.csdn.net/yerenyuan_pku/article/details/110442093
- https://blog.csdn.net/m0_61933976/article/details/128697003
示例代码仓库见 【https://gitee.com/quercus-sp204/sourcecode-and-demos】中的 “netty-sp” 模块部分。
SpringBoot启动方法分析的更多相关文章
- SpringBoot启动流程分析(二):SpringApplication的run方法
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- SpringBoot启动流程分析(三):SpringApplication的run方法之prepareContext()方法
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- SpringBoot启动原理分析
用了差不多两年的SpringBoot了,可以说对SpringBoot已经很熟了,但是仔细一想SpringBoot的启动流程,还是让自己有点懵逼,不得不说是自己工作和学习的失误,所以以此文对Spring ...
- SpringBoot启动流程分析(五):SpringBoot自动装配原理实现
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- SpringBoot启动流程分析(六):IoC容器依赖注入
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- SpringBoot启动流程分析(一):SpringApplication类初始化过程
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- SpringBoot启动流程分析(四):IoC容器的初始化过程
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- viewController启动方法分析
viewController启动方法分析 转载:http://blog.csdn.net/dizzthxl/article/details/14170047 首先理清楚一个概念: 创建一个类和实例化一 ...
- SpringBoot启动流程分析原理(一)
我们都知道SpringBoot自问世以来,一直有一个响亮的口号"约定优于配置",其实一种按约定编程的软件设计范式,目的在于减少软件开发人员在工作中的各种繁琐的配置,我们都知道传统的 ...
- SpringBoot启动流程分析
前景提示 @ComponentScan 的处理都放在org.springframework.context.annotation.ConfigurationClassParser#doProcess ...
随机推荐
- 前端(二)-CSS
1.样式 1.1 行内样式 <h1 style="color:red;">行内样式</h1> 1.2 内部样式 CSS代码写在 <head> 的 ...
- springboot整合security实现权限控制
1.建表,五张表,如下:1.1.用户表CREATE TABLE `t_sys_user` ( `user_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT ...
- Apollo架构设计
Apollo架构设计 Apollo有一点很好,就是它是由国内携程团队开发,而且文档写的很全,代码也完全开源.如果去了解它也可以直接去看它的官方文档. 一.配置中心概念 1.背景 在实际开发中都会与配置 ...
- 解决StringBuilder readline阻塞问题
readline之所以会阻塞socket流没有结束符 阻塞场景:read() 没有读取到任何数据 readLine() 没有读取到结束符或者换行符 可以用ready判断通道中数据是否读完,读完返回fa ...
- ASP.NET Core 快速轻量级的浏览器检测和设备检测库
在 .NET Framework 4.7 中那样,通过 HttpContext.Request 的 Browser 属性轻松获取发起 HTTP 请求的浏览器信息,ASP.NET Core 并未直接提供 ...
- 一键部署,玩转AI!天翼云Llama 3大模型学习机来了!
近日,Meta公司发布了其最新研发成果--开源大模型Llama 3,共包含Llama 3 8B和Llama 3 70B两种规格,参数量级分别为80亿与700亿,并表示这是目前同体量下性能最好的开源模型 ...
- 玩转云端 | 天翼云边缘安全加速平台AccessOne实用窍门之多款产品管理难?一站式平台管理全hold住!
随着数字化转型深入推进,企业信息化建设成效显著,同时其所面临的安全与性能挑战也日趋复杂,既要确保业务系统的安全性,同时也要提供快速.流畅的用户体验,以提升用户满意度和业务竞争力. 在传统的解决方案中, ...
- 「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项,以及粗浅的原理解析!
> 由于网页编辑器简陋,无法实现原文档的精心排版,如需原文档可联系... 序 「ximagine」在本篇文章中将介绍「荒岛」目前所使用的显示器测试流程及标准,我们主要使用Calman.Displ ...
- 自助式BI:灵活应变的商业智能
在这个信息爆炸的时代,商业智能(BI)已经成为企业决策的必备工具.无论是哪个行业,哪个规模的企业,似乎都无法忽视这一强大工具的存在.然而,传统的BI模式往往存在着一些限制,使得企业无法灵活地应对各种业 ...
- KUKA库卡机器人KR120维修故障参考方案
随着智能制造的飞速发展,KUKA库卡机器人KR120以其稳定的特点,在自动化生产线上扮演着举足轻重的角色.然而,任何机械设备在长期运行过程中都难免会遇到故障.本文将针对KUKA库卡机器人KR120维修 ...