关于java:SpringBoot-启动流程

启动入口

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        // step.1
        SpringApplication.run(DemoApplication.class, args);
    }
}

实例化 SpringApplication 对象

// step.2
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
    return run(new Class[]{primarySource}, args);
}

// step.3 
// 实例化SpringApplication对象,在构造方法内加载一些资源
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
    return new SpringApplication(primarySources).run(args);
}

// step.4
public SpringApplication(Class<?>... primarySources) {
    this(null, primarySources);
}

加载运行类信息 & 确定利用类型 & 加载初始化器 & 加载监听器 & 设置运行主类

// step.5
@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    this.resourceLoader = resourceLoader;
    Assert.notNull(primarySources, "PrimarySources must not be null");
    // 加载运行类信息,此处的primarySources实际上是启动传入的class
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    // 确定利用类型,默认servlet
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    this.bootstrapRegistryInitializers = new ArrayList<>(getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
    // 加载初始化器
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    // 加载监听器
    setListeners((Collection)getSpringFactoriesInstances(ApplicationListener.class));
    // 设置运行主类
    this.mainApplicationClass = deduceMainApplicationClass();
}

如果心愿自定义初始化器,则须要实现 ApplicationContextInitializer 接口
加载心愿自定义监听器,则须要实现 ApplicationListener 接口
以上两者都须要在resources目录下增加 META-INF/spring.factories 配置文件,将自定义的初始化器注册进去

执行启动办法 run()

// step.6
/**
 * 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) {
    // 记录启动开始工夫
    long startTime = System.nanoTime();
    DefaultBootstrapContext bootstrapContext = createBootstrapContext();
    // 申明利用上下文
    ConfigurableApplicationContext context = null;
    // 设置 无显示器仍然启动
    configureHeadlessProperty();
    // 创立所有 Spring 运行监听器并公布利用启动事件 并启用监听器
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting(bootstrapContext, this.mainApplicationClass);
    try {
        // 封装利用参数
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        // 环境筹备
        ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
        configureIgnoreBeanInfo(environment);
        // 打印banner
        Banner printedBanner = printBanner(environment);
        // 创立利用上下文
        context = createApplicationContext();
        context.setApplicationStartup(this.applicationStartup);
        // 把相干的类放入上下文中
        prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
        // 刷新上下文;
        // 将上述被加载的bean实例化;
        // @EnableAutoConfiguration 配置在此拆卸 
        // 启动tomcat
        refreshContext(context);
        // 刷新上下文后置解决
        afterRefresh(context, applicationArguments);
        // 记录启动实现时长
        Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
        }
        // 公布上下文准备就绪事件
        listeners.started(context, timeTakenToStartup);
        // 执行自定义的run办法
        callRunners(context, applicationArguments);
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, listeners);
        throw new IllegalStateException(ex);
    }
    try {
        Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
        listeners.ready(context, timeTakenToReady);
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, null);
        throw new IllegalStateException(ex);
    }
    return context;
}

运行时监听器

扩大性能 callRunners(context, applicationArguments)
能够在启动实现后执行自定义的内容;有2种实现形式

  • 实现 ApplicationRunner 接口
  • 实现 CommandLineRunner 接口

参考资料:
https://blog.csdn.net/weixin_…

https://blog.csdn.net/w200921…

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理