如何破坏单例模式

645 阅读1分钟

创建单例模式一般人都知道是有懒汉模式恶汉模式,

public class Singleton {


private static Singleton instance;

private Singleton(){}

public static synchronized Singleton getInstance(){
    if(instance == null) {
        instance = new Singleton();
        return instance;
    }
    return instance;
}
}

在Spring中单例在同一个容器中只有一个实例,那么Spring的单例真的是安全的吗???我们可不可以破坏它呢??

public static void main(String[] args) throws Exception{
        Singleton singleton = Singleton.getInstance();
        Singleton singleton1 = Singleton.getInstance();
        System.out.println(singleton.hashCode());
        System.out.println(singleton1.hashCode());
}

这里我直接贴图了 可以看到二个对象是同一个实例的。。。。。

现在我们换种方式获取,,,就是利用反射

public static void main(String[] args) throws Exception{
    Singleton singleton = Singleton.getInstance();
    Singleton singleton1 = Singleton.getInstance();
    System.out.println(singleton.hashCode());
    System.out.println(singleton1.hashCode());
    //利用反射获取该实例
    Constructor<Singleton> declaredConstructor = Singleton.class.getDeclaredConstructor();
    Singleton singleton2 = declaredConstructor.newInstance();
    System.out.println(singleton2.hashCode());
}

接下来看下三个对象的hashCode的值

利用反射我们可以获取另外一个实例,所以懒汉模式或者恶汉模式下的单例我们是可以破坏的,甚至Spring的单例我们也是可以破坏的,那么有没有其它一种方式实现单例安全呢????

那就是利用枚举 ,首先我们看下反射获得对象的方法

 Singleton singleton2 = declaredConstructor.newInstance();

看下它的源码

如果使用枚举的话,在你利用反射获取实例是会报错的

这是我们的枚举类

利用反射获取实例就会抛出异常

但是正常获取那么就是同一个实例