前言
单例模式Singleton: 单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。
单例模式的要点有三个:
一是某个类只能有一个实例
二是它必须自行创建这个实例
三是它必须自行向整个系统提供这个实例
实现
全局只有一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class Singleton { private static final Singleton INSTANCE = new Singleton();
public static Singleton getInstance() { return INSTANCE; }
private Singleton() { } }
public class Singleton { public static final Singleton INSTANCE = new Singleton();
private Singleton() { } }
|
使用枚举实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| public enum EnumSingleton {
INSTANCE;
public void hello() { System.out.println("Hello World!"); }
}
class Test { void test() { EnumSingleton enumSingleton = EnumSingleton.INSTANCE; enumSingleton.hello(); } }
public final class EnumSingleton extends Enum {
public static final EnumSingleton INSTANCE = new EnumSingleton();
private EnumSingleton() {}
public void hello() { System.out.println("Hello World!"); }
}
|
如果没有特殊的需求,使用Singleton模式的时候,最好不要延迟加载,这样会使代码更简单。延迟加载会遇到线程安全问题
非要实现的话最好借助内部类来实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class LazySingleton {
private static class LazyHolder { private static LazySingleton INSTANCE = new LazySingleton(); }
public static LazySingleton getInstance() { return LazyHolder.INSTANCE; }
private LazySingleton() {}
public void hello() { System.out.println("Hello World!"); } }
|
Spring中使用
Spring框架下使用@Component即可实现单例,不需要刻意去实现,如果需要懒加载再加上@Lazy,即实现了Bean对象在第一次使用时才创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component;
@Component @Lazy public class MySpringTestBean {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public MySpringTestBean() { logger.info("执行构造函数"); }
public void sayHello() { logger.info("hello world"); } }
|
测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest class MySpringTestBeanTest {
@Autowired MySpringTestBean mySpringTestBean;
@Test public void mySpringTestBeanTest() { mySpringTestBean.sayHello(); }
}
|
常用注解的默认实例化方式:
- @Component默认单例
- @Bean默认单例
- @Repository默认单例
- @Service默认单例
- @Controller默认多例
如果想声明成多例对象可以使用@Scope(“prototype”)
另外如果需要保证每个线程中都只有一个的话,借助ThreadLocal:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class ThreadSingleton { private static final ThreadLocal<ThreadSingleton> THREAD_LOCAL = ThreadLocal.withInitial(ThreadSingleton::new); public static ThreadSingleton getInstance() { ThreadSingleton threadSingleton = THREAD_LOCAL.get(); if(threadSingleton == null) { threadSingleton = new ThreadSingleton(); THREAD_LOCAL.set(threadSingleton); } return threadSingleton; } private ThreadSingleton() {} }
|