Java通过反射破坏单例模式

发布于:2024-12-18 ⋅ 阅读:(14) ⋅ 点赞:(0)

有个第三方工具类,不支持多例模式。但是又不能直接改第三方工具类的代码,因此可以通过反射破坏第三方工具类的单例。

第三方工具类反编译如下

可以看到构造函数进行了私有化,不允许外部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类的构造函数
            Constructor<DataHandler> 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值是否正确。");
}