编辑 | blame | 历史 | 原始文档

1. 简介

类似于nacos的动态配置,但是又不完全是,起初是因为一部分朋友不知道怎么去配静态配置(application.properties)和方便使用docker去运行而存在的。

2. 基本原理(可跳过)

当我们使用 getter 去获取数据时,一般是使用 getXxx这样的方法来获取,这是java全球通用的约定。然后我们使用动态配置时,我们使用一个切面去代理这个方法。

切点:

@Pointcut("@within(com.dobbinsoft.fw.support.annotation.DynamicConfigProperties)")

走代理方法,

@Around("cachePointCut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    MethodSignature signature = (MethodSignature)joinPoint.getSignature();
    DynamicConfigProperties annotation = (DynamicConfigProperties)signature.getDeclaringType().getAnnotation(DynamicConfigProperties.class);
    if (annotation != null) {
        String prefix = annotation.prefix();
        // 去对应的分组读取配置
        Class returnType = signature.getReturnType();
        if (returnType == String.class) {
            return dynamicConfigComponent.readString(prefix + ReflectUtil.getField(signature.getName()), null);
        } else if (returnType == Integer.class) {
            return dynamicConfigComponent.readInt(prefix + ReflectUtil.getField(signature.getName()), null);
        } else if (returnType == Long.class) {
            return dynamicConfigComponent.readLong(prefix + ReflectUtil.getField(signature.getName()), null);
        } else if (returnType == Boolean.class) {
            return dynamicConfigComponent.readBoolean(prefix + ReflectUtil.getField(signature.getName()), null);
        }
    }
    return joinPoint.proceed();
}

所以根本没用对象里面的属性,只用了它的方法签名,所以**请不要在群里面问,为什么对象里面没数据,又能get出来了.**

3. 接口

动态配置,只提供了一个持久化策略的接口,默认support包中给出 DynamicStorageFileSystemStrategy、DynamicStoragePropertiesStrategy 分别为文件系统持久化、静态配置文件持久化策略。这两个建议都不要用,文件系统持久化,将会破坏服务“无状态”的特性,不符合容器化的核心价值观。静态配置持久化则完全是为了测试时方便。当然在dobbinfw脚手架项目中给出了默认的mysql持久化策略。

public interface DynamicStorageStrategy {

    /**
     * 覆盖写,若存在,则更新,若不存在则写
     * @param key
     * @param value
     */
    public void write(String key, String value);

    public String read(String key);

    public boolean del(String key);

}

Q: 为什么mysql持久化策略要放在脚手架中?

A: 因为动态配置support包认为是一个可有可无的东西。业务系统也许不会用。

3. 使用方法

3.1. 启用

@EnableDynamicConfig
public class PromallApplication {
    // 在启动类上注解上,开启动态配置的注解
}

3.2. 编写配置类

@Data
@DynamicConfigProperties(prefix = DynamicConst.ADVERT_CONFIG_PREFIX)
public class UnimallAdvertProperties {

    /**
     * 首页TOP N 个数
     */
    private Integer topSalesNum;

}

3.3. 获取配置

@Autowired
private UnimallAdvertProperties unimallAdvertProperties;

....

Integer topSalesNum = unimallAdvertProperties.getTopSalesNum();

3.4. 更新配置

@Autowired
private DynamicConfigComponent dynamicConfigComponent;
....
// prefix与上文DynamicConst.ADVERT_CONFIG_PREFIX对应, 
dynamicConfigComponent.write(prefix + "topSalesNum", value);

4. 实现持久化策略

例如,您用的是mongodb配置保存方式,您可以自我实现DynamicStorageStrategy接口。并提高装配优先级即可。

@Component
@Primary
public class MyDynamicStorageStrategy implements DynamicStorageStrategy {
	.... impl
}