Spring中单例和多例的深入理解

Spring中单例和多例的深入理解

在软件开发中,对象的生命周期管理非常重要。Spring作为一个非常流行的Java开发框架,提供了两种常用的对象管理方式:单例(Singleton)和多例(Prototype)。本文将详细讲解Spring中单例和多例的深入理解。

单例模式

单例模式是一种常用的创建模式,它保证一个类只有一个实例,并提供一个访问它的全局访问点。在Spring中,单例模式是默认的bean Scope(作用域),即当在配置文件中没有指定其它Scope时,Spring就会默认使用Singleton。

如何使用Singleton

在Spring中,我们可以通过以下几种方式来使用Singleton:

  1. 在xml配置文件中,不指定bean的Scope,不声明任何注解,默认就是Singleton。
<bean id="userService" class="com.example.UserService"/>
  1. 在xml配置文件中,显式地使用Singleton。
<bean id="userService" class="com.example.UserService" scope="singleton"/>
  1. 在Java类中使用注解声明Singleton。
@Service
public class UserService {
    // ...
}

Singleton的特点

单例模式的特点:

  1. 每个bean的定义只有一个对象实例。
  2. Spring容器初始化时就会创建对象实例,并在容器关闭时销毁。
  3. 所有该类型的依赖 bean 都共享同一个实例对象。

Singleton的使用场景

在大部分情况下我们都应该使用Singleton,因为Singleton具有以下优点:

  1. 节省资源:每个实例都需要占用内存,并且创建和销毁也需要时间成本。
  2. 具有共享功能:在整个应用中,某些对象具有通用的特性,可以使用Singleton实现共享。

在Spring中,单例模式应该是在以下两种情况下使用:

  1. 对象占用较少内存并且需要重复使用。
  2. 某些资源是不可复制的,例如数据库连接和 Socket 连接等。

多例模式

多例模式是指每次获取实例时都会创建一个新的实例,不同于单例模式,它不保证同一类的对象只存在一个实例。在Spring中,多例模式需要显示地声明Scope为prototype。

如何使用Prototype

在Spring中,我们可以通过以下几种方式来使用Prototype:

  1. 在xml配置文件中显式地使用Prototype。
<bean id="userService" class="com.example.UserService" scope="prototype"/>
  1. 在Java类中使用注解声明Prototype。
@Component
@Scope("prototype")
public class UserService {
    // ...
}

Prototype的特点

多例模式的特点:

  1. 每次获取依赖时都会创建一个新的对象实例。
  2. Spring容器在初始化时不会创建对象实例,只有当你主动请求或注入它的时候才会创建新的实例。
  3. 由于创建和销毁实例的时间成本,多例模式的性能较差。

Prototype的使用场景

在以下情况下我们应该使用Prototype:

  1. 对象状态的话是不可共享的时候,例如一个计数器对象,每个对象状态是独立的,不能共享同一个对象。
  2. 对象状态的更改频率很高时,例如Session对象。

示例

下面举两个例子分别说明单例和多例的使用场景。

示例1:单例

假设我们有一个计数器类,每次执行加一操作。

public class Counter {
    private int count;

    public void add() {
        count++;
    }

    public int getCount() {
        return count;
    }
}

这个计数器类的状态很简单,只有一个数字类型的count字段。每次调用add方法都会将count加1。如果我们使用单例模式创建这个计数器,那么所有的方法调用都会使用同一个计数器对象。这是符合业务逻辑的:

public class UserService {
    @Autowired
    private Counter counter;

    public void add() {
        counter.add();
    }

    public int getCount() {
        return counter.getCount();
    }
}

上述代码中,我们使用@Autowired注入一个名为counter的计数器实例,它是单例的。在UserService中的add方法中,我们调用了counter实例的add方法。在getCount方法中,我们返回了counter实例的count值。如果有多个UserService实例,它们调用的都是同一个Counter实例。

示例2:多例

假设我们有一个随机数生成器类,每次执行时都能够生成一个不同的随机数。

public class RandomNumberGenerator {
    private int random = new Random().nextInt();

    public int getRandom() {
        return random;
    }
}

这个随机数生成器的状态是动态的,每次调用getRandom方法都可能返回不同的数字,所以我们需要使用多例模式。如果我们使用多例模式创建这个随机数生成器,那么每次方法调用都会使用一个新的随机数生成器。这是符合业务逻辑的:

public class UserService {
    private RandomNumberGenerator generator;

    public int getRandomNumber() {
        generator = new RandomNumberGenerator();
        return generator.getRandom();
    }
}

上述代码中,我们在每次需要生成随机数时重新创建一个RandomNumberGenerator实例。这样,如果有多个UserService实例,它们调用的都是不同的RandomNumberGenerator实例。

总结

单例和多例是Spring中两种常用的对象管理方式,应用场景不同。在使用时,我们需要根据对象的特点来选择合适的Scope。在大部分情况下,应该使用单例模式,因为它具有节省资源、具有共享功能的特点。只有在特定的业务场景下,才应该使用多例模式。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring中单例和多例的深入理解 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • 通过实践了解如何处理Java异常

    处理 Java 异常的攻略如下: 异常概述 Java 异常能够帮助我们处理程序运行时的错误或者问题,同时在出现异常情况下,也可以给用户展示错误信息,方便问题的排查与解决。Java 中的异常主要分为两类:已检查异常(Checked Exception)和运行时异常(Runtime Exception)。已检查异常通常是在方法声明中显式申明的,需要在方法调用处进…

    Java 2023年5月26日
    00
  • SpringBoot环境Druid数据源使用及特点

    下面是关于SpringBoot环境中Druid数据源使用及特点的详细攻略。 1. 什么是Druid Druid是阿里巴巴开源的数据连接池。相比于传统的连接池,Druid具有更好的扩展性和稳定性。同时,它还提供了多种功能强大的监控和统计特性,如监控SQL执行情况、打印SQL慢日志等。 2. 如何在SpringBoot中使用Druid数据源 2.1 引入依赖 首…

    Java 2023年5月20日
    00
  • 详解JAVA 反射机制

    详解JAVA 反射机制 什么是反射机制 反射机制是 Java 语言提供的一种能力,它允许本来在编译期无法访问的类的内部信息,在程序运行期可以获取到。使用反射机制,我们可以在程序运行时动态地获取类型信息、构造对象、访问字段和方法等。 反射机制的应用场景 设计灵活,可扩展性好。比如很多插件式的框架,允许用户开发自定义的模块,但是这些模块编译时是不确定的,只有在程…

    Java 2023年5月20日
    00
  • spring事务传播的Propagation.REQUIRES_NEW以及NEVER MANDATORY验证,及其失效的诡异问题

    NEVER 不使用事务,如果当前事务存在,则抛出异常 验证: @Service public class PrService { @Autowired PrDao dao; @Transactional public void savea() { dao.a();//保存第一条数据 saveb(); } @Transactional(propagation …

    Java 2023年5月8日
    00
  • 详解MyBatis工作原理

    详解MyBatis工作原理 MyBatis是一个流行的Java持久层框架,它通过将Java对象映射到数据库记录来操作数据库。本文将详细讲解MyBatis运作的原理。 MyBatis的三大组件 MyBatis框架主要由三个核心组件组成: SqlSessionFactoryBuilder:用于创建SqlSessionFactory。 SqlSessionFact…

    Java 2023年5月20日
    00
  • java中的取整与四舍五入方法实例

    Java中的取整与四舍五入方法实例 在Java中,常用的取整和四舍五入方法是Math.floor、Math.ceil、Math.round,本文将详细介绍这三个方法的用法和示例说明。 Math.floor Math.floor是向下取整,表示得到的最大整数。它的用法为:Math.floor(x),其中x为一个double类型的数。具体实现为删去小数部分,只保…

    Java 2023年5月26日
    00
  • XSS测试语句大全

    首先,需要了解XSS攻击的定义和常见形式,XSS攻击是一种Web应用程序漏洞攻击,攻击者将恶意的脚本代码注入到Web页面中。常见的XSS攻击形式包括反射型XSS、存储型XSS和DOM型XSS等。 接着,根据不同的XSS攻击类型选择合适的测试语句。以下是一些常用的测试语句: 基本测试语句: <script>alert(‘XSS’)</scri…

    Java 2023年6月15日
    00
  • SpringBoot+jpa配置如何根据实体类自动创建表

    SpringBoot可以通过JPA(Java Persistence API)来进行数据库操作。在使用JPA时,我们可以让它自动创建数据表,而不需要手动创建。 下面是Spring Boot与JPA自动生成数据表的配置方法: 配置数据源 首先,在application.properties中配置数据源: spring.datasource.url=jdbc:m…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部