Spring框架中的单例模式


前言

提示:详细内容可观看黑马程序员教程

基本概念:设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

黑马程序员教程对设计模式的叙述:一个问题通常有 N 种解法,其中肯定有一种解法是最优的,这个最优的解法被总结出来,称之为设计模式

本篇文章记录学习spring框架中所涉及的23种设计模式之一的单例模式笔记


提示:以下是本篇文章正文内容,下面案例仅供参考

一、单例模式的应用

既然设计模式是解决一个(类)问题的最优解,那么单例模式主要解决什么问题呢?也就是说它的应用场景是什么?

单例模式是确保一个类只能实例化一个对象,也就是说,这个对象在内存中只有一份。

接下来通过java代码来做个单例模式的DEMO

(一)Java实现单例模式

新建一个Maven项目,使用Maven项目是为了方便我们引入一些依赖,比如后续引入Spring框架的基础依赖和简化代码的依赖lombok

(二)引入lombok依赖

 <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.34</version>
 </dependency>

(三)实体类

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

// lombok 提供的注解,帮组我们实现set、get和toString方法
@Getter
@Setter
@ToString
public class Student {

    private Long sId;

    private String sName;

    private String sSex;

    private String sClass;
    
}

(四)在测试类编写测试代码

在测试类中,我们 new 两个 Student 对象 studentOne 和 studentTwo ,显然是两个不同对象,使用 == 比较两个对象是否相等,结果是false

 @Test
 public void test()
  {
      Student studentOne = new Student();
      studentOne.setSId(1L);
      studentOne.setSName("项羽");
      studentOne.setSSex("男");
      studentOne.setSClass("计科17甲");
      System.out.println(studentOne);

      Student studentTwo = new Student();
      studentTwo.setSId(2L);
      studentTwo.setSName("虞姬");
      studentTwo.setSSex("女");
      studentTwo.setSClass("计科17甲");
      System.out.println(studentTwo);

      System.out.println(studentOne == studentTwo);
  }

输出结果:
Student(sId=1, sName=项羽, sSex=, sClass=计科17)
Student(sId=2, sName=虞姬, sSex=, sClass=计科17)
false

接下来,我们将 Student类 中的构造方法(无参构造)私有化,定义一个类变量记住类的一个对象,再通过类方法来返回这个对象,这样就实现了单例模式

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

// lombok 提供的注解,帮组我们实现set、get和toString方法
@Getter
@Setter
@ToString
public class Student {

    private Long sId;

    private String sName;

    private String sSex;

    private String sClass;

     //私有化构造器
    private Student(){
    }
    
    // 定义一个类变量 student 来存储对象
    private static final Student student = new Student();

    // 定义一个静态方法,返回 student 变量
    public static Student getObject(){
        return student;
    }
    
}

我们再编写一个测试类,输出结果是true。说明Student类在内存中只有一个实例对象。可以将Student类中的 @ToString 注解去掉,查看输出结果,很明显结果是相同的

 @Test
 public void test()
  {
      Student student1 = Student.getObject();
      student1.setSId(1L);
      student1.setSName("张三");
      student1.setSSex("男");
      student1.setSClass("计科17甲");
      System.out.println(student1);

      Student student2 = Student.getObject();
      student2.setSId(2L);
      student2.setSName("李四");
      student2.setSSex("男");
      student2.setSClass("计科17甲");
      System.out.println(student2);

      System.out.println(student1 == student2);
  }
输出结果:
Student(sId=1, sName=张三, sSex=, sClass=计科17)
Student(sId=2, sName=李四, sSex=, sClass=计科17)
true

去掉注解  @ToString 输出结果:
com.personal.demo.entity.Student@38cccef
com.personal.demo.entity.Student@38cccef
true

二、Spring中的单例模式

(一)引入spring基础依赖

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context</artifactId>
   <version>6.1.5</version>
</dependency>

(二)添加spring配置文件

在resources目录下添加spring的配置文件,配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--
       bean标签: 配置一个Bean对象,将对象交由IOC容器管理
       id: 对象在IOC容器中的唯一标识
       class: 对象的全类名, 对象在IOC容器中的类型
    -->
    <bean id = "Student" class="com.personal.demo.entity.Student"></bean>
</beans>

在这里插入图片描述

(三)编写测试类

通过加载我们配置文件来获取一个 ioc 容器,在从ioc容器中根据 bean 的id 获取实例对象

@Test
public void testSpring(){
     ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
     Student studentOne =(Student) ioc.getBean("Student");
     studentOne.setSId(1L);
     studentOne.setSName("张三");
     studentOne.setSSex("男");
     studentOne.setSClass("计科17甲");
     System.out.println(studentOne);

     Student studentTwo =(Student) ioc.getBean("Student");
     studentTwo.setSId(2L);
     studentTwo.setSName("李四");
     studentTwo.setSSex("男");
     studentTwo.setSClass("计科17甲");
     System.out.println(studentTwo);

     System.out.println(studentOne == studentTwo);
 }
输出结果:
Student(sId=1, sName=张三, sSex=, sClass=计科17)
Student(sId=2, sName=李四, sSex=, sClass=计科17)
true

从上述结果我们发现 studentOne 和 studentTwo 是相等的,说明Spring框架中 ioc创建实例对象时,默认使用是单例模式。当然我们可以在配置文件中通过设置 scope 属性来设置为多实例的

在这里插入图片描述
再次输出结果就是 false

在这里插入图片描述


总结

写这些文章主要目的是想将知识一点点融会贯通,知其然知其所以然才是自我提升的根本(个人觉得八股文有点难背)。从基本的 java语言出发,到框架中所使用的设计模式,自己不但要如何验证框架是否使用了设计模式,还能手搓简单的设计模式,并且还需要学会一些框架配置:比如将单例设置成多例,以及为什么Spring要使用单例模式呢等等

  • 21
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring框架单例模式是一种常见的设计模式,用于确保在整个应用生命周期只有一个实例存在。虽然Spring本身已经提供了基于Bean的单例模式支持,但如果你想要手动实现一个简单的Spring风格的单例,你可以按照以下步骤: 1. **静态工厂方法**: - 创建一个私有的构造函数,仅允许通过工厂方法创建实例。 ```java public class Singleton { private static volatile Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } } ``` 2. **双重校验锁定(DCL)**: - 使用双重检查锁定优化,避免了同步块导致的性能开销。 ```java public class SingletonDCL { private volatile static Singleton instance; private SingletonDCL() {} public static Singleton getInstance() { if (instance == null) { instance = new SingletonDCL(); } return instance; } } ``` 3. **枚举类型单例**: - 使用枚举类型保证线程安全且易于理解。 ```java public enum SingletonEnum { INSTANCE; private SingletonEnum() {} } ``` 4. **单例模式Spring结合**: - 在Spring,`@Singleton`注解或者在配置文件使用`singleton`属性可以自动实现单例。 相关问题-- 1. 在Spring,如何通过XML配置实现单例模式? 2. Spring的`@Singleton`注解是如何工作的? 3. 为什么要使用枚举类型实现单例?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值