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); } }