springboot启动源码分析

文章详细阐述了SpringBoot应用程序的启动过程,从SpringApplication的创建到run方法的执行,包括环境变量的读取、ApplicationContext的创建、Bean的加载以及ApplicationRunner和CommandLineRunner的执行等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

springboot启动类

package com.ahs.ahsaccount;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class AhsAccountApplication {

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

}

run方法

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

实例方法

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		 将启动类放入primarySources
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		//根据classpath 下的类,推算当前web应用类型(REACTIVE, servlet)
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		//去spring.factories 中去获取所有key:org.springframework.context.ApplicationContextInitializer
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		//去spring.factories 中去获取所有key: org.springframework.context.ApplicationListener
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		//根据main方法推算出mainApplicationClass
		this.mainApplicationClass = deduceMainApplicationClass();
	}

获取启动类
获取web应用类型
读取了ApplicationContextInitializer ,ApplicationListener
根据main推算出所在的类

run方法

// SpringApplication.java

public ConfigurableApplicationContext run(String... args) {
    // 创建 StopWatch 对象,并启动。StopWatch 主要用于简单统计 run 启动过程的时长。
    StopWatch stopWatch = new StopWatch();
    //是记录了启动开始时间
    stopWatch.start();
    
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    // 配置 headless 属性
    configureHeadlessProperty();
    // 去spring.factroies中读取了SpringApplicationRunListener 的组件, 就是用来发布事件或者运行监听器
    SpringApplicationRunListeners listeners = getRunListeners(args);
    //发布1.ApplicationStartingEvent事件,在运行开始时发送
    listeners.starting();
    try {
        // 创建  ApplicationArguments 对象
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        //  加载属性配置。执行完成后,所有的 environment 的属性都会加载进来,包括 application.properties 和外部的属性配置。预初始化环境: 读取环境变量,读取配置文件信息(基于监听器)
        ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
        // 忽略beaninfo的bean
        configureIgnoreBeanInfo(environment);
        //   打印Banner 横幅
        Banner printedBanner = printBanner(environment);
        //  创建 Spring 容器。 根据webApplicationType创建Spring上下文
        context = createApplicationContext();
        //  异常报告器
        exceptionReporters = getSpringFactoriesInstances(
                SpringBootExceptionReporter.class,
                new Class[] { ConfigurableApplicationContext.class }, context);
        //  主要是调用所有初始化类的 initialize 方法,/预初始化spring上下文
        prepareContext(context, environment, listeners, applicationArguments,
                printedBanner);
        //  初始化 Spring 容器。ioc流程
        refreshContext(context);
        // 执行 Spring 容器的初始化的后置逻辑。默认实现为空。
        afterRefresh(context, applicationArguments);
        // 停止 StopWatch 统计时长
        stopWatch.stop();
        // 打印 Spring Boot 启动的时长日志。
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
        }
        //  通知 SpringApplicationRunListener 的数组,Spring 容器启动完成。
        listeners.started(context);
        // 调用 ApplicationRunner 或者 CommandLineRunner 的运行方法。
        callRunners(context, applicationArguments);
    } catch (Throwable ex) {
        // 如果发生异常,则进行处理,并抛出 IllegalStateException 异常
        handleRunFailure(context, ex, exceptionReporters, listeners);
        throw new IllegalStateException(ex);
    }

    //  通知 SpringApplicationRunListener 的数组,Spring 容器运行中。
    try {
        listeners.running(context);
    } catch (Throwable ex) {
        //  如果发生异常,则进行处理,并抛出 IllegalStateException 异常
        handleRunFailure(context, ex, exceptionReporters, null);
        throw new IllegalStateException(ex);
    }
    return context;
}

prepareEnvironment
// SpringApplication.java

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
	// Create and configure the environment
	//  创建 ConfigurableEnvironment 对象,并进行配置
	//根据webApplicationType 创建Environment 创建就会读取: java环境变量和系统环境变量
	ConfigurableEnvironment environment = getOrCreateEnvironment();
	configureEnvironment(environment, applicationArguments.getSourceArgs());
	// 通知 SpringApplicationRunListener 的数组,环境变量已经准备完成。
	//发布了ApplicationEnvironmentPreparedEvent 的监听器 读取了全局配置文件
	listeners.environmentPrepared(environment);
	//  绑定 environment 到 SpringApplication 上
	bindToSpringApplication(environment);
	//  如果非自定义 environment ,则根据条件转换
	if (!this.isCustomEnvironment) {
		environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
	}
	// 如果有 attach 到 environment 上的 MutablePropertySources ,则添加到 environment 的 PropertySource 中。
	ConfigurationPropertySources.attach(environment);
	return environment;
}
prepareContext
// SpringApplication.java

private void prepareContext(ConfigurableApplicationContext context,
        ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
        ApplicationArguments applicationArguments, Banner printedBanner) {
    // <1> 设置 context 的 environment 属性
    context.setEnvironment(environment);
    // <2> 设置 context 的一些属性
    postProcessApplicationContext(context);
    // <3> 初始化 ApplicationContextInitializer
    //拿到之前读取到所有ApplicationContextInitializer的组件, 循环调用initialize方法
    applyInitializers(context);
    // <4> 通知 SpringApplicationRunListener 的数组,Spring 容器准备完成。
    listeners.contextPrepared(context);
    // <5> 打印日志
    if (this.logStartupInfo) {
        logStartupInfo(context.getParent() == null);
        logStartupProfileInfo(context);
    }
    // Add boot specific singleton beans
    // <6> 设置 beanFactory 的属性
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
    if (printedBanner != null) {
        beanFactory.registerSingleton("springBootBanner", printedBanner);
    }
    if (beanFactory instanceof DefaultListableBeanFactory) {
        ((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }
    // Load the sources
    // <7> 加载 BeanDefinition 们
    Set<Object> sources = getAllSources();
    Assert.notEmpty(sources, "Sources must not be empty");
    load(context, sources.toArray(new Object[0]));
    // <8> 通知 SpringApplicationRunListener 的数组,Spring 容器加载完成。
    listeners.contextLoaded(context);
}
refreshContext
// SpringApplication.java


private void refreshContext(ConfigurableApplicationContext context) {
	// <1> 开启(刷新)Spring 容器
	refresh(context);
	// <2> 注册 ShutdownHook 钩子
	if (this.registerShutdownHook) {
		try {
			context.registerShutdownHook();
		} catch (AccessControlException ex) {
			// Not allowed in some environments.
		}
	}
}
callRunners

扩展点

// SpringApplication.java

private void callRunners(ApplicationContext context, ApplicationArguments args) {
    // <1> 获得所有 Runner 们
    List<Object> runners = new ArrayList<>();
    // <1.1> 获得所有 ApplicationRunner Bean 们
    runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
    // <1.2> 获得所有 CommandLineRunner Bean 们
    runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
    // <1.3> 排序 runners
    AnnotationAwareOrderComparator.sort(runners);
    // <2> 遍历 Runner 数组,执行逻辑
    for (Object runner : new LinkedHashSet<>(runners)) {
        if (runner instanceof ApplicationRunner) {
            callRunner((ApplicationRunner) runner, args);
        }
        if (runner instanceof CommandLineRunner) {
            callRunner((CommandLineRunner) runner, args);
        }
    }
}

总结

1、初始化SpringApplication 从spring.factories 读取 listener ApplicationContextInitializer 。
2.运行run方法
3.读取 环境变量 配置信息等
4. 创建springApplication上下文:ServletWebServerApplicationContext
5. . 预初始化上下文
6.调用refresh 加载ioc容器 加载所有的自动配置类
7、创建servlet容器
8.整个流程中会多次调用很多监听器对外进行

### AI智能客服与智能会话 #### 定义与概念 AI智能客服指的是利用人工智能技术实现客户服务自动化的一种解决方案。这类系统可以理解并回应用户的查询,提供帮助和服务支持。其核心在于模拟人类对话过程中的交互行为,使得机器能够以自然的方式同客户交流。 #### 工作原理 智能客服的工作机制依赖于多种先进技术的支持: - **自然语言处理(NLP)**:这是指让计算机理解和生成人类使用的文字或语音的能力。通过对输入的信息进行语义分析、意图识别以及上下文管理等操作,智能客服得以解析用户的需求并向用户提供恰当的回答[^3]。 - **机器学习算法**:为了提高响应质量,智能客服还会采用监督式学习方法训练模型,使其可以从大量历史案例中学习最佳实践;同时也会运用强化学习不断优化自身的策略,在实际应用场景里做出更加合理的判断和建议[^1]。 - **知识库集成**:除了依靠内置逻辑外,很多先进的智能客服还连接着庞大的后台数据库作为支撑。当遇到复杂问题时,它们可以通过检索这些结构化信息源获取准确答案,并将其转化为易于被顾客接受的形式呈现出来。 #### 主要应用领域 随着技术进步,越来越多的企业开始部署AI驱动的聊天机器人来改善用户体验、降低运营成本并增强竞争力。以下是几个典型的应用场景: - **电子商务平台**:在线商店常常面临海量咨询请求的压力,而借助智能客服工具则可以在第一时间解答常见疑问,引导访客顺利完成购买流程; - **金融服务行业**:银行及其他金融机构也积极引入此类服务,用于账户查询、转账汇款指导等方面工作,既提高了效率又保障了安全性; - **电信运营商**:电话服务中心往往需要应对数以万计的日均来电量,此时拥有强大应变能力的人工智能助理无疑成为缓解人工坐席压力的有效手段之一。 ```python # 示例代码展示了一个简单的基于规则匹配的智能回复函数 def simple_chatbot_response(user_input): responses = { "你好": "您好!请问有什么可以帮助您的吗?", "再见": "感谢光临,祝您生活愉快!" } return responses.get(user_input.strip(), "抱歉,我不太明白您的意思") print(simple_chatbot_response("你好")) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值