SpringBoot(4) - SpringApplication(4) - 自定义Environment或ApplicationContext

参考:https://docs.spring.io/spring-boot/docs/1.5.17.RELEASE/reference/htmlsingle/#howto-customize-the-environment-or-application-context

 

官方文档:

SpringApplication的ApplicationListeners和ApplicationContextInitializers可被用于将自定义应用于上下文或环境。 Spring Boot为了在内部使用,从META-INF/spring.factories加载了许多此类自定义项。 有许多种注册其他自定义的方式:

  • 编程方式添加,通过在程序运行之前调用SpringApplication上的addListeners和addInitializers方法。
  • 声明方式添加,通过设置context.initializer.classes或context.listener.classes声明。
  • 打包成jar方式添加(所有应用),通过添加META-INF/spring.factories并打包成jar。

SpringApplication将一些特殊的ApplicationEvent发送给监听器(也包括在创建上下文之前的一些事件),然后为ApplicationContext发布的事件注册监听器。

在使用EnvironmentPostProcessor刷新应用程序上下文之前,还可以自定义环境。 每个实现都应该在META-INF/spring.factories中注册:

org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostProcessor

该实现可以加载任意文件并将它们添加到环境中。 例如,此示例从类路径加载YAML配置文件:

public class EnvironmentPostProcessorExample implements EnvironmentPostProcessor {
    private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader();

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        Resource path = new ClassPathResource("com/example/myapp/config.yml");
        PropertySource<?> propertySource = loadYaml(path);
        environment.getPropertySources().addLast(propertySource);
    }

    private PropertySource<?> loadYaml(Resource path) {
        if (!path.exists()) {
            throw new IllegalArgumentException("Resource " + path + " does not exist");
        }
        try {
            return this.loader.load("custom-resource", path, null);
        } catch (IOException ex) {
            throw new IllegalStateException("Failed to load yaml configuration from " + path, ex);
        }
    }
}

 注:

  • Environment已经准备好了Spring Boot默认加载的所有常用属性源。 因此,可以从环境中获取文件的位置。 此示例在属性源列表末尾添加custom-resource属性源。 可以自定义属性源的次序,如头部、某个属性源前/后、末尾等。
  • 虽然在@SpringBootApplication上使用@PropertySource似乎方便又容易在环境中加载自定义资源,但Spring官方不推荐使用它,因为Spring Boot会在刷新ApplicationContext之前准备环境。 通过@PropertySource定义的任何key都加载的太晚以致于无法对自动配置产生任何影响。

 

自定义添加属性源示例:

通过spring.factories文件注册,这种方式可以打包成jar文件作为公共组件来使用。

1. 自定义配置文件config.yml

放在classpath目录下,用于在ApplicationContext刷新前添加

yaml: 
  server:
   port: 8081

2. 编译时添加config.yml至classpath

pom.xml使用<resource>标签:

<build>
    <resources>
        <resource>
            <filtering>false</filtering>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.yml</include>
            </includes>
        </resource>
    </resources>
</build>

3. 自定义EnvironmentPostProcessor

添加classpath下的confi.yml为属性源:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import java.io.IOException;

public class YamlEnvironmentPostProcessor implements EnvironmentPostProcessor {
    private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader();

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        Resource path = new ClassPathResource("com/momo/springbootenvironment/config/config.yml");
        PropertySource<?> propertySource = loadYaml(path);
        // 属性源末尾添加
        environment.getPropertySources().addLast(propertySource);
    }

    private PropertySource<?> loadYaml(Resource path) {
        if (!path.exists()) {
            throw new IllegalArgumentException("Resource " + path + " does not exist");
        }
        try {
            return this.loader.load("customConfig:[classpath:/com/momo/springbootenvironment/config/config.yml]", path, null);
        } catch (IOException ex) {
            throw new IllegalStateException("Failed to load yaml configuration from " + path, ex);
        }
    }
}

4. 注册自定义EnvironmentPostProcessor

在src/main/resources/META-INF添加spring.factories,并注册:

org.springframework.boot.env.EnvironmentPostProcessor=\
com.momo.springbootenvironment.config.YamlEnvironmentPostProcessor

5. 测试

public static void main(String[] args) {
    ConfigurableApplicationContext ac = SpringApplication.run(Application.class, args);
    ConfigurableEnvironment environment = ac.getEnvironment();
    System.out.println("server.port:" + environment.getProperty("server.port"));
    System.out.println("yaml.server.port:" + environment.getProperty("yaml.server.port"));
}

 

demo代码:https://github.com/mytt-10566/springboot-environment

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值