java热加载(三)—— 配置文件热加载

今天我们说一下配置文件的热加载,在项目开发的过程中,都会用到一些数据的文件(格式如:csv,json等)。使用时会把数据加载到对应的java对象中,同时为了避免重复加载数据,我们会在第一次使用时把数据加载到缓存中,再次使用直接读取缓存中的数据即可。那数据内容发生了变化,该怎么办呢?这里说一下为了避免数据内容被误修改,所有我们存储数据对象的属性都是final的。
格式如下:

public class ConfDemo {
	/** a */
	public final String a;
	/** b */
	public final int b;
    .....

那热加载时,如何修改呢?一般两种方式,一是替换java对象,另一种就是使用反射修改。替换java对象的缺点就是有的时候我们会引用数据对象,那替换对象,不能修改这个引用对象的数据,所以最后我们选择了反射修改数据对象。

看下面例子:

public class Demo {
    public final int a;
    public Demo(int a) {
        this.a = a;
    }
}

public class Test {
    public static void main(String[] args) throws Exception {
        Demo a = new Demo(1);
        Class<?> clz = clz.getClass();
        Filed f = clz.getDeclaredField("a");
        f.setAccessible(true);
        f.set(a, 3);
        System.out.println(p.a);
    }
}

这样我们完成了热替换。我们延伸一下反射相关的知识,看到这里大家是不是发现反射能够修改final的变量值的,其实这样的说法是不准确的,final的变量值是可以修改的,但是有个前提是:定义的时候没有初始化。如果定义的时候初始化了也是不能修改的。
即,如果变成如下形式,再用反射修改a的值,是不会成功的

public class Demo {
    public final int a = 1;
}

那这是为什么呢?这是因为编译期间final类型的数据自动被优化了,所有用到该变量的地方自动替换成常量。

如果你就想初始化时设置值,还想使用反射修改这个值,还有一种方法来逃脱编译的优化,可以设置值为

public class Demo {
    public final int a = null != null ? 1 : 1;
}

这样设置之后,也能进行反射修改。

那么我们继续延伸,是不是final修饰的都会被虚拟机优化呢?答案当然是否定的。基本数据类型加上String类型(直接双引号的字符串)都会被编译器优化。其他类型的final修饰的,还是可以被修改的。

说到这还有一个需要注意的点就是:上面修改值得方法对final类型的属性都能正常运行,但是对于static的也就是常量会报错。那我们怎么修改常量呢?

对于常量来讲也会按照final的优化进行,那如何修改呢?这里用到了Field的modifies,每一个标记都会有一个标识(可以通过查看Modifier的源码,来看每一个约束的对应标识),我们可以通过修改这个标识,然后进行对常量属性的修改,如下

public class Demo {
    public static final int a = 1;
}

public class Test {
    public static void main(String[] args) throws Exception {
        Demo a = new Demo();
        Class<?> clz = clz.getClass();
        Filed f = clz.getDeclaredField("a");
        Filed modifiers = Filed.class.getDeclaredField("modifiers");
        modifiers.setAccessible(true);
        // 修改属性标识
        modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);
        f.setAccessible(true);
        f.set(a, 3);
        System.out.println(p.a);
    }
}

这样就能执行成功了,但是上面的例子是不能修改成功的。

配置的相关的热加载以及final属性反射相关的知识就说到这,有说的不对的地方,欢迎指正。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值