当前位置: 首页 > news >正文

1.单例模式有哪几种常见的实现方式?

目录

1.问题

2.知识储备

(1).SpringBoot的Bean注册和DI(依赖注入)

[1].SpringBoot的Bean注册

{1}.基于@Component及其衍生注解

{2}.基于@Bean注解

[2].SpringBoot的DI

{1}.什么是DI

{2}.常见的DI注解

(2).单例模式

[1].什么是单例模式

[2].单例模式的常见实现方式

{1}.饿汉式(立即加载)

{2}.懒汉式(延迟加载,线程不安全)

{3}.懒汉式(线程安全,synchronized修饰方法)

{4}.双重检查锁定(DCL,Double-Checked Locking)

3.分析

4.解决方案:

(1).基于饿汉式实现单例模式:

(2).基于线程不安全懒汉式实现单例模式:

(3).基于线程安全懒汉式实现单例模式:

(4).基于DCL实现单例模式

5.小结


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(数据层)

以下是一段使用了衍生注解的示例代码:

// 业务层Bean(@Service是@Component的衍生注解)
@Service
public class UserService {// 业务逻辑...
}// 控制层Bean
@Controller
public class UserController {// 业务逻辑...
}
{2}.基于@Bean注解

通过在配置类中使用@Bean注解,手动定义Bean的创建逻辑,适合注册第三方类(如工具类、框架组件)或者需要自定义实例化过程的Bean

使用方式:在被@Configuration标识的配置类中,定义返回值为目标类型的方法,并添加@Bean注解

以下是一段使用了@Bean注解的示例代码:

// 配置类(标识为配置类)
@Configuration
public class AppConfig {// 注册一个RestTemplate实例到容器@Beanpublic 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的代码:

@Service
public class UserService {// 字段注入@Autowired@Qualifier("userRepositoryImpl") // 配合@Qualifier指定Bean名称(解决同类型冲突)private UserRepository userRepo;// 构造器注入(单构造器时可省略@Autowired)@Autowiredpublic UserService(UserRepository userRepo) {this.userRepo = userRepo;}// Setter方法注入@Autowiredpublic void setUserRepo(UserRepository userRepo) {this.userRepo = userRepo;}
}

@Resource:先根据名找,在根据类寻找

以下是一段基于@Resource完成DI的代码:

@Service
public class OrderService {// 按字段名"paymentService"匹配Bean(若不存在则按类型)@Resourceprivate PaymentService paymentService;// 通过name属性指定Bean名称(优先按名称匹配)@Resource(name = "alipayService")public void setPaymentService(PaymentService paymentService) {this.paymentService = paymentService;}
}

(2).单例模式

[1].什么是单例模式

单例模式是一种常用的设计模式,其核心是保证一个类在整个应用中只有一个实例,并提供一个全局访问点。

[2].单例模式的常见实现方式

常见的实现方式有以下几种,各有特点和使用场景

{1}.饿汉式(立即加载)

原理:在类加载时就创建实例,确保线程安全,但是可能提前占用资源

特点:简单直观,天然线程安全(因为类加载过程是线程安全的),但是无论是否使用都会创建实例,可能造成资源浪费。

以下是饿汉式的一段示例代码:

public class A{private static final A INSTANCE= new A();private A(){}public static A getInstance(){return INSTANCE;}
}
{2}.懒汉式(延迟加载,线程不安全)

原理:在首次调用getInstance时才创建实例,实现延迟加载,但多线程环境下可能创建多个实例

特点:节省资源,线程不安全,不适合多线程场景

以下是懒汉式的一段示例代码:

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关键字,强制多线程排队访问,保证线程安全。

特点:为了解决懒汉式的线程安全问题,但是每次调用方法都要加锁,性能开销比较大。

以下是懒汉式(线程安全)的一段示例代码:

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的一段示例代码:

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).基于饿汉式实现单例模式:

public class A{private static final A INSTANCE= new A();private A(){}public static A getInstance(){return INSTANCE;}
}

(2).基于线程不安全懒汉式实现单例模式:

public class B{private static B INSTANCE;private B(){}public static  B getInstance(){if(INSTANCE==null){INSTANCE = new B();}return INSTANCE;}
}

(3).基于线程安全懒汉式实现单例模式:

public class C{private static C instance ;private C(){}public static synchronized C getInstance(){if(instace==null){instance = new C();}return instance }
}

(4).基于DCL实现单例模式

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.你学会了什么是单例模式,以及四种实现单例模式的方式

注:如果发现文章有错别字、理解错误、语义错误等问题,请联系作者修改。大家一起努力才能创建更好的生态!

http://www.dtcms.com/a/465697.html

相关文章:

  • 安蓉建设总公司网站服装设计官网
  • PyTorch的安装与使用
  • 解决办法:win11连接蓝牙的时候每次连接都是100%的音量
  • foundry创建项目
  • 网站整体地图怎么做招设计师在哪里找
  • C#学习小笔记(完整版)—— Patience
  • 解决MySQL8.0及其更高版本的两个安全问题——及其配置MySQL实现SSL/TLS加密通信、caching_sha2_password通信
  • Node.js性能优化:从事件循环到内存管理
  • Node.js核心模块:fs、path与http详解
  • 企业级UDP文件传输工具如何重塑数据交换格局
  • 在JavaScript / Node.js中,Web服务器参数处理与编码指南
  • 佛山新网站建设服务网站中文域名好吗
  • Python打包成exe(windows)或者app(mac)
  • 网站开发都做什么小程序电商系统开发
  • 《电子商务网站开发实训》总结抖音代运营 广州
  • 《MySQL索引优化实战从B+树原理到慢查询性能提升》
  • 深入理解MySQL索引原理B+树如何提升查询性能
  • Spring Boot 整合 Thymeleaf 生成 HTML 页面教学
  • 深入解析MySQL索引优化从B+树原理到实战性能调优
  • MySQL索引优化的艺术从B+树原理到慢查询性能提升实践
  • 解密MySQL索引优化从B+树原理到实战性能提升
  • {title:深入解析MySQL索引优化从B+树原理到实战调优策略}
  • 深入解析MySQL索引优化从B+树原理到实战避坑指南
  • 古色古香网站模板加盟网络营销推广公司
  • 北京网站建设推荐q479185700上快给手机做网站的公司
  • wordpress建站视频静态网站可以申请域名吗
  • 3. 3层神经网络的实现
  • 【论文阅读 | TCSVT 2024 | CCAFusion: 用于红外与可见光图像融合的跨模态坐标注意力网络】
  • 中小企业网站建设客户需求调查问卷基于拍卖的拍卖网站开发
  • 百度收录提交接口谷歌优化的网络公司