美文网首页
设计模式:单例模式(3)

设计模式:单例模式(3)

作者: 谁家的猪 | 来源:发表于2019-07-23 08:25 被阅读0次

反射攻击解决方案及原理

测试反射是否可以创建单例对象

  1. 创建测试类
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * @author lijiayin
 */
public class ReflectTest {

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class clazz = HungrySingleton.class;
        Constructor constructor = clazz.getDeclaredConstructor();
        constructor.setAccessible(true);
        HungrySingleton instance = HungrySingleton.getInstance();
        HungrySingleton object = (HungrySingleton) constructor.newInstance();
        System.out.println(instance);
        System.out.println(object);
        System.out.println(instance == object);
    }
}
  1. 测试结果


    测试结果.png
  2. 结论
    通过反射可以创建对象

反射攻击解决方案

构造器抛出异常,只适用于通过类初始化实现单例的模式

  1. 修改HungrySingleton类
import java.io.Serializable;

/**
 * @author lijiayin
 */
public class HungrySingleton implements Serializable {
    private final static HungrySingleton hungrySingleton;
    static {
        hungrySingleton = new HungrySingleton();
    }
    private HungrySingleton(){
        if(hungrySingleton != null){
            throw new RuntimeException("单例构造器禁止反射调用");
        }
    }
    public static HungrySingleton getInstance(){
        return hungrySingleton;
    }
    private Object readResolve(){
        return hungrySingleton;
    }
}
  1. 测试结果


    测试结果.png
  2. 结论
    成功阻止反射创建
  3. 同理StaticInnerClassSingleton这种单例方法,也可以通过这种方式阻止反射调用
/**
 * @author lijiayin
 */
public class StaticInnerClassSingleton {
    
    private StaticInnerClassSingleton(){
        if(InnerClass.staticInnerClassSingleton != null){
            throw new RuntimeException("单例构造器禁止反射调用");
        }
    }
    
    private static class InnerClass {
        private static StaticInnerClassSingleton staticInnerClassSingleton = new StaticInnerClassSingleton();
    }
    
    public static StaticInnerClassSingleton getInstance(){
        return InnerClass.staticInnerClassSingleton;
    }
}

使用枚举类

创建EnumInstance枚举类型

/**
 * @author lijiayin
 */
public enum EnumInstance {
    
    INSTANCE;
    private Object data;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public static EnumInstance getInstance(){
        return INSTANCE;
    }
}

测试序列化与反序列化

代码实现
import java.io.*;

/**
 * @author lijiayin
 */
public class EnumSerializableTest {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        EnumInstance enumInstance = EnumInstance.getInstance();
        enumInstance.setData(new Object());
        ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("singleton_file"));
        outputStream.writeObject(enumInstance);
        
        File file = new File("singleton_file");
        ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(file));
        EnumInstance newInstance = (EnumInstance)inputStream.readObject();
        System.out.println(enumInstance.getData());
        System.out.println(newInstance.getData());
        System.out.println(enumInstance.getData() == newInstance.getData());
    }
}
测试结果
测试结果.png
原理

ObjectInputStream的源码,readObject()方法,与上一章类似,这次由于是enum类型,调用readEnum()方法,并没有创建新对象。

测试反射

代码实现
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * @author lijiayin
 */
public class EnumReflectTest {

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class clazz = EnumInstance.class;
        Constructor constructor = clazz.getDeclaredConstructor(String.class, Integer.class);
        constructor.setAccessible(true);
        EnumInstance enumInstance = (EnumInstance) constructor.newInstance("ABC", 888);
    }
}
测试结果
测试结果.png

相关文章

  • 设计模式第二篇、单例设计模式

    目录1、什么是单例设计模式2、单例设计模式的简单实现3、单例设计模式面临的两个问题及其完整实现4、单例设计模式的应...

  • 单例模式

    目录 1、设计模式简介 2、什么是单例模式 3、单例模式应用场合 4、单例模式作用 5、单例模式3个要点/要素 6...

  • 单例模式Java篇

    单例设计模式- 饿汉式 单例设计模式 - 懒汉式 单例设计模式 - 懒汉式 - 多线程并发 单例设计模式 - 懒汉...

  • 设计模式之一:单例模式

    摘要:设计模式之一:单例模式目录介绍1.单例模式介绍2.单例模式定义3.单例模式使用场景4.单例模式的实现方式 4...

  • python中OOP的单例

    目录 单例设计模式 __new__ 方法 Python 中的单例 01. 单例设计模式 设计模式设计模式 是 前人...

  • 单例

    目标 单例设计模式 __new__ 方法 Python 中的单例 01. 单例设计模式 设计模式设计模式 是 前人...

  • 设计模式 - 单例模式

    设计模式 - 单例模式 什么是单例模式 单例模式属于创建型模式,是设计模式中比较简单的模式。在单例模式中,单一的类...

  • 设计模式

    常用的设计模式有,单例设计模式、观察者设计模式、工厂设计模式、装饰设计模式、代理设计模式,模板设计模式等等。 单例...

  • 2018-04-08php实战设计模式

    一、单例模式 单例模式是最经典的设计模式之一,到底什么是单例?单例模式适用场景是什么?单例模式如何设计?php中单...

  • python 单例

    仅用学习参考 目标 单例设计模式 __new__ 方法 Python 中的单例 01. 单例设计模式 设计模式设计...

网友评论

      本文标题:设计模式:单例模式(3)

      本文链接:https://www.haomeiwen.com/subject/pdlulctx.html