【问题标题】:How to break Singleton?如何打破单例?
【发布时间】:2013-12-31 19:48:57
【问题描述】:

如何打破java中的单例类? 单例模式确保一个类只有一个实例,并提供一个全局访问点。

类的默认构造函数是私有的,这样可以防止其他类直接实例化该对象。

静态修饰符应用于返回对象的实例方法,因为它使该方法成为类级别的方法,无需创建对象即可访问

编辑:

public class Singleton {
    private static Singleton singleInstance;

    private Singleton() {
        System.out.println("Singleton Constructor Running...");
    }
    public static Singleton getInstance() { 
        if (singleInstance == null) { 
            synchronized (Singleton.class) { 
            if (singleInstance == null) { 
                    singleInstance = new Singleton();
                }
            }
        } 
        return singleInstance; 
    }
}

使用反射打破单例

import java.lang.reflect.Constructor;

public class BreakSingletonUsingReflection {
    public static void main(String[] args) {
        Singleton instanceOne = Singleton.getInstance();
        Singleton instanceTwo = null;
        try {
            Constructor[] constructors = Singleton.class.getDeclaredConstructors();
            for (Constructor constructor : constructors) {
                //Below code will destroy the singleton pattern
                constructor.setAccessible(true);
                instanceTwo = (Singleton) constructor.newInstance();
                break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(instanceOne.hashCode());
        System.out.println(instanceTwo.hashCode());
    }
}

【问题讨论】:

  • 你所说的“中断”是什么意思?
  • 如果用enum来实现呢?
  • public static Singleton getInstance() { if (singleInstance == null) { synchronized (Singleton.class) { if (singleInstance == null) { singleInstance = new Singleton(); } } } 返回单实例; }
  • 这闻起来像 an XY problem. 你想要实现的最终目标是什么?
  • 为数据库类创建单个对象

标签: java


【解决方案1】:

1.

import java.lang.reflect.Constructor;


    public class ReflectionSingletonTest {

        public static void main(String[] args) {
            EagerInitializedSingleton instanceOne = EagerInitializedSingleton.getInstance();
            EagerInitializedSingleton instanceTwo = null;
            try {
                Constructor[] constructors = EagerInitializedSingleton.class.getDeclaredConstructors();
                for (Constructor constructor : constructors) {
                    //Below code will destroy the singleton pattern
                    constructor.setAccessible(true);
                    instanceTwo = (EagerInitializedSingleton) constructor.newInstance();
                    break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(instanceOne.hashCode());
            System.out.println(instanceTwo.hashCode());
        }

    }

2.

单例类:

package com.singleton.securitymgr;

public class Singleton {

    private static final Singleton INSTANCE = new Singleton();

    private Singleton() {
        System.out.println("Singleton Constructor Running...");
    }

    public static final Singleton getInstance() {
        return INSTANCE;
    }
}

测试类:

package com.singleton.securitymgr;

import java.lang.reflect.Constructor;

public class Test {

    public static void main(String[] args) throws Exception {

        Singleton s = Singleton.getInstance();

        Class clazz = Singleton.class;

        Constructor cons = clazz.getDeclaredConstructor();
        cons.setAccessible(true);

        Singleton s2 = (Singleton) cons.newInstance();
    }
}

【讨论】:

    【解决方案2】:

    另一种方法是序列化 Object 将其存储在文件中并反序列化以获取新的 Object。

    【讨论】:

      【解决方案3】:

      单例仅适用于每个类加载器。要打破它,请使用多个类加载器

      【讨论】:

        猜你喜欢
        • 2022-11-20
        • 2012-01-11
        • 2011-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-13
        相关资源
        最近更新 更多