单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
但是一般的我们这些写单例的时候可能都会忽略掉一些东西,导致单例代码的不严谨。
反射机制破解单例模式(枚举除外):
[Java] 纯文本查看 复制代码
?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 | public class BreakSingleton{ public static void main(String[] args) throw Exception{ Class clazz = Class.forName( "Singleton" ); Constructor c = clazz.getDeclaredConstructor( null ); c.setAccessible( true ); Singleton s1 = c.newInstance(); Singleton s2 = c.newInstance(); //通过反射,得到的两个不同对象 System.out.println(s1); System.out.println(s2); } } |
如何避免以上的漏洞:
[Java] 纯文本查看 复制代码
?
01 02 03 04 05 06 07 08 09 10 11 12 | class Singleton{ private static final Singleton singleton = new Singleton(); private Singleton() { //在构造器中加个逻辑判断,多次调用抛出异常 if (instance!= null ){ throw new RuntimeException() } } public static Singleton getInstance(){ return singleton; } } |
反序列化机制破解单例模式(枚举除外):
[Java] 纯文本查看 复制代码
?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public class BreakSingleton{ public static void main(String[] args) throws Exception{ //先根据单例模式创建对象(单例模式所以s1,s2是一样的) Singleton s1=Singleton.getInstance(); Singleton s2=Singleton.getInstance(); //将s1写入本地某个路径 FileOutputStream fos= new FileOutputStream( "本地某个路径下文件" ); ObjectOutputStream oos= new ObjectOutputStream(fos); oos.writeObject(s1); oos.close(); fos.close(); //从本地某个路径读取写入的对象 ObjectInputStream ois= new ObjectInputStream( new FileInputStream( "和上面的本地参数路径相同" )); Singleton s3=(Singleton) ois.readObject(); System.out.println(s1); System.out.println(s2); System.out.println(s3); //s3是一个新对象 } } |
如何避免实现序列化单例模式的漏洞:
[Java] 纯文本查看 复制代码
?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 | class Singleton implements Serializable{ private static final Singleton singleton = new Singleton(); private Singleton() { } public static Singleton getInstance(){ return singleton; } //反序列化定义该方法,则不需要创建新对象 private Object readResolve() throws ObjectStreamException{ return singleton; } } |