SpringBoot是如何动起来的

程序入口

SpringApplication.run(BeautyApplication.class, args);

执行此方法来加载整个SpringBoot的环境。

1. 从哪儿开始?

SpringApplication.java

 /**
 * Run the Spring application, creating and refreshing a new
 * {@link ApplicationContext}.
 * @param args the application arguments (usually passed from a Java main method)
 * @return a running {@link ApplicationContext}
 */
 public ConfigurableApplicationContext run(String... args) {
 //...
 }

调用SpringApplication.java 中的 run 方法,目的是加载Spring Application,同时返回 ApplicationContext。

2. 执行了什么?

2.1 计时

记录整个Spring Application的加载时间!

StopWatch stopWatch = new StopWatch();
stopWatch.start();
// ...
stopWatch.stop();
if (this.logStartupInfo) {
 new StartupInfoLogger(this.mainApplicationClass)
 .logStarted(getApplicationLog(), stopWatch);
}

2.2 声明

// 声明 ApplicationContext
ConfigurableApplicationContext context = null;
// 声明 一个异常报告集合
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();

2.3 指定程序运行模式

指定 java.awt.headless,默认是true

一般是在程序开始激活headless模式,告诉程序,现在你要工作在Headless mode下,就不要指望硬件帮忙了,你得自力更生,依靠系统的计算能力模拟出这些特性来。

private void configureHeadlessProperty() {
 System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, System.getProperty(
 SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}

2.4 配置监听并发布应用启动事件


SpringApplicationRunListener 负责加载 ApplicationListener事件。

SpringApplicationRunListeners listeners = getRunListeners(args);
// 开始
listeners.starting();
// 处理所有 property sources 配置和 profiles 配置,准备环境,分为标准 Servlet 环境和标准环境
ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);
// 准备应用上下文
prepareContext(context, environment, listeners, applicationArguments,printedBanner);
// 完成
listeners.started(context);
// 异常
handleRunFailure(context, ex, exceptionReporters, listeners);
// 执行
listeners.running(context);

getRunListeners 中根据 type =
SpringApplicationRunListener.class 去拿到了所有的 Listener 并根据优先级排序。

对应的就是 META-INF/spring.factories 文件中的
org.springframework.boot.SpringApplicationRunListener=org.springframework.boot.context.event.EventPublishingRunListener

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
 Class<?>[] parameterTypes, Object... args) {
 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
 // Use names and ensure unique to protect against duplicates
 Set<String> names = new LinkedHashSet<>(
 SpringFactoriesLoader.loadFactoryNames(type, classLoader));
 List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
 classLoader, args, names);
 AnnotationAwareOrderComparator.sort(instances);
 return instances;
 }

在 ApplicationListener 中 , 可以针对任何一个阶段插入处理代码。

public interface SpringApplicationRunListener {
 /**
 * Called immediately when the run method has first started. Can be used for very
 * early initialization.
 */
 void starting();
 /**
 * Called once the environment has been prepared, but before the
 * {@link ApplicationContext} has been created.
 * @param environment the environment
 */
 void environmentPrepared(ConfigurableEnvironment environment);
 /**
 * Called once the {@link ApplicationContext} has been created and prepared, but
 * before sources have been loaded.
 * @param context the application context
 */
 void contextPrepared(ConfigurableApplicationContext context);
 /**
 * Called once the application context has been loaded but before it has been
 * refreshed.
 * @param context the application context
 */
 void contextLoaded(ConfigurableApplicationContext context);
 /**
 * The context has been refreshed and the application has started but
 * {@link CommandLineRunner CommandLineRunners} and {@link ApplicationRunner
 * ApplicationRunners} have not been called.
 * @param context the application context.
 * @since 2.0.0
 */
 void started(ConfigurableApplicationContext context);
 /**
 * Called immediately before the run method finishes, when the application context has
 * been refreshed and all {@link CommandLineRunner CommandLineRunners} and
 * {@link ApplicationRunner ApplicationRunners} have been called.
 * @param context the application context.
 * @since 2.0.0
 */
 void running(ConfigurableApplicationContext context);
 /**
 * Called when a failure occurs when running the application.
 * @param context the application context or {@code null} if a failure occurred before
 * the context was created
 * @param exception the failure
 * @since 2.0.0
 */
 void failed(ConfigurableApplicationContext context, Throwable exception);
}

3. 每个阶段执行的内容

3.1 listeners.starting();

在加载Spring Application之前执行,所有资源和环境未被加载。

3.2 prepareEnvironment(listeners, applicationArguments);

创建 ConfigurableEnvironment;

将配置的环境绑定到Spring Application中;

 private ConfigurableEnvironment prepareEnvironment(
 SpringApplicationRunListeners listeners,
 ApplicationArguments applicationArguments) {
 // Create and configure the environment
 ConfigurableEnvironment environment = getOrCreateEnvironment();
 configureEnvironment(environment, applicationArguments.getSourceArgs());
 listeners.environmentPrepared(environment);
 bindToSpringApplication(environment);
 if (this.webApplicationType == WebApplicationType.NONE) {
 environment = new EnvironmentConverter(getClassLoader())
 .convertToStandardEnvironmentIfNecessary(environment);
 }
 ConfigurationPropertySources.attach(environment);
 return environment;
 }

3.3 prepareContext

配置忽略的Bean;

 private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
 if (System.getProperty(
 CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
 Boolean ignore = environment.getProperty("spring.beaninfo.ignore",
 Boolean.class, Boolean.TRUE);
 System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME,
 ignore.toString());
 }
 }

打印日志-加载的资源

Banner printedBanner = printBanner(environment);

根据不同的WebApplicationType创建Context

context = createApplicationContext();

3.4 refreshContext

支持定制刷新

 /**
 * Register a shutdown hook with the JVM runtime, closing this context
 * on JVM shutdown unless it has already been closed at that time.
 * <p>This method can be called multiple times. Only one shutdown hook
 * (at max) will be registered for each context instance.
 * @see java.lang.Runtime#addShutdownHook
 * @see #close()
 */
 void registerShutdownHook();

3.5 afterRefresh

刷新后的实现方法暂未实现

 /**
 * Called after the context has been refreshed.
 * @param context the application context
 * @param args the application arguments
 */
 protected void afterRefresh(ConfigurableApplicationContext context,
 ApplicationArguments args) {
 }

3.6 listeners.started(context);

到此为止, Spring Application的环境和资源都加载完毕了;

发布应用上下文启动完成事件;

执行所有 Runner 运行器 - 执行所有 ApplicationRunner 和 CommandLineRunner 这两种运行器

// 启动
callRunners(context, applicationArguments);

3.7 listeners.running(context);

触发所有
SpringApplicationRunListener 监听器的 running 事件方法

l链接:juejin.im/post/5c6f730ce51d457f14363a53

回复“资源”,视频教程,微服务、并发,数据可调优等免费给大家分享

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot 态生成配置可以通过使用 Spring Boot 的 ConfigurationProperties 注解和 Spring 的 Environment 对象来实现。具体步骤如下: 1. 在 application.properties 或 application.yml 文件中定义默认的配置属性。 2. 创建一个 Java 类,并使用 @ConfigurationProperties 注解将其与默认配置属性关联起来。在这个类中,你可以定义一些属性和方法,用于态生成配置。 3. 在 Spring Boot 应用程序中,使用 @EnableConfigurationProperties 注解将这个类注册为一个 Bean。 4. 在需要态生成配置的地方,使用 Spring 的 Environment 对象获取配置属性,并根据需要修改它们。 5. 如果需要将修改后的配置保存到文件中,可以使用 Spring 的 ConfigurableEnvironment 对象将其写入到 application.properties 或 application.yml 文件中。 下面是一个简单的示例代码: ``` @Configuration @ConfigurationProperties(prefix = "myconfig") public class MyConfig { private String name; private int age; // getter and setter methods public void updateConfig(Environment env) { this.name = env.getProperty("myconfig.name"); this.age = Integer.parseInt(env.getProperty("myconfig.age")); // modify the configuration properties as needed } } @SpringBootApplication @EnableConfigurationProperties(MyConfig.class) public class MyApp { public static void main(String[] args) { SpringApplication.run(MyApp.class, args); } @Autowired private MyConfig myConfig; @EventListener(ApplicationReadyEvent.class) public void onApplicationReady() { myConfig.updateConfig(Environment); // use the updated configuration properties } } ``` 在这个示例中,MyConfig 类与名为 myconfig 的默认配置属性关联起来。在应用程序启后,它会从 Environment 对象中获取配置属性,并根据需要修改它们。在 onApplicationReady 方法中,我们可以使用更新后的配置属性来执行一些操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值