单例模式

单例模式使用场景,数据源,文件配置,上下文等
实现方式:
写法:声明静态变量,构造方法私有化,全局唯一访问入口
懒汉模式:类加载即实例化,高效,性能好,但是浪费内存,如果量多的话大量消耗内存,影响程序运行,例如启动缓慢
饿汉模式:使用时候加载,节省内存,存在线程安全问题,doubleCheck方式解决线程安全问题。
静态内部类方式:利用java特性,加载classpath文件下的.class文件特性,静态内部类因为路径问题,只有在使用的时候,才会初始化,静态内部类内使用懒汉式写法,达到单例效果。
以上都无法避免java反射攻击以及发序列化问题
注册式:枚举,枚举因为使用的是内部容器管理的方式,与ioc相似,通过唯一的key来管理实例,在初始化的时候就已经写入容器,而且在反射攻击的时候,jdk底层自身有做判断,如果类型为枚举类,则不支持反射构造器使用,避免发射攻击:
ThreadLocal<>式 线程特性,针对单个线程,以线程名称为key,与ioc思想一致,单个线程实现单例:
以上方法都无法避免反序列化破坏
反序列化破坏解决办法,重写readResolve方法,返回单例实例,ObjectInputStream在读取实例的时候,会判断是否存在readResolve方法,存在的话直接反射获取实例,否则生成新的实例(破坏单例的原因)
AbstractBeanFactory.org.springframework.beans.factory.support.FactoryBeanRegistrySupport#getObjectFromFactoryBean中使用了注册式单例模式+doubleCheck,ContextError中使用了ThreadLocal<>式单例,使得错误记录做到隔离
克隆模式,因为底层使用字节流序列化的方式,不关注构造方法私有化,所以也会破坏单例,不过这种模式本身与单例模式也是冲突的,既然支持克隆,就不应该设计成单例的

posted @ 2021-04-11 12:10  好好的一个居士  阅读(45)  评论(0)    收藏  举报