springboot如何在靜態類中獲取配置-配置獲取全解

  1. springboot如何獲取配置文件的配置?
  2. springboot如何在靜態類中獲取配置?

以下所有示例都通過驗證。

1.定義配置文件格式

這裏主要指常見的配置文件:properties, yaml.

當然,json也可以作爲配置,不過不是首選。

使用的配置文件:

application.properties

api.key=jimo
api.password=password

application.yml

api:
  username: admin

2.動態注入加載

2.1 @Value

@Component
public class ApiConfig {
    @Value("${api.key}")
    private String key;
    @Value("${api.username}")
    private String username;
    @Value("${api.password}")
    private String password;
}

2.2 @ConfigurationProperties(prefix = “api”)

@Component
@ConfigurationProperties(prefix = "api")
public class ApiConfig {
    private String key;
    private String username;
    private String password;
}

2.3 指定配置文件@PropertySource

@PropertySource是spring提供的一個註解,用於把特定配置加載到Environment環境變量裏,標準用法是和Configuration一起使用。

注意:@PropertySource(value = {"classpath:test.conf"})對於同一個文件,只需要在一個地方註冊,其他地方都可以使用了。

比如:在主類註冊

@PropertySource(value = {"classpath:test.conf"})
@SpringBootApplication
public class ConfigTestApplication {

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

在其他所有bean裏都可以使用:

@Component
public class Api {
    @Value("${test.a}")
    private String a;
    @Value("${test.b}")
    private String b;
}

另外:@Value@ConfigurationProperties 都是可以和@PropertySource組合使用的,只是注意配置的重複導致覆蓋問題(後加載的會覆蓋前面的).

@Data
@Component
@PropertySource(value = {"classpath:test.conf"})
public class Api4Config {
    @Value("${test.a}")
    private String a;
    @Value("${test.b}")
    private String b;
}

3.靜態加載

指在靜態類中讀取配置文件內容

3.1 直接讀取

3.1.1 Properties

我們可以使用最基礎的Properties工具類:這是java的方式

import java.io.IOException;
import java.util.Properties;
import org.springframework.core.io.ClassPathResource;

/**
 * 直接讀取配置文件
 *
 * @author jimo
 * @version 1.0.0
 */
public class RawConfigUtil {

    private static Properties properties = readProperties("test.conf", "test2.conf");

    private static Properties readProperties(String... confFile) {
        final Properties properties = new Properties();
        try {
            for (String path : confFile) {
                final ClassPathResource resource = new ClassPathResource(path);
                properties.load(resource.getInputStream());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return properties;
    }

    public static String getString(String key) {
        return properties.getProperty(key);
    }
}

3.1.2 typesafe.config

或者通過第三方工具:https://github.com/lightbend/config讀取

        <dependency>
            <groupId>com.typesafe</groupId>
            <artifactId>config</artifactId>
            <version>1.4.0</version>
        </dependency>

代碼:

import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;

/**
 * @author jimo
 * @version 1.0.0
 */
public class ConfigUtils {

    private static Config load;

    // 默認加載classpath下的application.*
    static {
        load = ConfigFactory.load();
    }

    /**
     * 讀取配置文件中指定Key的值
     *
     * @param key 配置文件中的key
     * @return 指定key的value
     */
    public static String getString(String key) {
        return load.getString(key);
    }

    /**
     * 讀取配置文件中指定Key的值
     *
     * @param key 配置文件中的key
     * @return 指定key的value
     */
    public static int getInt(String key) {
        return load.getInt(key);
    }

    /**
     * 讀取配置文件中指定Key的值
     *
     * @param key 配置文件中的key
     * @return 指定key的value
     */
    public static boolean getBoolean(String key) {
        return load.getBoolean(key);
    }

}

根據其介紹,默認可以加載這些配置文件:

system properties
application.conf (all resources on classpath with this name)
application.json (all resources on classpath with this name)
application.properties (all resources on classpath with this name)
reference.conf (all resources on classpath with this name)

比較特別的是可以讀取json配置,不過筆者用得不多。

3.1.3 小結

但是,這2種方式有以下缺點:

  1. 都不能讀取yaml格式的配置
  2. 不能利用springboot從外部和環境變量加載配置的功能,所以只能是死的配置,不夠靈活

3.2 使用Environment

要針對spring環境,還是用spring的工具。

Environment是在Spring中代表當前運行的環境,包括:profilesproperties,
它繼承了PropertyResolver接口所以才具有讀取配置的功能:

public interface Environment extends PropertyResolver {...}

所以,配置的實現其實是PropertyResolver接口的實現類做的。

如果我們能在靜態類裏持有這個環境,那麼就可以獲取變量了,恰好spring就提供了這樣的接口:EnvironmentAware.

public interface EnvironmentAware extends Aware {

	/**
	 * Set the {@code Environment} that this component runs in.
	 */
	void setEnvironment(Environment environment);
}

這個接口就一個方法:當環境準備好時,會調用這個接口的實現類,然後設置實例。

所以,我們實現這個接口得到Environment:

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

/**
 * @author jimo
 * @version 1.0.0
 */
@Slf4j
@Component
public class MyEnvBeanUtil implements EnvironmentAware {

    private static Environment env;

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

    public static String getString(String key) {
        return env.getProperty(key);
    }
}

我們實際調用時:

    @Test
    void testEnv() {
        assertEquals("password", MyEnvBeanUtil.getString("api.password"));
        assertEquals("admin", MyEnvBeanUtil.getString("api.username"));
    }

3.3 繼承PropertySourcesPlaceholderConfigurer

PropertySourcesPlaceholderConfigurer實現了EnvironmentAware,所以更加豐富,因爲可以設置佔位符這些信息,用於自定義佔位符使用這個,使用方法

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.env.ConfigurablePropertyResolver;
import org.springframework.core.env.PropertyResolver;
import org.springframework.stereotype.Component;

/**
 * @author jimo
 * @version 1.0.0
 */
@Component
public class PropertyUtil extends PropertySourcesPlaceholderConfigurer {

    private static PropertyResolver propertyResolver;

    @Override
    protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
                                     ConfigurablePropertyResolver propertyResolver) throws BeansException {
        super.processProperties(beanFactoryToProcess, propertyResolver);
        PropertyUtil.propertyResolver = propertyResolver;
    }

    public static String getString(String key) {
        return propertyResolver.getProperty(key);
    }
}

4.總結

本文對spring獲取配置做了一些總結,主要有以下方式獲取spring的配置:

  1. @Value
  2. @ConfigurationProperties
  3. @PropertySource指定配置文件
  4. Properties讀取
  5. typesafe.config讀取
  6. EnvironmentAware
  7. PropertySourcesPlaceholderConfigurer

後續會總結springboot的多環境配置。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章