springboot 创建单例模式
springboot 单例模式的两种写法集成 service因为是单例模式,所有需要spring上下文注入进来,才能获取到@Componentpublic class SpringContextUtils implements ApplicationContextAware {private static ApplicationContext applicationContext;@Overrid
·
springboot 单例模式的两种写法
- 集成 service
因为是单例模式,所有需要spring上下文注入进来,才能获取到
@Component
public class SpringContextUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtils.applicationContext = applicationContext;
}
/**
* 获取 ApplicationContext
*
* @return
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public static Object getBean(String name) {
return applicationContext.getBean(name);
}
public static <T> T getBean(Class<T> clazz) {
return applicationContext.getBean(clazz);
}
public static <T> T getBean(String name, Class<T> clazz) {
return applicationContext.getBean(name, clazz);
}
}
- 单列模式:饿汉式(一般最好使用饿汉式来操作)
public class JdysEquipmentSinleton {
private static volatile JdysEquipmentSinleton INSYANCE;
private int CODE;
private IJdysEquipmentBillService jdysEquipmentBillServiceForNew;
private JdysEquipmentSinleton(){
jdysEquipmentBillServiceForNew = SpringContextUtils.getBean(IJdysEquipmentBillService.class);
}
public static JdysEquipmentSinleton getInstance(){
if(null == INSYANCE){
synchronized (JdysEquipmentSinleton.class){
if(null == INSYANCE){
INSYANCE = new JdysEquipmentSinleton();
}
}
}
return INSYANCE;
}
public String getMaxEquipmentBillCode2(){
if(0 != CODE){
CODE += 1;
return "D" + handelStrCode(CODE);
}else {
String maxEquipmentBillCode = DataUtil.isNotEmpty(jdysEquipmentBillServiceForNew.getMaxEquipmentBillCode()) ? jdysEquipmentBillServiceForNew.getMaxEquipmentBillCode() : "D00000";
CODE += Integer.valueOf(maxEquipmentBillCode.substring(1,6));
CODE += 1;
return "D" + handelStrCode(CODE);
}
}
public String handelStrCode(int code){
int length = String.valueOf(code).length();
int num = 0;
if(length < 5){
num = 5 - length;
}
String numCode = "";
for (int i = 0; i < num; i++) {
numCode += "0";
}
return numCode + code;
}
- 一般常用的懒汉式单例
private LazyMan(){
System.out.println(Thread.currentThread().getName() + "ok");
}
/**
* volatile 避免指令重排
* */
private volatile static LazyMan lazyMan;
// 防止多线程出现问题,就使用了双重检测锁模式,懒汉式单列, 简称 DCL 懒汉式
public static LazyMan getInstance(){
if(null == lazyMan){
synchronized (LazyMan.class){
if(null == lazyMan){
lazyMan = new LazyMan(); //在极端情况下不是一个原子性的操作
/**
* 1. 分配内存空间
* 2.执行构造方法,初始化对象
* 3.把这个对象指向这个空间
*
* 123 A
*
* 132 B
* */
}
}
}
return lazyMan; //当B线程进来的时候可以能 lazyMan 还没重拍好
}
- 使用单列模式和反射斗智
package com.central.jdys.config;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
// 懒汉式单例(单列模式只会加载一次)
public class LazyMan {
private static boolean LazyFlag = false;
private LazyMan(){
// 保护反射机制来破坏
synchronized (LazyMan.class){
if(LazyFlag == false){
LazyFlag = true;
}else {
throw new RuntimeException("不要用反射来破坏");
}
}
System.out.println(Thread.currentThread().getName() + "ok");
}
/**
* volatile 避免指令重排
* */
private volatile static LazyMan lazyMan;
// 防止多线程出现问题,就使用了双重检测锁模式,懒汉式单列, 简称 DCL 懒汉式
public static LazyMan getInstance(){
if(null == lazyMan){
synchronized (LazyMan.class){
if(null == lazyMan){
lazyMan = new LazyMan(); //在极端情况下不是一个原子性的操作
/**
* 1. 分配内存空间
* 2.执行构造方法,初始化对象
* 3.把这个对象指向这个空间
*
* 123 A
*
* 132 B
* */
}
}
}
return lazyMan; //当B线程进来的时候可以能 lazyMan 还没重拍好
}
public static void main(String[] args) throws Exception {
/**
* 如果一个是通过单列加载,一个是通过反射new对象,那么就能在构造方法里面设置 synchronized 拦截住
* */
//
// LazyMan instance = LazyMan.getInstance(); //通过单列加载
// // 反射可以破坏单例
// Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
// declaredConstructor.setAccessible(true); //无视 私有关键字
// LazyMan lazyMan = declaredConstructor.newInstance(); //直接new一个对象
/**
* 当两个对象都是用反射加载的,那么就拦不住
*
* 解决,定义一个标志位LazyFlag,放在内部类,做判断
*
* 当然这种也是可以被破坏的
* */
/*** 拿到字段
* getDeclaredField 拿到字段
* setAccessible(true) 破坏私有属性
* */
Field lazyFlag = LazyMan.class.getDeclaredField("LazyFlag");
lazyFlag.setAccessible(true);
// 反射可以破坏单例
Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
declaredConstructor.setAccessible(true); //无视 私有关键字
LazyMan instance = declaredConstructor.newInstance(); //直接new一个对象
/**
* 通过反射new出对象后,在把 lazyFlag 的标志位 改为 false,就能重新new 对象
* */
lazyFlag.set(instance,false);
LazyMan lazyMan = declaredConstructor.newInstance(); //直接new一个对象
System.out.println(instance);
System.out.println(lazyMan);
}
/**静态内部类实现*/
public static class InnerClass{
}
}
- 使用枚举
– 枚举是没用办法使用反射来破解的,枚举没有无参构造,只有一个有参构造,一个是 String,一个是int类型,强行使用反射,jdk会直接抛出异常
更多推荐
已为社区贡献1条内容
所有评论(0)