springboot 单例模式的两种写法
- 集成 service
因为是单例模式,所有需要spring上下文注入进来,才能获取到
@Component
public class SpringContextUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtils.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public static Object getBean(String name) {
return applicationContext.getBean(name);
}
public static T getBean(Class clazz) {
return applicationContext.getBean(clazz);
}
public static T getBean(String name, Class 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");
}
private volatile static LazyMan lazyMan;
// 防止多线程出现问题,就使用了双重检测锁模式,懒汉式单列, 简称 DCL 懒汉式
public static LazyMan getInstance(){
if(null == lazyMan){
synchronized (LazyMan.class){
if(null == lazyMan){
lazyMan = new LazyMan(); //在极端情况下不是一个原子性的操作
}
}
}
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");
}
private volatile static LazyMan lazyMan;
// 防止多线程出现问题,就使用了双重检测锁模式,懒汉式单列, 简称 DCL 懒汉式
public static LazyMan getInstance(){
if(null == lazyMan){
synchronized (LazyMan.class){
if(null == lazyMan){
lazyMan = new LazyMan(); //在极端情况下不是一个原子性的操作
}
}
}
return lazyMan; //当B线程进来的时候可以能 lazyMan 还没重拍好
}
public static void main(String[] args) throws Exception {
//
// LazyMan instance = LazyMan.getInstance(); //通过单列加载
// // 反射可以破坏单例
// Constructor declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
// declaredConstructor.setAccessible(true); //无视 私有关键字
// LazyMan lazyMan = declaredConstructor.newInstance(); //直接new一个对象
Field lazyFlag = LazyMan.class.getDeclaredField("LazyFlag");
lazyFlag.setAccessible(true);
// 反射可以破坏单例
Constructor declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
declaredConstructor.setAccessible(true); //无视 私有关键字
LazyMan instance = declaredConstructor.newInstance(); //直接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会直接抛出异常