马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
- public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
- this.sources = new LinkedHashSet();
- this.bannerMode = Mode.CONSOLE;
- this.logStartupInfo = true;
- this.addCommandLineProperties = true;
- this.addConversionService = true;
- this.headless = true;
- this.registerShutdownHook = true;
- this.additionalProfiles = Collections.emptySet();
- this.isCustomEnvironment = false;
- this.lazyInitialization = false;
- this.applicationContextFactory = ApplicationContextFactory.DEFAULT;
- this.applicationStartup = ApplicationStartup.DEFAULT;
- this.resourceLoader = resourceLoader;
- Assert.notNull(primarySources, "PrimarySources must not be null");
- this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
- //1.推测web应用类型(NONE REACTIVE SERVLET)
- this.webApplicationType = WebApplicationType.deduceFromClasspath();
- //2.从spring.factories中获取BootstrapRegistryInitializer对象
- this.bootstrapRegistryInitializers =
- this.getBootstrapRegistryInitializersFromSpringFactories();
-
- //3.从spring.factories中获取ApplicationContextInitializer对象
- this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
- //4.从spring.factories中获取ApplicationListener对象
- this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
- //5.推测出Main类 (main()方法所在的类)
- this.mainApplicationClass = this.deduceMainApplicationClass();
- }
复制代码- public ConfigurableApplicationContext run(String... args) {
- StopWatch stopWatch = new StopWatch();
- stopWatch.start();
- DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
- ConfigurableApplicationContext context = null;
- this.configureHeadlessProperty();
- /**从spring.factories中获取SpringApplicationRunListeners 对象
- * 默认会拿到一个EventPublishingRunListener ,他会启动过程的各个阶段发布对应的事件
- **/
- SpringApplicationRunListeners listeners = this.getRunListeners(args);
- listeners.starting(bootstrapContext, this.mainApplicationClass);
- try {
- //将run()的参数封装为DefaultApplicationArguments对象
- ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
- //配置文件的入口
- ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
- this.configureIgnoreBeanInfo(environment);
- Banner printedBanner = this.printBanner(environment);
- //根据应用类型创建Spring容器
- context = this.createApplicationContext();
- context.setApplicationStartup(this.applicationStartup);
- this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
- //刷新Spring容器, 会解析配置类 扫描 启动Webserver
- this.refreshContext(context);
- this.afterRefresh(context, applicationArguments);
- stopWatch.stop();
- if (this.logStartupInfo) {
- (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
- }
- listeners.started(context);
- //调用applicationArguments 和CommandLineRunner
- this.callRunners(context, applicationArguments);
- } catch (Throwable var10) {
- this.handleRunFailure(context, var10, listeners);
- throw new IllegalStateException(var10);
- }
- try {
- listeners.running(context);
- return context;
- } catch (Throwable var9) {
- this.handleRunFailure(context, var9, (SpringApplicationRunListeners)null);
- throw new IllegalStateException(var9);
- }
- }
复制代码 Spring Boot 加载设置文件的机制是其核心功能之一,它通过一系列源码实现从差别泉源加载设置,并支持机动的设置管理。以下是 Spring Boot 加载设置文件的源码分析及着实现原理的具体阐明。(上述两段是加载设置文件的源码片断)
1. Spring Boot 加载设置文件的团体流程
Spring Boot 加载设置文件的流程可以分为以下几个步调:
- 初始化 Environment:在应用启动时,创建并初始化 Environment 对象。
- 加载默认设置文件:从 application.properties 或 application.yml 加载设置。
- 加载 Profile 特定的设置文件:根据激活的 Profile 加载 application-{profile}.properties 或 application-{profile}.yml。
- 加载外部化设置:从下令行参数、情况变量、JNDI 等外部泉源加载设置。
- 归并设置:将全部设置泉源归并到 Environment 中,供应用步伐利用。
2. 源码分析
以下是 Spring Boot 加载设置文件的核心源码分析。
2.1 SpringApplication.run()
Spring Boot 应用的启动入口是 SpringApplication.run() 方法。在这个方法中,会初始化 Environment 并加载设置文件。
源码位置:org.springframework.boot.SpringApplication
- public ConfigurableApplicationContext run(String... args) {
- // ...
- ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
- // ...
- }
复制代码 阐明:
- prepareEnvironment() 方法负责创建和设置 Environment 对象。
2.2 prepareEnvironment()
prepareEnvironment() 方法会调用 configureEnvironment() 来加载设置文件。
源码位置:org.springframework.boot.SpringApplication
- private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
- // 创建 Environment 对象
- ConfigurableEnvironment environment = getOrCreateEnvironment();
- // 配置 Environment,加载配置文件
- configureEnvironment(environment, applicationArguments.getSourceArgs());
- // 触发环境准备事件
- listeners.environmentPrepared(environment);
- // 将 Environment 绑定到 SpringApplication
- bindToSpringApplication(environment);
- return environment;
- }
复制代码 阐明:
- getOrCreateEnvironment():根据应用范例(Web 或非 Web)创建 StandardEnvironment 或 StandardServletEnvironment。
- configureEnvironment():加载设置文件和其他外部化设置。
2.3 configureEnvironment()
configureEnvironment() 方法会调用 configurePropertySources() 和 configureProfiles() 来加载设置文件和激活 Profile。
源码位置:org.springframework.boot.SpringApplication
- protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
- configurePropertySources(environment, args);
- configureProfiles(environment, args);
- }
复制代码 阐明:
- configurePropertySources():加载下令行参数、默认设置文件等。
- configureProfiles():设置激活的 Profile。
2.4 ConfigFileApplicationListener
ConfigFileApplicationListener 是 Spring Boot 加载设置文件的核心类。它监听 ApplicationEnvironmentPreparedEvent 变乱,并加载 application.properties 或 application.yml 文件。
源码位置:org.springframework.boot.context.config.ConfigFileApplicationListener
- public void onApplicationEvent(ApplicationEvent event) {
- if (event instanceof ApplicationEnvironmentPreparedEvent) {
- onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
- }
- }
复制代码 阐明:
- onApplicationEnvironmentPreparedEvent():在情况准备完成后触发,加载设置文件。
2.5 Loader.load()
Loader 是 ConfigFileApplicationListener 的内部类,负责现实加载设置文件。
源码位置:org.springframework.boot.context.config.ConfigFileApplicationListener.Loader
- void load() {
- for (String location : getSearchLocations()) {
- for (String name : getSearchNames()) {
- load(location, name);
- }
- }
- }
复制代码 阐明:
- getSearchLocations():获取设置文件的搜索路径(如 classpath:/、file:./config/ 等)。
- getSearchNames():获取设置文件的名称(如 application)。
- load(location, name):从指定路径加载设置文件。
2.6 PropertySourcesLoader
PropertySourcesLoader 负责将设置文件内容加载到 PropertySource 中。
源码位置:org.springframework.boot.env.PropertySourcesLoader
- public PropertySource<?> load(Resource resource) throws IOException {
- if (resource.getFilename().endsWith(".yml")) {
- return loadYaml(resource);
- } else {
- return loadProperties(resource);
- }
- }
复制代码 阐明:
- loadYaml():加载 YAML 格式的设置文件。
- loadProperties():加载 Properties 格式的设置文件。
2.7 Profile 的加载
Spring Boot 支持通过 Profile 加载差别的设置文件。Profiles 和 ProfilePropertySource 负责处理处罚 Profile 相干的设置。
源码位置:org.springframework.core.env.Profiles
- public static Profiles of(String... profiles) {
- return new Profiles() {
- @Override
- public boolean matches(Predicate<String> predicate) {
- // ...
- }
- };
- }
复制代码 阐明:
- Profiles:管理 Profile 的激活状态。
- ProfilePropertySource:根据激活的 Profile 加载特定的设置文件。
3. Spring Boot 加载设置文件的实现原理
Spring Boot 加载设置文件的实现原理可以总结为以下几点:
- 多泉源加载:
- 支持从类路径、外部目次、情况变量、下令行参数等多种泉源加载设置。
- 优先级机制:
- 后加载的设置会覆盖先加载的设置,下令行参数的优先级最高。
- Profile 支持:
- 通过 spring.profiles.active 指定激活的 Profile,加载对应的设置文件。
- 外部化设置:
- 支持从外部文件、情况变量、JNDI 等加载设置,实用于云原生和容器化摆设。
4. 示例:Spring Boot 加载设置文件的流程
以下是一个完备的示例,展示 Spring Boot 怎样加载设置文件。
4.1 默认设置文件
application.properties:
- server.port=8080
- spring.profiles.active=dev
复制代码 4.2 Profile 特定的设置文件
application-dev.properties:
4.3 Java 代码
- @RestController
- public class MyController {
-
- @Value("${server.port}")
- private String port;
-
- @GetMapping("/port")
- public String getPort() {
- return "Server port: " + port;
- }
- }
复制代码 4.4 运行效果
- 如果激活的 Profile 是 dev,则 server.port 的值为 8081。
- 如果没有激活 Profile,则 server.port 的值为 8080。
5. 总结
Spring Boot 加载设置文件的机制非常机动,支持多泉源、多格式的设置加载。通过 Environment、PropertySource、ConfigFileApplicationListener 等核心类和组件,Spring Boot 实现了设置文件的加载、归并和优先级管理。明白这些源码和机制,可以资助我们更好地利用和扩展 Spring Boot 的设置功能。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
|