目录
(1).SpringBoot的Bean注册和DI(依赖注入)
{3}.懒汉式(线程安全,synchronized修饰方法)
[{4}.双重检查锁定(DCL,Double-Checked Locking)](#{4}.双重检查锁定(DCL,Double-Checked Locking))
1.问题
小编有在写工具项目,是一个纯javase项目,没有使用springboot等框架 。因此遇到了一个问题,我发现有的类我需要重复的使用,但是在不同的类或者方法中,导致每次都需要进行创建,这样性能是比较差的 。以往在springboot中小编都是直接通过@Component注册,然后通过@Autowired注入的。在这里由于是Javase原生项目无法使用这种方式。小编思考了一下,可以使用单例模式来解决我这个需求。
2.知识储备
想要理解和解决这个问题,一些知识储备是必不可少的。
(1).SpringBoot的Bean注册和DI(依赖注入)
需要注意的是SpringBoot的Bean注册和DI,当然是需要依赖SpringBoot环境的。

[1].SpringBoot的Bean注册
众所周知,SpringBoot的一个很显著的特点,就是可以把类交给SpringBoot来管理,而不需要手动管理。那么Bean注入就是这个特点的前提,只有通过Bean注入明确把哪些类交给SpringBoot管理,SpringBoot才能帮我们管理
Bean注册的常见方式:
{1}.基于@Component及其衍生注解
这是最常用的方式了,通过注解标识类,让Spring自动扫描并注册Bean
@Component
衍生注解:@Controller(控制层)、@Service(服务层)、@Repository(数据层)
以下是一段使用了衍生注解的示例代码:
java
// 业务层Bean(@Service是@Component的衍生注解)
@Service
public class UserService {
// 业务逻辑...
}
// 控制层Bean
@Controller
public class UserController {
// 业务逻辑...
}
{2}.基于@Bean注解
通过在配置类中使用@Bean注解,手动定义Bean的创建逻辑,适合注册第三方类(如工具类、框架组件)或者需要自定义实例化过程的Bean
使用方式:在被@Configuration标识的配置类中,定义返回值为目标类型的方法,并添加@Bean注解
以下是一段使用了@Bean注解的示例代码:
java
// 配置类(标识为配置类)
@Configuration
public class AppConfig {
// 注册一个RestTemplate实例到容器
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
// 自定义配置(如添加拦截器、设置超时时间等)
restTemplate.getInterceptors().add(new LoggingInterceptor());
return restTemplate;
}
// 注册一个自定义工具类Bean
@Bean(name = "dateUtils") // 可通过name指定Bean名称(默认是方法名)
public DateUtils createDateUtils() {
return new DateUtils();
}
}
[2].SpringBoot的DI
{1}.什么是DI
DI(Dependecy Injection)依赖注入,是Spring框架中实现控制反转(IOC)的核心思想。其核心思想是:让 Spring 容器负责将一个对象(依赖)自动 "注入" 到另一个依赖它的对象中,而不是由对象自己创建或查找依赖。
SpringBoot三大特性:AOP、IOC、DI
{2}.常见的DI注解
@Autowired:Spring最常用的DI注解,先根据类寻找,然后再根据名寻找
以下是一段基于@Autowired完成DI的代码:
java
@Service
public class UserService {
// 字段注入
@Autowired
@Qualifier("userRepositoryImpl") // 配合@Qualifier指定Bean名称(解决同类型冲突)
private UserRepository userRepo;
// 构造器注入(单构造器时可省略@Autowired)
@Autowired
public UserService(UserRepository userRepo) {
this.userRepo = userRepo;
}
// Setter方法注入
@Autowired
public void setUserRepo(UserRepository userRepo) {
this.userRepo = userRepo;
}
}
@Resource:先根据名找,在根据类寻找
以下是一段**基于@**Resource完成DI的代码:
java
@Service
public class OrderService {
// 按字段名"paymentService"匹配Bean(若不存在则按类型)
@Resource
private PaymentService paymentService;
// 通过name属性指定Bean名称(优先按名称匹配)
@Resource(name = "alipayService")
public void setPaymentService(PaymentService paymentService) {
this.paymentService = paymentService;
}
}
(2).单例模式
[1].什么是单例模式
单例模式是一种常用的设计模式,其核心是保证一个类在整个应用中只有一个实例,并提供一个全局访问点。

[2].单例模式的常见实现方式
常见的实现方式有以下几种,各有特点和使用场景
{1}.饿汉式(立即加载)
原理:在类加载时就创建实例,确保线程安全,但是可能提前占用资源
特点:简单直观,天然线程安全(因为类加载过程是线程安全的),但是无论是否使用都会创建实例,可能造成资源浪费。
以下是饿汉式的一段示例代码:
java
public class A{
private static final A INSTANCE= new A();
private A(){}
public static A getInstance(){
return INSTANCE;
}
}
{2}.懒汉式(延迟加载,线程不安全)
原理:在首次调用getInstance时才创建实例,实现延迟加载,但多线程环境下可能创建多个实例
特点:节省资源,线程不安全,不适合多线程场景
以下是懒汉式的一段示例代码:
java
public class B{
private static B INSTANCE;
private B(){}
public static B getInstance(){
if(INSTANCE==null){
INSTANCE = new B();
}
return INSTANCE;
}
}
{3}.懒汉式(线程安全,synchronized修饰方法)
原理:在getInstace()方法上添加synchroninzed关键字,强制多线程排队访问,保证线程安全。
特点:为了解决懒汉式的线程安全问题,但是每次调用方法都要加锁,性能开销比较大。
以下**是懒汉式(线程安全)**的一段示例代码:
java
public class C{
private static C instance ;
private C(){}
public static synchronized C getInstance(){
if(instace==null){
instance = new C();
}
return instance
}
}
{4}.双重检查锁定(DCL,Double-Checked Locking)
原理:结合懒加载和锁机制,仅在实例未创建时加锁,同时通过volatile关键字防止指令重排,兼顾性能和线程安全
特点:懒加载、线程安全、性能好,是实际开发中常用的方式
以下是DCL的一段示例代码:
java
public class D{
private static volatile D instace;
private D(){}
public static D getInstace(){
// 第一次检查:未创建时才进入同步块(提高性能)
if(instance==null){
synchronized(D.class){
// 第二次检查:防止多线程同时进入同步块后重复创建
if(instance==null){
instace = new D();
}
}
}
return instance;
}
}
3.分析
之所以需要手写单例模式,主要还是因为是基于javase,如果是基于springboot其实大多数情况是不需要我们手写的。大家一定不要重复造轮子。写这个文章是为了让大家能在无法借助springboot时来实现单例的!
4.解决方案:
(1).基于饿汉式实现单例模式:
java
public class A{
private static final A INSTANCE= new A();
private A(){}
public static A getInstance(){
return INSTANCE;
}
}
(2).基于线程不安全懒汉式实现单例模式:
java
public class B{
private static B INSTANCE;
private B(){}
public static B getInstance(){
if(INSTANCE==null){
INSTANCE = new B();
}
return INSTANCE;
}
}
(3).基于线程安全懒汉式实现单例模式:
java
public class C{
private static C instance ;
private C(){}
public static synchronized C getInstance(){
if(instace==null){
instance = new C();
}
return instance
}
}
(4).基于DCL实现单例模式
java
public class D{
private static volatile D instace;
private D(){}
public static D getInstace(){
// 第一次检查:未创建时才进入同步块(提高性能)
if(instance==null){
synchronized(D.class){
// 第二次检查:防止多线程同时进入同步块后重复创建
if(instance==null){
instace = new D();
}
}
}
return instance;
}
}
5.小结
什么你都看到小结了?你难道就是传说中的"勤奋者"?
在本文,
1.你学会了SpringBoot的Bean注册和BI
2.你学会了什么是单例模式,以及四种实现单例模式的方式
注:如果发现文章有错别字、理解错误、语义错误等问题,请联系作者修改。大家一起努力才能创建更好的生态!