郑州怎样建设公司网站,织梦网站文章内容模板,wordpress张戈,成都的汽车网站建设有个第三方工具类#xff0c;不支持多例模式。但是又不能直接改第三方工具类的代码#xff0c;因此可以通过反射破坏第三方工具类的单例。
第三方工具类反编译如下
可以看到构造函数进行了私有化#xff0c;不允许外部new#xff0c;只能通过newInstance进行实例化。并且…有个第三方工具类不支持多例模式。但是又不能直接改第三方工具类的代码因此可以通过反射破坏第三方工具类的单例。
第三方工具类反编译如下
可以看到构造函数进行了私有化不允许外部new只能通过newInstance进行实例化。并且newInstance是单例的。 DataHandler.class
public class DataHandler {private static volatile DataHandler INSTANCE;private final byte[] encryptKeys;private final String publicKeys;private final String privateKeys;private final String appID;private final String secret;private String version 2.0.0;private boolean skipVerify false;private DataHandler(String appID, String secret, String publicKey, String privateKey) throws IOException {//.....}public static DataHandler newInstance(String appID, String secret, String publicKey, String privateKey) throws IOException {if (INSTANCE null) {Class var4 DataHandler.class;synchronized(DataHandler.class) {if (INSTANCE null) {INSTANCE new DataHandler(appID, secret, publicKey, privateKey);}}}return INSTANCE;}
}通过反射破坏单例模式
import java.lang.reflect.Constructor;public class DataHandlerFactory {public static DataHandler createNewInstance(String appId, String appSecret, String publicKey, String privateKey) {try {// 获取DataHandler类的构造函数ConstructorDataHandler constructor DataHandler.class.getDeclaredConstructor(String.class, String.class, String.class, String.class);constructor.setAccessible(true);// 通过反射创建新的实例return constructor.newInstance(appId, appSecret, publicKey, privateKey);} catch (Exception e) {return null;}}}使用方法
//原本使用第三方工具类的方式默认单例模式
DataHandler dataHandler DataHandler.newInstance(appId, appSecret, publicKey, privateKey);//修改后允许多例。createNewInstance方法如果抛出异常那么是有可能为null因此下面要进行手动判空
DataHandler dataHandler DataHandlerFactory.createNewInstance(appId, appSecret, publicKey, privateKey);
if (Objects.isNull(dataHandler)) {throw new RuntimeException(创建DataHandler对象失败请检查appId, appSecret, publicKey, privateKey值是否正确。);
}通过缓存构造函数、缓存重复的实例进一步提升性能和减少反射所带来的性能开销
优化DataHandlerFactory类
import lombok.extern.slf4j.Slf4j;import java.lang.reflect.Constructor;
import java.util.concurrent.ConcurrentHashMap;Slf4j
public class DataHandlerFactory {// 使用线程安全的 ConcurrentHashMap 存储实例public static final ConcurrentHashMapString, DataHandler instanceCache new ConcurrentHashMap();// 缓存构造函数private static ConstructorDataHandler cachedConstructor;static {try {cachedConstructor DataHandler.class.getDeclaredConstructor(String.class, String.class, String.class, String.class);cachedConstructor.setAccessible(true);} catch (NoSuchMethodException | SecurityException e) {log.error(e.getMessage(), e);}}public static DataHandler createNewInstance(String appId, String appSecret, String publicKey, String privateKey) {// 创建一个缓存键String cacheKey appId _ appSecret _ publicKey _ privateKey;// 检查缓存中是否已有该实例如果有则直接返回DataHandler instance instanceCache.get(cacheKey);if (instance ! null) {return instance;}// 如果缓存中没有该实例则创建并缓存try {instance cachedConstructor.newInstance(appId, appSecret, publicKey, privateKey);// 存入缓存并确保线程安全instanceCache.put(cacheKey, instance);return instance;} catch (Exception e) {log.error(e.getMessage(), e);return null;}}}