一、Spring Boot启动流程
在了解Spring Boot的启动顺序之前,我们需要先了解Spring Boot的启动流程。在Spring Boot启动时,会以SpringApplication为入口进行启动。SpringApplication会开启一些基本的事件(ApplicationEvent),并将这些事件发送给所有注册了相应监听器(ApplicationListener)的组件进行处理。
因此,Spring Boot的启动流程可以概括为以下几步:
- 创建SpringApplication
- 执行SpringApplication的run()方法
- SpringApplication会依次发布以下事件:ApplicationStartingEvent、ApplicationEnvironmentPreparedEvent、ApplicationContextInitializedEvent、ApplicationPreparedEvent、ApplicationStartedEvent、ApplicationReadyEvent、ApplicationFailedEvent
- 所有注册了相应的监听器会处理它们感兴趣的事件
二、Spring Boot启动顺序
1. SpringApplication构造函数
在创建SpringApplication实例的时候,Spring Boot会进行相关的初始化和准备阶段。在这个过程中,Spring Boot会根据一些默认设置来决定要使用哪些特性,并对这些特性进行配置。比如,自动配置、Profile、配置文件等。
示例代码
@SpringBootApplication public class SpringApplicationDemo { public static void main(String[] args) { SpringApplication application = new SpringApplication(SpringApplicationDemo.class); application.run(args); } }
2. ApplicationStartingEvent
在调用SpringApplication的run()方法之前,SpringApplication会发布ApplicationStartingEvent事件。这个事件表示SpringApplication即将启动。在这个事件中,我们可以进行一些相关的操作,比如输出程序启动日志。
示例代码
@Component public class StartingEventListener implements ApplicationListener<ApplicationStartingEvent> { private static final Logger LOGGER = LoggerFactory.getLogger(StartingEventListener.class); @Override public void onApplicationEvent(ApplicationStartingEvent event) { LOGGER.info("Application is starting with args: {}", Arrays.toString(event.getArgs())); } }
3. ApplicationEnvironmentPreparedEvent
在执行run()方法之前,SpringApplication会发布ApplicationEnvironmentPreparedEvent事件。在这个事件中,我们可以对应用程序的环境进行一些自定义配置,比如添加自定义属性、配置环境变量等。
示例代码
@Component public class EnvironmentPreparedEventListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> { @Override public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) { ConfigurableEnvironment environment = event.getEnvironment(); Map<String, Object> properties = new HashMap<>(); properties.put("server.port", 8081); PropertiesPropertySource propertySource = new PropertiesPropertySource("customProperties", properties); environment.getPropertySources().addFirst(propertySource); } }
4. ApplicationContextInitializedEvent
在执行run()方法时,Spring Boot会发布ApplicationContextInitializedEvent事件。这个事件表示ApplicationContext正在被创建,但是还没有加载任何Bean。在这个事件中,我们可以手动往ApplicationContext中添加一些Bean。
示例代码
@Component public class ContextInitializedEventListener implements ApplicationListener<ApplicationContextInitializedEvent> { @Override public void onApplicationEvent(ApplicationContextInitializedEvent event) { ConfigurableApplicationContext context = event.getApplicationContext(); context.getBeanFactory().registerSingleton("myBean", new Object()); } }
5. ApplicationPreparedEvent
在上一步中,ApplicationContext成功创建并加载了所有的Bean。在执行run()方法之前,Spring Boot会发布ApplicationPreparedEvent事件。在这个事件中,我们可以获取ApplicationContext,并进行一些自定义配置。
示例代码
@Component public class PreparedEventListener implements ApplicationListener<ApplicationPreparedEvent> { @Override public void onApplicationEvent(ApplicationPreparedEvent event) { ConfigurableApplicationContext context = event.getApplicationContext(); DataSource dataSource = context.getBean(DataSource.class); try { dataSource.getConnection().close(); } catch (SQLException e) { e.printStackTrace(); } } }
6. ApplicationStartedEvent
在上一步结束后,ApplicationContext会被刷新,并启动完成。在这个时候,Spring Boot会发布ApplicationStartedEvent事件。在这个事件中,我们可以进行一些启动后的操作,比如数据初始化。
示例代码
@Component public class StartedEventListener implements ApplicationListener<ApplicationStartedEvent> { private static final Logger LOGGER = LoggerFactory.getLogger(StartedEventListener.class); @Override public void onApplicationEvent(ApplicationStartedEvent event) { LOGGER.info("Application has started..."); } }
7. ApplicationReadyEvent
当应用程序启动并且ApplicationContext中的Bean都已经装配好之后,Spring Boot会发布ApplicationReadyEvent事件,这个事件表示此时应用程序已经准备好了。我们可以在这种情况下进行一些定时任务的启动、消息的处理等操作。
示例代码
@Component public class ReadyEventListener implements ApplicationListener<ApplicationReadyEvent> { @Override public void onApplicationEvent(ApplicationReadyEvent event) { TimerTask task = new TimerTask() { @Override public void run() { System.out.println("I'm a TimerTask!"); } }; Timer timer = new Timer(); timer.schedule(task, 5000L); } }
8. ApplicationFailedEvent
如果应用程序启动失败,Spring Boot会发布ApplicationFailedEvent事件,这个事件表示应用程序启动过程中出现了错误。在这个事件中我们可以获取到失败的原因,并进行相应的处理。
示例代码
@Component public class FailedEventListener implements ApplicationListener<ApplicationFailedEvent> { @Override public void onApplicationEvent(ApplicationFailedEvent event) { Throwable throwable = event.getException(); LOGGER.error("Application failed to start: {}", throwable.getMessage()); } }
三、总结
通过本文的介绍,我们可以详细了解Spring Boot启动顺序背后的机制和原理。在实际开发中,我们可以根据自己的需求选择合适的时间点进行自定义操作,从而达到更加优美的应用启动顺序。