简单灵活的spring配置工具类ConfigFactory

这是我自己基于Environment对象封装的一个配置工程工具类,旨在解决配置在java代码层面的灵活性使用问题!
在这里插入图片描述

1. ConfigFactory类基本功能介绍

  • String getString(String key)
    根据配置键获取对应String值。

  • Integer getInteger(String key)
    根据配置键获取对应Integer类型值。

  • Long getLong(String key)
    根据配置键获取对应Long类型值。

  • Boolean getBoolean(String key)
    根据配置键获取对应Boolean类型值。

  • T extract(String prefix, Class type)
    根据前缀和类类型,提取以配置前缀为目前的配置封装成type对象类型。

  • BindResult bind(String prefix, Class type)
    根据前缀和类类型,提取将指定配置前缀开头的配置参数,封装到type对象类型中。

  • BindResult bind(String prefix, T target)
    根据前缀和目标对象,提取将指定配置前缀开头的配置参数,封装到taget目标对象中。

  • BindResult bind(String prefix, Bindable target)
    根据前缀和可绑定结构,提取将指定配置前缀开头的配置参数,封装到taget目标可绑定结构中。

2. ConfigFactory源码

import org.springframework.boot.context.properties.bind.BindResult;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.core.env.Environment;

import org.springframework.util.Assert;

/**  
 * <pre>Spring配置工厂,解决在无法注入的代码块中,获取指定键对应的配置</pre>
 * @author lilinhai
 * @since 2019-11-16 20:08
 * @version V1.0  
 */
public class ConfigFactory
{
    
    private static Environment environment;
    
    private static Binder binder;
    
    /**
     * <p>Set Method   :   environment Environment</p>
     * @param environment
     */
    public static void setEnvironment(Environment environment)
    {
        Assert.notNull(environment, "environment can't be null.");
        ConfigFactory.environment = environment;
        binder = Binder.get(environment);
    }

    public static String getString(String key)
    {
        check(key);
        return environment.getProperty(key, String.class);
    }

    public static Integer getInteger(String key)
    {
        check(key);
        return environment.getProperty(key, Integer.class);
    }
    
    public static Long getLong(String key)
    {
        check(key);
        return environment.getProperty(key, Long.class);
    }
    
    public static Boolean getBoolean(String key)
    {
        check(key);
        return environment.getProperty(key, Boolean.class, false);
    }
    
    /**
     * 根据prefix从配置中提取对象
     * @author sinhy
     * @since 2021-12-11 23:00 
     * @param <T>
     * @param prefix
     * @param type
     * @return T
     */
    public static <T> T extract(String prefix, Class<T> type)
    {
        BindResult<T> br = bind(prefix, type);
        return br.isBound() ? br.get() : null;
    }
    
    /**
     * 根据prefix从配置中提取对象
     * @author sinhy
     * @since 2021-12-11 23:00 
     * @param <T>
     * @param prefix
     * @param type
     * @return T
     */
    public static <T> BindResult<T> bind(String prefix, Class<T> type)
    {
        check(prefix);
        return binder.bind(prefix, type);
    }
    
    /**
     * 绑定
     * @author sinhy
     * @since 2022-06-15 22:20 
     * @param <T>
     * @param prefix
     * @param target
     * @return BindResult<T>
     */
    public static <T> BindResult<T> bind(String prefix, Bindable<T> target)
    {
        check(prefix);
        return binder.bind(prefix, target);
    }
    
    /**
     * 绑定
     * @author sinhy
     * @since 2022-06-15 22:20 
     * @param <T>
     * @param prefix
     * @param target
     * @return BindResult<T>
     */
    public static <T> BindResult<T> bind(String prefix, T target)
    {
        return bind(prefix, Bindable.ofInstance(target));
    }
    
    /**
     * <p>Get Method   :   environment Environment</p>
     * @return environment
     */
    public static Environment getEnvironment()
    {
        return environment;
    }

    private static void check(String key)
    {
        Assert.notNull(environment, "'environment' must not be null.");
        Assert.notNull(key, "'key' must not be null.");
    }
}

3. ConfigFactory对象初始化

ConfigFactory对象需要初始化后才能正常使用,直接在应用启动更早的地方调用setEnvironment即可完成初始化,如下代码案例中是在EnvironmentPostProcessor的自定义实现中完成ConfigFactory的初始化, EnvironmentPostProcessor是springboot应用启动时较先加载的一个配置组件。通过它去初始化ConfigFactory,可以让ConfigFactory最早得到初始化,以至于在各个地方调用不会出错!

/**
 * 自定义EnvironmentPostProcessor
 */
public class ApplicationEnvironmentPostProcessor implements EnvironmentPostProcessor
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application)
    {
        ConfigFactory.setEnvironment(environment);
        
    }
}

4. extract(String prefix, Class type)使用

在开发中经常遇到,或是非常很重要一个功能,比如在spring容器还未启动完成时,需要实例化某些配置,以进行必要的初始化设置。
今天给大家介绍一个在spring容器启动阶段,有时候需要用到类似 @ConfigurationProperties 用法的场景去初始化一些功能设置。
ConfigFactory.extract即可实现类似 @ConfigurationProperties 的配置注入封装的功能,即提取指定前缀的配置,封装成一个java对象。如下这段代码,需要在应用启动时,根据配置初始化系统的默认Locale时区

案例源码

ApplicationConfigProperties applicationProperties = ConfigFactory.extract("spring.application", ApplicationConfigProperties.class);
if (applicationProperties != null)
{
    if (!ObjectUtils.isEmpty(applicationProperties.getDefaultLocale()))
    {
        Locale.setDefault(applicationProperties.getDefaultLocale());
    }
    
    if (!ObjectUtils.isEmpty(applicationProperties.getDefaultTimeZone()))
    {
        TimeZone.setDefault(applicationProperties.getDefaultTimeZone());
    }
}

场景分析

这段代码看似简洁,但如果按平常的做法,肯定是先读取配置,然后转换成相应的Locale和TimeZone对象,如果涉及字段繁多的,使用将变得过于繁杂,使用ConfigFactory.extract后,可以瞬间简化操作。

5. bind(String prefix, T target)函数使用

HikariDataSource master = createDataSource(properties, HikariDataSource.class);
ConfigFactory.bind(HIKARI_PREFIX, master);

// 你可以操作master对象的属性了
...
System.out.println(master.getDriverClassName())

6. bind(String prefix, Bindable target)函数使用

以下代码是用于自定义封装从数据库节点列表的真实案例代码:


// 调用 bind(String prefix, Bindable<T> target) 将从节点列表封装成BindResult<List<Properties>>类型
BindResult<List<Properties>> ml = ConfigFactory.bind(SLAVE_PREFIX, Bindable.listOf(Properties.class));
    if (ObjectUtils.isEmpty(ml))
    {
        throw new RuntimeException("从库若是配置了spring.datasource.slaves,则不能为空!");
    }
	  
	  // 从BindResult<List<Properties>>中获取List<DataSource>对象
    List<DataSource> slaveDataSources = new ArrayList<>(ml.get().size());
    for (Properties slave : ml.get())
    {
        String username = slave.getProperty("username");
        String password = slave.getProperty("password");
        String url = slave.getProperty("url");
        Assert.notNull(username, "从库用户名不能为空");
        Assert.notNull(password, "从库密码不能为空");
        Assert.notNull(url, "从库URL不能为空");
        DruidDataSource slaveDataSource = createDataSource(properties, DruidDataSource.class);
        slaveDataSource.setUsername(username);
        slaveDataSource.setPassword(password);
        slaveDataSource.setUrl(url);
        ConfigFactory.bind(DRUID_PREFIX, slaveDataSource);
        slaveDataSource.setDefaultAutoCommit(true);
        slaveDataSource.setName("slave-node");
        slaveDataSource.init();
        slaveDataSources.add(slaveDataSource);
    }

在这里插入图片描述

7. 总结

以上就是有关ConfigFactory配置工厂类的使用,从初始化,到每个api的介绍。在项目架构设计中经常或多或少需要用到自定义配置组件,此时ConfigFactory类带给配置的灵活性可以体现出来!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码到π退休

你的打赏是我精心创作的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值