Apollo加载配置小坑一记

公司的配置中心使用的是携程的Apollo配置中心,现在基本上所有的配置文件都迁移到了Apollo里面。Apollo的使用非常方便,实时生效,不需要重启应用。但是有个缺点,就是对配置没有进行校验,如果配置格式或者类型有问题的话,就会抛异常。
鉴于此,一些逻辑上的校验就得自己做。例如对下载的账单要进行分割,这个大小不能小于1MB。我在配置的set方法里面做了一点简单的校验,例如账单分割单位billCutSize,如果小于1MB,就直接设置为1MB。

@Value("${bill_cut_size:1}")
 private int billCutSize;
    
 public void setBillCutSize(int size){
        if(size < 1){
            billCutSize = 1;
        }else{
            billCutSize = size;
        }
}

但是运行的时候,发现billCutSize设置为0的时候,并没有被替换成1,仍然是0。看来Apollo加载配置的时候,并不是通过setter方法加载的。下面通过源码进行分析说明

// apollo配置个更新后,会通过AutoUpdateConfigChangeListener触发onChange
public void onChange(ConfigChangeEvent changeEvent) {
        // 获取到所有更改了的Key集合
        Set<String> keys = changeEvent.changedKeys();
        if(!CollectionUtils.isEmpty(keys)) {
            Iterator var3 = keys.iterator();

            while(true) {
                String key;
                Collection targetValues;
                do {
                    do {
                        do {
                            if(!var3.hasNext()) {
                                return;
                            }

                            key = (String)var3.next();
                            targetValues = this.springValueRegistry.get(key);
                        } while(targetValues == null);
                    } while(targetValues.isEmpty());
                } while(!this.shouldTriggerAutoUpdate(changeEvent, key));

                Iterator var6 = targetValues.iterator();

                while(var6.hasNext()) {
                    SpringValue val = (SpringValue)var6.next();
                    this.updateSpringValue(val); // 就是这个方法去更新值
                }
            }
        }
    }

然后updateSpringValue里面做什么了呢?

private void updateSpringValue(SpringValue springValue) {
        try {
            // 解析值
            Object value = this.resolvePropertyValue(springValue);
            springValue.update(value); // 更新
            logger.info("Auto update apollo changed value successfully, new value: {}, {}", value, springValue);
        } catch (Throwable var3) {
            logger.error("Auto update apollo changed value failed, {}", springValue.toString(), var3);
        }

    }
    
public void update(Object newVal) throws IllegalAccessException, InvocationTargetException {
        if(this.isField()) { // 配置的值是field类型
            this.injectField(newVal);
        } else {
            this.injectMethod(newVal);
        }

    }
    
 private void injectField(Object newVal) throws IllegalAccessException {
        boolean accessible = this.field.isAccessible();
        this.field.setAccessible(true);
        this.field.set(this.bean, newVal); // 通过反射赋值
        this.field.setAccessible(accessible);
    }

看到了这里就豁然开朗了,原来是通过反射对字段赋值,怪不得set方法不起作用。其实回过头来想,用spring开发久了,依赖注入的思想根深蒂固,以为什么都是靠构造器和setter进行注入。我们的configBean,其实不一定有带参数的构造器和setter方法的,这样一来通过反射进行赋值确实是更好的方法。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值