单例模式详解--通过源码分析:反射及反序列化破坏单例原理及枚举式单例如果防止其破坏、readResolve()如何防止反序列化破坏单例以及spring容器式单例思想

本文详细探讨了单例模式的实现方式,包括饿汉式、懒汉式、反射破坏单例、序列化破坏单例及其防止策略。重点介绍了枚举式单例如何防止反射和反序列化破坏,以及Spring框架中的单例思想。文章通过源码分析,解释了readResolve()方法如何防止反序列化破坏单例,并总结了各种单例模式的优缺点。
摘要由CSDN通过智能技术生成

写在前面

本文从最基础的饿汉式及懒汉式demo进行引入,通过jdk源码分别分析了:反射及反序列化破坏单例原理、readResolve()如何防止反序列化破坏单例、枚举式单例的优点及如何防止反射及反序列化破坏、以及spring容器式单例思想详解。

饿汉式单例模式:

一般形式

/**
 * 优点:执行效率高,性能高,没有任何的锁
 * 缺点:某些情况下,可能会造成内存浪费
 */
public class HungrySingleton {
   

    private static final HungrySingleton hungrySingleton = new HungrySingleton();

    private HungrySingleton(){
   }

    public static HungrySingleton getInstance(){
   
        return  hungrySingleton;
    }
}

静态代码块

/**
 * 静态代码块
 */
public class HungryStaticSingleton {
   

    private static final HungryStaticSingleton hungrySingleton;

    static {
   
        hungrySingleton = new HungryStaticSingleton();
    }

    private HungryStaticSingleton(){
   }

    public static HungryStaticSingleton getInstance(){
   
        return  hungrySingleton;
    }
}

懒汉式单例模式:

双重检查锁

/**
 * 优点:性能高了,线程安全了
 * 缺点:可读性难度加大,不够优雅,并且加锁会产生性能问题
 */
public class LazyDoubleCheckSingleton {
   
    private volatile static LazyDoubleCheckSingleton instance;
    private LazyDoubleCheckSingleton(){
   }

    public static LazyDoubleCheckSingleton getInstance(){
   
        //检查是否要阻塞
        if (instance == null) {
   
            synchronized (LazyDoubleCheckSingleton.class) {
   
                //检查是否要重新创建实例
                if (instance == null) {
   
                    instance = new LazyDoubleCheckSingleton();
                    //指令重排序的问题
                }
            }
        }
        return instance;
    }
}

静态内部类

/*
   优点:写法优雅,利用了Java本身语法特点,性能高,避免了内存浪费,不能被反射破坏
   缺点:不优雅
 */
public class LazyStaticInnerClassSingleton {
   

    private LazyStaticInnerClassSingleton(){
   
        if(LazyHolder.INSTANCE != null){
   
            throw new RuntimeException("不允许非法访问");
        }
    }

    private static LazyStaticInnerClassSingleton getInstance(){
   
        return LazyHolder.INSTANCE;
    }

    private static class LazyHolder{
   
        private static final LazyStaticInnerClassSingleton INSTANCE = new LazyStaticInnerClassSingleton();
    }
}

反射破坏单例

public class ReflectTest {
   

    public static void main(String[] args) {
   
        try {
   
            //获取单例类的class及构造器
            Class<?> clazz = LazyDoubleCheckSingleton.class;
            Constructor c = clazz.getDeclaredConstructor(null);

            //设置强制访问
            c.setAccessible(true);

            //实例化两次
            Object instance1 = c.newInstance();
            Object instance2 = c.newInstance();

            //分别打印
            System.out.println(instance1);
            System.out.println(instance2);

            //false
            System.out.println(instance1 == instance2);

        }catch (Exception e){
   
            e.printStackTrace();
        }
    }
}

输出结果:在这里插入图片描述

序列化破坏单例:

//一个单例对象创建好后,有时候需要将对象序列化然后写入磁盘,下次使用时再从磁盘中读取对象进行反序列化,然后将其转化为内存对象。反序列化后的对象会重新分配内存,即重新创建
public class SeriableSingletonTest {
   
    public 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值