常见设计模式-单例模式(2)

今天主要来介绍注册式单例模式

       注册式单例包括两种:一种是枚举式单例,一种是容器式单例(springIoc模块中大量用到此模式)

       先来介绍枚举式单例,问题:为什么枚举式一定可以保证单例?

      我新建了一个单例类来测试解决该问题

       

           而后我通过Jad反编译可以看到

         

1、首先它并没有一个无参的构造方法,在整个程序中,不管怎么序列化,程序启动时只会初始化该对象一次。

2、其次获取该实例的INSTANCE实际上是一个饿汉式单例,属于线程安全范畴。

到此为止,保证单例性质解决了,但是怎么保证被反序列化暴力破解呢?

 其实在ObjectInputStream.readObjecg() 方法中  进入到readObject0()方法内

在我们进入到 readEnum() 方法内可以发现

实际上是通过一个类名加上一个枚举的名字,通过这两个唯一值去确定这个枚举,显然我们的JVM中肯定只会被加载一次。

序列化方法看来是行不通了,那么能否通过反射方式去破坏该单例呢?

结果得知:  我们通过反射方式去创建该对象但是却显示无法被反射

从JDK层面就为枚举不被序列化和反射破坏。

接下来介绍另外一种单例方式:容器式单例   springIoc模块 是采用这种方式

但是不可避免会带来线程安全问题

可以看到创建了N个对象 解决方案:

实际上我们还是可以采用同步锁的方式  就可以完美解决该问题了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值