掌握 Spring IoC 容器与 Bean 作用域:详解 singleton 与 prototype 的使用与配置

小万哥
• 阅读 1024

在您的应用程序中,由 Spring IoC 容器管理的形成其核心的对象被称为 "bean"。一个 bean 是由 Spring IoC 容器实例化、组装和管理的对象

这些 bean 是通过您提供给容器的配置元数据创建的。Bean 定义包含了所谓的配置元数据,容器需要了解以下内容:

  • 如何创建一个 bean
  • Bean 的生命周期详细信息
  • Bean 的依赖关系

上述所有的配置元数据都转化为每个 bean 定义的以下属性集合。

序号 属性和描述
1 class
这是必填属性,指定要用于创建 beanbean 类。
2 name
此属性唯一地指定 bean 标识符。在基于 XML 的配置元数据中,您可以使用 id 和/或 name 属性来指定 bean 标识符。
3 scope
此属性指定从特定 bean 定义创建的对象的范围
4 constructor-arg
这用于注入依赖项
5 properties
这用于注入依赖项
6 autowiring mode
这用于注入依赖项
7 lazy-initialization mode
延迟初始化的 bean 告诉 IoC 容器在首次请求时创建 bean 实例,而不是在启动时创建。
8 initialization method
在容器设置了 bean 的所有必需属性之后,要调用的回调函数
9 destruction method
在包含 bean 的容器销毁时要使用的回调函数

Spring 配置元数据

Spring IoC 容器与实际编写配置元数据的格式完全解耦。以下是向 Spring 容器提供配置元数据的三种重要方法:

  • 基于 XML 的配置文件。
  • 基于注解的配置。
  • 基于 Java 的配置。

您已经看到了如何将基于 XML 的配置元数据提供给容器,但让我们看一下包含不同 bean 定义的 XML 配置文件的另一个示例,包括延迟初始化、初始化方法和销毁方法。

<?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-3.0.xsd">

   <!-- 一个简单的 `bean` 定义 -->
   <bean id = "..." class = "...">
      <!-- 此处是该 `bean` 的协作者和配置 -->
   </bean>

   <!-- 启用延迟初始化的 `bean` 定义 -->
   <bean id = "..." class = "..." lazy-init = "true">
      <!-- 此处是该 `bean` 的协作者和配置 -->
   </bean>

   <!-- 具有初始化方法的 `bean` 定义 -->
   <bean id = "..." class = "..." init-method = "...">
      <!-- 此处是该 `bean` 的协作者和配置 -->
   </bean>

   <!-- 具有销毁方法的 `bean` 定义 -->
   <bean id = "..." class = "..." destroy-method = "...">
      <!-- 此处是该 `bean` 的协作者和配置 -->
   </bean>

   <!-- 更多的 `bean` 定义在此处 -->

Spring 中的 Bean 作用域

在定义 <bean> 时,您可以选择为该 bean 声明一个作用域。例如,要强制 Spring 每次需要时生成新的 bean 实例,您应该将 bean 的作用域属性声明为 prototype。类似地,如果您希望 Spring 每次需要时返回相同的 bean 实例,您应该将 bean 的作用域属性声明为 singleton

Spring 框架支持以下五种作用域,其中三种仅在使用与 Web 相关的 ApplicationContext 时才可用。

序号 作用域 & 描述
1 singleton
bean 定义的作用域限制为 Spring IoC 容器中的单个实例(默认)。
2 prototype
将单个 bean 定义的作用域限制为具有任意数量的对象实例。
3 request
bean 定义的作用域限制为 HTTP 请求。仅在具有与 Web 相关的 Spring ApplicationContext 的情况下有效。
4 session
bean 定义的作用域限制为 HTTP 会话。仅在具有与 Web 相关的 Spring ApplicationContext 的情况下有效。
5 global-session
bean 定义的作用域限制为全局 HTTP 会话。仅在具有与 Web 相关的 Spring ApplicationContext 的情况下有效。

当讨论与

Web 相关的 Spring ApplicationContext 时,将讨论其他三种作用域。

单例作用域(singleton

如果将作用域设置为 singletonSpring IoC 容器将创建一个对象的确切实例,该实例由 bean 定义定义。此单个实例存储在此类单例 bean 的缓存中,对于该命名 bean 的所有后续请求和引用都会返回缓存的对象。

默认作用域始终是 singleton。但是,当您需要一个且仅一个 bean 实例时,您可以在 bean 配置文件中将作用域属性设置为 singleton,如下所示:

<!-- 具有 `singleton` 作用域的 `bean` 定义 -->
<bean id="..." class="..." scope="singleton">
   <!-- 此处放置此 `bean` 的协作者和配置 -->

示例

假设您已经准备好 Eclipse IDE,并采取以下步骤创建 Spring 应用程序:

步骤

  1. 创建一个名为 SpringExample 的项目,在创建的项目中的 src 文件夹下创建一个名为 com.tutorialspoint 的包
  2. 使用"Add External JARs"选项添加所需的 Spring
  3. com.tutorialspoint 包下创建 JavaHelloWorldMainApp
  4. src 文件夹下创建 Beans 配置文件 Beans.xml
  5. 最后一步是创建所有 Java 文件和 Bean 配置文件的内容,并按以下说明运行应用程序。

以下是 HelloWorld.java 文件的内容:

package com.tutorialspoint;

public class HelloWorld {
   private String message;

   public void setMessage(String message){
      this.message  = message;
   }
   public void getMessage(){
      System.out.println("Your Message : " + message);
   }
}

以下是 MainApp.java 文件的内容:

package com.tutorialspoint;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
   public static void main(String[] args) {
      ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
      HelloWorld objA = (HelloWorld) context.getBean("helloWorld");

      objA.setMessage("I'm object A");
      objA.getMessage();

      HelloWorld objB = (HelloWorld) context.getBean("helloWorld");
      objB.getMessage();
   }
}

以下是 singleton 作用域所需的 Beans.xml 配置文件的内容:

<?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-3.0.xsd">

   <bean id="helloWorld" class="com.tutorialspoint.HelloWorld" scope="singleton">
   </bean>

</beans>

当您完成创建源代码和 bean 配置文件后,让我们运行应用程序。如果您的应用程序一切正常,它将打印以下消息:

Your Message : I'm object A
Your Message : I'm object A

原型作用域(prototype

如果将作用域设置为 prototypeSpring IoC 容器将在每次请求特定 bean 时创建该对象的新 bean 实例。通常,对于所有有状态的 bean,使用 prototype 作用域,对于无状态的 bean,使用 singleton 作用域。

要定义原型作用域,您可以在 bean 配置文件中将作用域属性设置为 prototype,如下所示:

<!-- 具有 `prototype` 作用域的 `bean` 定义 -->
<bean id="..." class="..." scope="prototype">
   <!-- 此处放置此 `bean` 的协作者和配置 -->
</bean>

示例

假设您已经准备好 Eclipse IDE,并采取以下步骤创建 Spring 应用程序:

步骤

  1. 创建一个名为 SpringExample 的项目,在创建的项目中的 src 文件夹下创建一个名为 com.tutorialspoint 的包
  2. 使用"Add External JARs"选项添加所需的 Spring
  3. com.tutorialspoint 包下创建 JavaHelloWorldMainApp
  4. src 文件夹下创建 Beans 配置文件 Beans.xml
  5. 最后一步是创建所有 Java 文件和 Bean 配置文件的内容,并按以下说明运行应用程序。

以下是 HelloWorld.java 文件的内容:

package com.tutorialspoint;

public class HelloWorld {
   private String message;

   public void setMessage(String message){
      this.message  = message;
   }
   public void getMessage(){
      System.out.println("Your Message : " + message);
   }
}

以下是 MainApp.java 文件的内容:

package com.tutorialspoint;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
   public static void main(String[] args) {
      ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
      HelloWorld objA = (HelloWorld) context.getBean("helloWorld");

      objA.setMessage("I'm object A");
      objA.getMessage();

      HelloWorld objB = (HelloWorld) context.getBean("helloWorld");
      objB.getMessage();
   }
}

以下是 prototype 作用域所需的 Beans.xml 配置文件的内容:

<?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-3.0.xsd">

   <bean id="helloWorld" class="com.tutorialspoint.HelloWorld" scope="prototype">
   </bean>

</beans>

当您完成创建源代码和bean配置文件后,让我们运行应用程序。如果您的应用程序一切正常,它将打印以下消息:

Your Message : I'm object A
Your Message : I'm object A

最后

为了方便其他设备和平台的小伙伴观看往期文章:

微信公众号搜索:Let us Coding,关注后即可获取最新文章推送

看完如果觉得有帮助,欢迎 点赞、收藏、关注

点赞
收藏
评论区
推荐文章
Easter79 Easter79
2年前
SpringIOC官方文档解读
IoC容器本章介绍了Spring的控制反转(IoC)容器。1.1。SpringIoC容器和Bean简介本章介绍了反转控制(IoC)原则的Spring框架实现。IoC也称为依赖注入(DI)。在此过程中,对象可以通过①构造函数参数(),②工厂方法的参数③或在构造或从工厂方法返回后在对象实例上设置的属性来定义其依
Easter79 Easter79
2年前
Spring中管理Bean依赖注入之后和Bean销毁之前的行为
    对于Singleton作用域的Bean,Spring容器将会跟踪它们的生命周期,容器知道何时实例化结束、何时销毁。Spring可以管理Bean在实例化结束之后和Bean销毁之前的行为。Bean依赖关系注入之后的行为:    Spring提供了两种方式在Bean全部属性设置成功后执行特定的行为:在Spring配置文件
Stella981 Stella981
2年前
Spring Ioc之BeanFactory
   IoC(InversionofControl),即所谓的控制反转,就是应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器(BeanFactory)负责的。   Spring通过配置文件(或者注解、JavaConfig)描述Bean和Bean之间的依赖关系,利用反射机制实例化Bean并建立Bean之间的依赖关系。Spr
Easter79 Easter79
2年前
Spring的BeanFactoryPostProcessor接口
接口简介BeanFactoryPostProcessor接口是Spring初始化BeanFactory时对外暴露的扩展点,SpringIoC容器允许BeanFactoryPostProcessor在容器实例化任何bean之前读取bean的定义,并可以修改它。BeanDefinitionRegistryPostPro
Wesley13 Wesley13
2年前
JAVA记录
singleton作用域:当把一个Bean定义设置为singleton作用域是,SpringIoC容器中只会存在一个共享的Bean实例,并且所有对Bean的请求,只要id与该Bean定义相匹配,则只会返回该Bean的同一实例。值得强调的是singleton作用域是Spring中的缺省作用域。prototype作用域:protot
Stella981 Stella981
2年前
Spring Bean注册解析(一)
       Spring是通过IoC容器对Bean进行管理的,而Bean的初始化主要分为两个过程:Bean的注册和Bean实例化。Bean的注册主要是指Spring通过读取配置文件获取各个bean的声明信息,并且对这些信息进行注册的过程。Bean的实例化则指的是Spring通过Bean的注册信息对各个Bean进行实例化的过程。本文主要讲解Spring是如何
Wesley13 Wesley13
2年前
Spring学习详解(1)——Spring入门详解
一:spring的基本用法:1,关于spring容器:spring容器是Spring的核心,该容器负责管理spring中的java组件,ApplicationContextctx newClassPathXmlApplicationContext("bean.xml");//这种方式实例化容器,容器会自动预初始化所有Bean实例
Easter79 Easter79
2年前
Spring容器中Bean的作用域
当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域。Spring支持如下5种作用域:singleton:单例模式,在整个SpringIoC容器中,使用singleton定义的Bean将只有一个实例prototype:原型模式,每次通过容器
Stella981 Stella981
2年前
Spring Bean 范围
Scope分类scope范围说明singleton(默认)每个SpringIoC容器定义单个bean实例prototype任意数量的对象实例request每个HTTP请求都有自己的Bean实例sessionHTTP会话的生命周期将共用同一个Bean实例globalSession全局HTTP会话的生命周期
Easter79 Easter79
2年前
Spring高级应用之注入嵌套Bean
在Spring中,如果某个Bean所依赖的Bean不想被Spring容器直接访问,可以使用嵌套Bean。和普通的Bean一样,使用<bean元素来定义嵌套的Bean,嵌套Bean只对它的外部的Bean有效,Spring容器无法直接访问嵌套的Bean,因此定义嵌套Bean也无需指定id属性。如下配置片段是一个嵌套Bean的示例:<bean id