【SpringBoot】启动过程之——SpringApplication初始化及运行

Spring Boot 工程的主函数

@SpringBootApplication()
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(WhidsSsApplication.class, args);
    }
}

分为了两个部分:

  • 初始化 SpringApplication
new SpringApplication
  • 运行 SpringApplication
springApplication.run()

1. 初始化 SpringApplication

配置基本的环境变量、资源、构造器、监听器。

初始化阶段的主要作用是为运行 SpringApplication 实例对象启动环境变量准备、以及进行资源构造器的初始化动作。

@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
   this.resourceLoader = resourceLoader;
   Assert.notNull(primarySources, "PrimarySources must not be null");
   this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
   this.webApplicationType = WebApplicationType.deduceFromClasspath();
   this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories();
   setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
   setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
   this.mainApplicationClass = deduceMainApplicationClass();
}
  1. setInitializers,实例化所有初始器:
    加载 ApplicationContextInitializer 是在 SpringFactoriesLoader.loadFactoryNames 方法里面进行的。这个方法会尝试从类路径的 META-INF/spring.factories 读取相应配置文件,然后进行遍历,读取配置文件中Key为:org.springframework.context.ApplicationContextInitializer 的 value。
    以 spring-boot 为例,它的 Initializers 定义如下,Initializers 的作用在上一章中已详细解释
# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
  1. setListeners,实例化所有监听器
    同样以 spring-boot 为例,它的 Initializers 定义如下:
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.env.EnvironmentPostProcessorApplicationListener

2. 运行 SpringApplication

Spring Boot 正式启动加载过程,包括启动流程监控模块、配置环境加载模块、ApplicationContext 容器上下文环境加载模块。

其中的一些关键步骤:

  1. 发布应用启动过程中的一系列事件
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);

SpringApplicationRunListeners 本质上是一个事件发布者,它在 SpringBoot 应用启动的不同时间点发布不同应用事件类型(ApplicationEvent):
在这里插入图片描述
由上文知在初始化的流程中,SpringApplication 加载了一系列 ApplicationListener,其监听的事件就是在这里发布的。

  1. 创建应用程序上下文
    ApplicationContext,也就是我们所说的 Spring Ioc 容器,是在 BeanFactory 的基础之上的一种更高级的容器,除了具有基本的 bean 管理功能之外,还提供对事件监听机制以及国际化的支持等。
context = createApplicationContext();
  1. 准备ApplicationContext
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);

主要完成以下工作:

  • 实例化单例的 BeanNameGenerator
// public static final String CONFIGURATION_BEAN_NAME_GENERATOR =
//      "org.springframework.context.annotation.internalConfigurationBeanNameGenerator";
      
context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
      this.beanNameGenerator);

Spring 定义 bean 有两种模式:配置文件(xml,properties)和注解。BeanNameGenerator 是为 bean 定义生成 bean 名称的策略接口。
其实现类有两个:
DefaultBeanNameGenerator :用来处理 xml 资源文件,但一般情况下在 Spring Boot 中我们很少使用 xml 来引入 bean;
AnnotationBeanNameGenerator :处理 @Component 等注解生成 bean name。当注解中有 value 属性时,则给 bean 命名为 value 值。当没有指定名称时,则根据类名自动生成。

  • 执行初始化方法。在初始化阶段中我们加载了所有的 ApplicationContextInitializer ,依次执行
initializer.initialize(context);
  • 发布事件,通知监听者 ApplicationContext 已经准备完毕
listeners.contextLoaded(context);

void contextLoaded(ConfigurableApplicationContext context) {
   doWithListeners("spring.boot.application.context-loaded", (listener) -> listener.contextLoaded(context));
}
  • 将所有的bean加载到容器中
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
  • 再次发布事件,通知监听者 ApplicationContext 已经装载完毕
listeners.contextLoaded(context);
  1. 刷新上下文,属于 spring 中的机制,包括了属性自动装配等步骤
refreshContext(context);
  1. 发布上下文准备就绪事件
listeners.started(context);
### Spring Boot 初始化与模板配置 #### 使用 `@SpringBootApplication` 注解简化配置 在 Spring Boot 应用中,`@SpringBootApplication` 是一个复合注解,包含了常用的三个核心功能:自动配置、组件扫描以及启用基于约定优于配置的原则。这使得开发者可以快速搭建应用程序而无需过多关注底层细节[^2]。 ```java @SpringBootApplication public class ProviderApp { public static void main(String[] args) { SpringApplication.run(ProviderApp.class, args); } } ``` #### 自定义初始化逻辑 为了实现特定于项目的启动时操作,可以通过实现 `ApplicationRunner` 或者 `CommandLineRunner` 接口来编写自定义的初始化器。这些接口允许在应用上下文完全加载之后执行额外的任务,比如数据预加载或服务注册等[^1]。 ```java @Component public class InitInfo implements ApplicationRunner { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Override public void run(ApplicationArguments args) throws Exception { // 执行必要的初始化工作 logger.info("Initializing application..."); } } ``` #### 利用 Spring Initializr 创建项目结构 对于新项目的创建,推荐使用官方提供的工具——Spring Initializr,在线平台能够帮助生成带有基本依赖项和服务端点的基础工程文件夹。只需指定所需的框架版本和技术栈选项即可获得完整的 Maven 或 Gradle 构建脚本[^3]。 访问地址:<https://start.spring.io/> ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值