Java通过ResourceBundle获取properties配置

1、demo中考虑了配置读取并发问题(只是为了练练手而已,配置文件的一致性又不用考虑,手动狗头[旺财])

2、使用了单例模式,获取单例工具对象

3、增加了缓存机制,用以保存不同配置读取,节约资源,提高效率(貌似初始化的同步,效率更低)

4、既然是ResourceBundle,肯定只能读取properties文件啊!!

 

 

package com.yd.rcp.utils;

import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;

/**
 * 工具类,获取src目录下的properties配置文件。 处理过单例工具类初始并发、以及读取配置并发 。确保并发读取配置不会出现覆盖读取
 */
public class PropertiesTools {
    private static volatile PropertiesTools tools = null;
    private static volatile Map<String, ResourceBundle> bundlePool = null;

    /**
     * 单例模式的标准姿势
     * */
    private PropertiesTools() {
    }
    
    /**
     * 没有开放的构造的构造函数,肯定得给个函数处理工具类的获取。
     * 控制并发问题,避免多线程任务获取到不同的工具类对象,导致后面读取不同配置时,后者覆盖前者。(先者读取好配置,后者才初始化)
     * */
    public synchronized static PropertiesTools getPropertiesTools() {
        if (tools == null) {
            tools = new PropertiesTools();
        }
        return tools;
    };

    /**
     * 获取指定配置文件中的一个值
     * @param packageFileName     "包名.文件名",不需要接后缀名,只读取properties文件
     * @param key                 需要获取的键名
     * @return                     键对应的值
     * */
    public String getPropertyValue(String packageFileName, String key) {
        return getPropertyStringValue(packageFileName, key, String.class);
    }
    /**
     * 获取指定配置文件中的,指定的一个值
     * @param packageFileName     "包名.文件名",不需要接后缀名,只读取properties文件
     * @param key                 需要获取的键名
     * @param T                    需要获取的值类型
     * @return                     键对应的值
     * */
    public <T> T getPropertyStringValue(String packageFileName, String key, Class<T> T) {
        if (bundlePool == null) {
            initBundlePool();
        }
        ResourceBundle nameBundle = bundlePool.get(packageFileName);
        if (nameBundle != null) {
            return getValueByClazzType(nameBundle, key, T);
        }
        ResourceBundle temp = ResourceBundle.getBundle(packageFileName.trim());
        bundlePool.put(packageFileName, temp);
        return getValueByClazzType(temp, key, T);
    }

    /**
     * 获取Bundle对象,解决某个对象需要暂存一个Bundle的需求
     * @param packageFileName     "包名.文件名",不需要接后缀名,只读取properties文件
     * @return                     ResourceBundle对象
     * */
    public ResourceBundle getBundle(String packageFileName) {
        if (bundlePool == null) {
            initBundlePool();
        }
        if (checkBundle(packageFileName)) {
            return bundlePool.get(packageFileName);
        }
        return createBundle(packageFileName);
    }

    /**
     * 根据文件名创建相应的Bundle,并缓存做缓存。创建时同步是为了预防一个配置都被读取两次(看并发情况,其实可以不使用同步)
     * @param packageFileName     "包名.文件名",不需要接后缀名,只读取properties文件
     * */
    private synchronized ResourceBundle createBundle(String packageFileName) {
        if (checkBundle(packageFileName)) {
            return bundlePool.get(packageFileName);
        }
        ResourceBundle temp = ResourceBundle.getBundle(packageFileName.trim());
        bundlePool.put(packageFileName, temp);
        return temp;
    }

    /**
     * 检查缓存中是否有存在读取过的配置
     * @param packageFileName     "包名.文件名",不需要接后缀名,只读取properties文件
     * @return 存在缓存的逻辑值
     * */
    private boolean checkBundle(String packageFileName) {
        ResourceBundle nameBundle = bundlePool.get(packageFileName);
        if (nameBundle != null) {
            return true;
        }
        return false;
    }

    /**
     * 针对不同的配置对象需求获取不同类型的值
     * @param bundle        值所存在的Bundle对象
     * @param key            被查询值的键名
     * @param type            预期值的类型
     * @return                被查询的值
     * */
    @SuppressWarnings("unchecked")
    private <T> T getValueByClazzType(ResourceBundle bundle, String key, Class<T> type) {
        if (type == Object.class) {
            return (T) bundle.getObject(key);
        }
        if (type == String[].class) {
            return (T) bundle.getStringArray(key);
        }
        return (T) bundle.getString(key);
    }

    /**
     * 初始化缓存容器,同步避免缓存被覆盖
     * */
    private synchronized void initBundlePool() {
        if (bundlePool == null) {
            bundlePool = new HashMap<String, ResourceBundle>();
        }
    }

    public static void main(String[] args) {
        PropertiesTools tool = PropertiesTools.getPropertiesTools();
        String temp = tool.getPropertyValue("com.yd.rcp.utils.customer", "username");
        System.out.println(temp);
    }
}

 

上一篇:手动安装pyhanlp


下一篇:不停服务,动态加载properties资源文件