SpringbootRun方法运行原理

SpringbootRun方法运行原理

一.Spring Boot的运行原理主要涉及以下几个核心方面:

1.启动流程

​ Spring Boot应用的启动通常通过SpringApplication.run()方法开始:

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

2.SpringApplication初始化

创建SpringApplication实例:分析主配置类上的注解(如@SpringBootApplication)
推断应用类型:判断是Web应用(Servlet或Reactive)还是普通应用
加载ApplicationContextInitializer:从spring.factories加载上下文初始化器
加载ApplicationListener:从spring.factories加载事件监听器
推断主配置类:确定包含main方法的启动类

3.run方法执行过程

SpringApplication.run()方法的主要执行步骤:
启动计时器:记录应用启动时间
准备Environment:创建并配置环境变量
打印Banner:显示Spring Boot的ASCII艺术字标识
创建ApplicationContext:根据应用类型创建相应的应用上下文
准备上下文:设置环境、初始化器等
刷新上下文:
注册Bean定义
初始化所有单例Bean
启动内嵌Web服务器(如果是Web应用)
启动完成:发布应用启动完成事件

4.自动配置机制

@EnableAutoConfiguration:启用自动配置功能
条件注解:通过@Conditional系列注解控制Bean的创建条件
spring.factories:定义自动配置类的配置文件
Starter机制:提供开箱即用的依赖集合

5.核心特性

约定优于配置:减少开发者需要编写的配置
内嵌服务器:支持Tomcat、Jetty、Undertow等
外部化配置:支持多种配置方式(properties、yaml、环境变量等)
健康检查和监控:通过Actuator提供应用监控功能
pring Boot通过这些机制大大简化了Spring应用的开发和部署过程。

二.下面我将结合Spring Boot源码详细解释SpringApplication.run()方法的执行原理:

1.SpringApplication.run()入口方法

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

public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
    return new SpringApplication(primarySources).run(args);
}

这里创建了SpringApplication实例并调用其run()方法。

2.SpringApplication构造函数

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

@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));
    // 推断应用类型(NONE, SERVLET, REACTIVE)
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    // 从spring.factories加载ApplicationContextInitializer
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    // 从spring.factories加载ApplicationListener
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    // 推断主配置类
    this.mainApplicationClass = deduceMainApplicationClass();
}

3.run()方法核心实现

// SpringApplication.java
public ConfigurableApplicationContext run(String... args) {
    // 启动计时器
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    
    DefaultBootstrapContext bootstrapContext = createBootstrapContext();
    ConfigurableApplicationContext context = null;
    configureHeadlessProperty();
    
    // 获取SpringApplicationRunListeners,用于发布事件
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting(bootstrapContext, this.mainApplicationClass);
    
    try {
        // 处理命令行参数
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        
        // 准备Environment
        ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
        
        // 打印Banner
        Banner printedBanner = printBanner(environment);
        
        // 创建ApplicationContext
        context = createApplicationContext();
        
        // 设置bootstrap上下文
        context.setApplicationStartup(this.applicationStartup);
        
        // 准备ApplicationContext
        prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
        
        // 刷新ApplicationContext(核心步骤)
        refreshContext(context);
        
        // 刷新后的处理
        afterRefresh(context, applicationArguments);
        
        stopWatch.stop();
        
        // 发布应用启动完成事件
        listeners.started(context);
        
        // 调用Runner接口
        callRunners(context, applicationArguments);
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, listeners);
        throw new IllegalStateException(ex);
    }
    
    try {
        // 发布运行中事件
        listeners.running(context);
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, null);
        throw new IllegalStateException(ex);
    }
    
    return context;
}

4.prepareEnvironment方法

// SpringApplication.java
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
        DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
    // 获取或创建Environment
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    
    // 配置Environment属性源
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    
    // 应用Environment后处理器
    ConfigurationPropertySources.attach(environment);
    
    // 发布环境准备事件
    listeners.environmentPrepared(bootstrapContext, environment);
    
    // 将环境绑定到SpringApplication
    bindToSpringApplication(environment);
    
    // 如果是非Web环境且有自定义Environment,则转换为标准Environment
    if (!this.isCustomEnvironment) {
        environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
                deduceEnvironmentClass());
    }
    
    ConfigurationPropertySources.attach(environment);
    return environment;
}

5.createApplicationContext方法

// SpringApplication.java
protected ConfigurableApplicationContext createApplicationContext() {
    return this.applicationContextFactory.create(this.webApplicationType);
}

// ApplicationContextFactory.java
@Override
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
    try {
        return switch (webApplicationType) {
            case SERVLET -> new AnnotationConfigServletWebServerApplicationContext();
            case REACTIVE -> new AnnotationConfigReactiveWebServerApplicationContext();
            default -> new AnnotationConfigApplicationContext();
        };
    }
    catch (Exception ex) {
        throw new IllegalStateException("Unable to create configured ApplicationContext", ex);
    }
}

6.prepareContext方法

// SpringApplication.java
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
        ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
        ApplicationArguments applicationArguments, Banner printedBanner) {
    // 设置Environment
    context.setEnvironment(environment);
    
    // 后置处理ApplicationContext
    postProcessApplicationContext(context);
    
    // 应用ApplicationContextInitializer
    applyInitializers(context);
    
    // 发布上下文准备事件
    listeners.contextPrepared(context);
    
    bootstrapContext.close(context);
    
    // 记录启动日志
    if (this.logStartupInfo) {
        logStartupInfo(context.getParent() == null);
        logStartupProfileInfo(context);
    }
    
    // 添加启动相关的单例Bean
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
    if (printedBanner != null) {
        beanFactory.registerSingleton("springBootBanner", printedBanner);
    }
    if (beanFactory instanceof DefaultListableBeanFactory) {
        ((DefaultListableBeanFactory) beanFactory)
                .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }
    if (this.lazyInitialization) {
        context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
    }
    
    // 加载主配置类作为Bean定义
    Set<Object> sources = getAllSources();
    Assert.notEmpty(sources, "Sources must not be empty");
    load(context, sources.toArray(new Object[0]));
    
    // 发布上下文加载完成事件
    listeners.contextLoaded(context);
}

7.refreshContext方法

// SpringApplication.java
private void refreshContext(ConfigurableApplicationContext context) {
    if (this.registerShutdownHook) {
        shutdownHook.registerApplicationContext(context);
    }
    refresh(context);
}

protected void refresh(ConfigurableApplicationContext context) {
    // 调用ApplicationContext的refresh方法
    context.refresh();
}

context.refresh()是Spring框架的核心方法,它会完成Bean工厂的创建Bean定义的加载Bean实例的创建等核心工作。

8.callRunners方法

// SpringApplication.java
private void callRunners(ApplicationContext context, ApplicationArguments args) throws Exception {
    List<Object> runners = new ArrayList<>();
    // 获取ApplicationRunner类型的Bean
    runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
    // 获取CommandLineRunner类型的Bean
    runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
    AnnotationAwareOrderComparator.sort(runners);
    
    // 依次执行Runner
    for (Object runner : new LinkedHashSet<>(runners)) {
        if (runner instanceof ApplicationRunner) {
            callRunner((ApplicationRunner) runner, args);
        }
        if (runner instanceof CommandLineRunner) {
            callRunner((CommandLineRunner) runner, args);
        }
    }
}

通过以上源码分析可以看出,SpringApplication.run()方法是一个复杂的过程,它整合了Spring框架的核心功能,并在此基础上提供了自动配置、外部化配置、内嵌服务器等Spring Boot特有的功能。

posted @ 2025-08-21 23:55  mz456  阅读(12)  评论(0)    收藏  举报