SpringBoot自定义Environment属性及属性绑定

有时候我们需要在spring bean的生命周期开始前,初始化一些环境变量到Environment中,在bean生命周期的过程中,可以动态的注入这些环境变量。下面就介绍3种方式,配置环境变量。

自定义Environment属性有常用的3种方式,属性绑定有手动绑定和注解自动绑定2种方式。

源码

获取源码

方式一:实现FactoryBean

我们常见的一些框架本身是可以单独运行的,而不是依赖于Spring。同时,有框架为了使用Spring的IOC,通常都提供了一个与Spring整合的jar包,例如:mybatis-spring,我们在xml中会配置一个SqlSessionFactoryBean,它是实现了FactoryBean的,SqlSessionFactoryBean类中完成了一些必要对象的初始化,通过FactoryBean#getObject方法,将SqlSessionFactory交给了Spring管理。通过这个例子,我可以告诉你,FactoryBean是很多框架整合到Spring IOC的桥梁。那我们也可以通过FactoryBean初始化环境变量。

步骤1:实现FactoryBean、EnvironmentAware

super.getDefaultProperties()方法是DefaultPropertiesConfig中的,本博客讲述了3种实现方式,就把要配置的环境变量抽出来了。

public class InjectEnvironmentFactoryBean extends DefaultPropertiesConfig implements FactoryBean<Properties>, EnvironmentAware {

    private Environment environment;
    @Override
    public Properties getObject() throws Exception {
        Properties p = new Properties();
        Map<String, Object> defaultProperties = super.getDefaultProperties();
        if (defaultProperties != null) {
            MapPropertySource propertySource = new MapPropertySource(DefaultPropertiesConfig.ASSOCIATED_NAME, defaultProperties);
            ((ConfigurableEnvironment) environment).getPropertySources().addFirst(propertySource);
            p.putAll(defaultProperties);
        }
        return p;
    }

    @Override
    public Class<?> getObjectType() {
        return Properties.class;
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
}

步骤2:context:property-placeholder配置

在xml中注入InjectEnvironmentFactoryBean,同时被context:property-placeholder引用,这样才可以在Spring bean生命周期开始前将环境变量设置在Environment中。

<?xml version="1.0" encoding="utf-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd 
       http://www.springframework.org/schema/context 
       https://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="environmentInject" class="com.example.environment.inject.env.InjectEnvironmentFactoryBean"/>
    <!-- ContextNamespaceHandler -->
    <context:property-placeholder properties-ref="environmentInject"/>
</beans>

公共的属性类

public class DefaultPropertiesConfig {
	// 环境配置的关联key
    public static final String ASSOCIATED_NAME = "configTestName";
    // 环境变量的公共前缀
    public static final String PREFIX = "config.test";
    // name
    public static final String ARG1 = "name";
    // age
    public static final String ARG2 = "age";
    // address
    public static final String ARG3 = "address";

    public Map<String, Object> getDefaultProperties() {
        Map<String, Object> environmentInject = new HashMap<>();
        environmentInject.put(PREFIX + "." + ARG1, "大桥");
        environmentInject.put(PREFIX + "." + ARG2, "18");
        environmentInject.put(PREFIX + "." + ARG3, "ka");
        return environmentInject;
    }
}

测试

手动绑定环境变量

配置类
public class ConfigTest {
    private String name;
    private String age;
    private String address;
}
测试方法

注意:DefaultPropertiesConfig中配置的key,带有config.test前缀, 使用Binder.get(environment).bind(“config.test”, ConfigTest.class)可以自动的匹配配置类。

// 使 PropertiesFactoryBean 生效
@ImportResource("classpath:access-config.xml")
public class EnvironmentInjectDemo {

    public static void main(String[] args) {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        // 注册 Configuration Class
        context.register(EnvironmentInjectDemo.class);
        // 启动 Spring 应用上下文
        context.refresh();

        ConfigurableEnvironment environment = context.getEnvironment();
        try {
            // 测试 IOC 容器没有 ConfigTest Bean,因为没有扫描这个包,也没有添加注解
            ConfigTest configTest = context.getBean(ConfigTest.class);
        } catch (Exception e) {
            System.err.println("测试 IOC 容器没有 ConfigTest Bean: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.access.boot.sample.ConfigTest' available");
        }

        // 手动绑定 PropertiesFactoryBean 注入的环境变量
        // 绑定环境变量前缀为 config.test 的属性到 ConfigTest 中
        BindResult<ConfigTest> bind = Binder.get(environment).bind("config.test", ConfigTest.class);
        if (bind.isBound()) {
            ConfigTest configTest = bind.get();
            System.out.println(configTest);
        }

        // 关闭 Spring 应用上下文
        context.close();
    }
}

注解自动绑定环境变量

自动配置类
@Configuration
@ConfigurationProperties(prefix = "config.test")
public class AutoConfigTest {
    private String name;
    private String age;
    private String address;
}
测试方法

注意:AutoConfigTest配置类中使用了ConfigurationProperties注解,指定了prefix=“config.test”,通过注解的形式,可以自动绑定环境变量到AutoConfigTest配置类中。

@SpringBootApplication
@ImportResource("classpath:access-config.xml")
public class EnvironmentAutoInjectDemo {
    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(EnvironmentAutoInjectDemo.class, args);
        // AutoConfigTest 自动配置的类,自动将手动注入到 Environment 中的环境变量注入到配置类
        AutoConfigTest bean = run.getBean(AutoConfigTest.class);
        System.out.println(bean);
        run.close();
    }
}

方式二:实现EnvironmentPostProcessor

步骤1:实现EnvironmentPostProcessor

/**
 * 通过 spring.factories 配置
 * org.springframework.boot.env.EnvironmentPostProcessor=\
 * com.example.environment.inject.env.InjectEnvironmentPostProcessor
 * 使用 @Configuration 等其他方式配置不生效
 */
public class InjectEnvironmentPostProcessor extends DefaultPropertiesConfig implements EnvironmentPostProcessor {
    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        Map<String, Object> defaultProperties = super.getDefaultProperties();
        MapPropertySource propertySource = new MapPropertySource(ASSOCIATED_NAME, defaultProperties);
        environment.getPropertySources().addFirst(propertySource);
    }
}

步骤2:spring.factories配置

在resources/META-INF文件夹下新建spring.factories文件,内容如下:

org.springframework.boot.env.EnvironmentPostProcessor=\
  com.example.environment.inject.env.InjectEnvironmentPostProcessor

测试

注意:测试时,需要将方式一中的xml配置注释掉,测试方法见方式一中的测试方法。

方式三:实现ApplicationContextInitializer

步骤1:实现ApplicationContextInitializer

/**
 * 通过 spring.factories 配置
 * org.springframework.context.ApplicationContextInitializer=\
 * com.example.environment.inject.env.InjectEnvironmentApplicationContextInitializer
 */
public class InjectEnvironmentApplicationContextInitializer extends DefaultPropertiesConfig implements
        ApplicationContextInitializer<ConfigurableApplicationContext> {

    @Override
    public void initialize(ConfigurableApplicationContext context) {
        ConfigurableEnvironment environment = context.getEnvironment();
        Map<String, Object> defaultProperties = super.getDefaultProperties();
        MapPropertySource propertySource = new MapPropertySource(ASSOCIATED_NAME, defaultProperties);
        environment.getPropertySources().addFirst(propertySource);
    }
}

步骤2:spring.factories配置

在resources/META-INF文件夹下新建spring.factories文件,内容如下:

org.springframework.context.ApplicationContextInitializer=\
   com.example.environment.inject.env.InjectEnvironmentApplicationContextInitializer

测试

注意:测试时,需要将方式一、方式二中的配置注释掉,测试方法见方式一中的测试方法。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Boot 中,可以通过在 `application.yaml` 或 `application.properties` 文件中定义属性来获取属性值。以下是几种获取属性值的方法: 1. 使用 `@Value` 注解:可以通过 `@Value("${property.key}")` 注解来注入属性值,其中 `property.key` 是在配置文件中定义的属性键。 ```java import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class MyComponent { @Value("${my.property}") private String myProperty; // getter and setter } ``` 2. 使用 `@ConfigurationProperties` 注解:可以通过 `@ConfigurationProperties(prefix = "prefix")` 注解将属性绑定到一个类上,其中 `prefix` 是在配置文件中定义的属性前缀。 ```java import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "my") public class MyProperties { private String property; // getter and setter } ``` 3. 使用 `Environment` 对象:可以通过注入 `Environment` 对象来获取属性值。 ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; @Component public class MyComponent { @Autowired private Environment env; public void someMethod() { String property = env.getProperty("my.property"); // 使用属性值... } } ``` 这些方法都可以用来获取在配置文件中定义的属性值。注意,如果使用 `@Value` 或 `@ConfigurationProperties` 注解,需要确保在配置文件中正确配置了对应的属性键和属性值。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值