Spring 依赖注入 - 快速指南



Spring DI - 概述

Spring 是最流行的企业级 Java 应用开发框架。全球数百万开发者使用 Spring 框架创建高性能、易于测试和可重用的代码。

Spring 框架是一个开源的 Java 平台。它最初由 Rod Johnson 编写,并于 2003 年 6 月在 Apache 2.0 许可下首次发布。

Spring 提供 IOC 容器,与 EJB 容器相比,这些容器通常比较轻量级。这对于在内存和 CPU 资源有限的计算机上开发和部署应用程序非常有利。

依赖注入 (DI)

Spring 最为显著的技术是依赖注入 (DI),它是控制反转的一种形式。控制反转 (IoC) 是一个通用概念,可以用多种不同的方式表达。依赖注入仅仅是控制反转的一个具体示例。

在编写复杂的 Java 应用程序时,应用程序类应尽可能独立于其他 Java 类,以提高重用这些类的可能性,并在单元测试时独立于其他类进行测试。依赖注入有助于将这些类粘合在一起,同时保持它们的独立性。

依赖注入究竟是什么?让我们分别来看这两个词。这里的“依赖”部分转化为两个类之间的关联。例如,类 A 依赖于类 B。现在,让我们来看第二部分,“注入”。这意味着类 B 将由 IoC 注入到类 A 中。

依赖注入可以通过向构造函数传递参数或通过构造后使用 setter 方法来实现。由于依赖注入是 Spring 框架的核心,我们将在单独的章节中结合相关示例解释此概念。

Spring DI - 环境设置

本章将指导您如何准备开发环境以开始使用 Spring 框架的工作。它还将教你如何在设置 Spring 框架之前在你的机器上设置 JDK、Maven 和 Eclipse:

设置 Java 开发工具包 (JDK)

您可以从 Oracle 的 Java 网站下载最新版本的 SDK:Java SE 下载。 您将在下载的文件中找到安装 JDK 的说明,请按照给定的说明安装和配置设置。最后,设置 PATH 和 JAVA_HOME 环境变量以引用包含 java 和 javac 的目录,通常分别为 java_install_dir/bin 和 java_install_dir。

如果您运行的是 Windows 并已将 JDK 安装在 C:\jdk-11.0.11,则必须将以下行添加到 C:\autoexec.bat 文件中。

set PATH=C:\jdk-11.0.11;%PATH% 
set JAVA_HOME=C:\jdk-11.0.11 

或者,在 Windows NT/2000/XP 上,您需要右键单击“我的电脑”,选择“属性”→“高级”→“环境变量”。然后,您需要更新 PATH 值并单击“确定”按钮。

在 Unix(Solaris、Linux 等)上,如果 SDK 安装在 /usr/local/jdk-11.0.11 中并且您使用的是 C shell,则必须将以下内容添加到 .cshrc 文件中。

setenv PATH /usr/local/jdk-11.0.11/bin:$PATH 
setenv JAVA_HOME /usr/local/jdk-11.0.11

或者,如果您使用集成开发环境 (IDE),例如 Borland JBuilder、Eclipse、IntelliJ IDEA 或 Sun ONE Studio,则需要编译并运行一个简单的程序以确认 IDE 知道您已安装 Java 的位置。否则,您需要按照 IDE 文档中给出的说明进行正确的设置。

设置 Eclipse IDE

本教程中的所有示例均使用 Eclipse IDE 编写。因此,我们建议您应该在您的机器上安装最新版本的 Eclipse。

要安装 Eclipse IDE,请从 www.eclipse.org/downloads 下载最新的 Eclipse 二进制文件。下载安装程序后,将二进制分发版解压到方便的位置。例如,在 Windows 上为 C:\eclipse,在 Linux/Unix 上为 /usr/local/eclipse,最后适当地设置 PATH 变量。

可以通过在 Windows 机器上执行以下命令启动 Eclipse,或者您可以简单地双击 eclipse.exe

%C:\eclipse\eclipse.exe 

可以通过在 Unix(Solaris、Linux 等)机器上执行以下命令启动 Eclipse:

$/usr/local/eclipse/eclipse

成功启动后,如果一切正常,则应显示以下结果:

Eclipse Home page

设置 Maven

在本教程中,我们使用 maven 来运行和构建基于 spring 的示例。请按照 Maven - 环境设置 安装 maven。

Spring DI - IoC 容器

Spring 容器是 Spring 框架的核心。容器将创建对象,将它们连接在一起,配置它们,并管理它们从创建到销毁的整个生命周期。Spring 容器使用 DI 来管理构成应用程序的组件。这些对象称为 Spring Bean,我们将在下一章中讨论。

容器通过读取提供的配置元数据来获取有关要实例化、配置和组装哪些对象的指令。配置元数据可以用 XML、Java 注解或 Java 代码表示。下图显示了 Spring 工作方式的高级视图。Spring IoC 容器使用 Java POJO 类和配置元数据来生成完全配置且可执行的系统或应用程序。

Spring IoC Container

Spring 提供以下两种不同类型的容器。

序号 容器和描述
1

Spring BeanFactory 容器

这是最简单的容器,提供对 DI 的基本支持,并由 org.springframework.beans.factory.BeanFactory 接口定义。BeanFactory 和相关的接口(例如 BeanFactoryAware、InitializingBean、DisposableBean)仍然存在于 Spring 中,目的是为了与大量与 Spring 集成的第三方框架向后兼容。

2

Spring ApplicationContext 容器

此容器添加了更多特定于企业的功能,例如能够从属性文件解析文本消息和能够将应用程序事件发布给感兴趣的事件侦听器。此容器由 org.springframework.context.ApplicationContext 接口定义。

ApplicationContext 容器包含 BeanFactory 容器的所有功能,因此通常建议使用它而不是 BeanFactory。对于像移动设备或基于 applet 的应用程序这样的轻量级应用程序,如果数据量和速度很重要,仍然可以使用 BeanFactory。

Spring DI - BeanFactory 容器

这是最简单的容器,提供对 DI 的基本支持,并由 org.springframework.beans.factory.BeanFactory 接口定义。BeanFactory 和相关的接口(例如 BeanFactoryAware、InitializingBean、DisposableBean)仍然存在于 Spring 中,目的是为了与大量与 Spring 集成的第三方框架向后兼容。

有很多 BeanFactory 接口的实现可以直接从 Spring 中获得。最常用的 BeanFactory 实现是 **XmlBeanFactory** 类。此容器从 XML 文件读取配置元数据,并使用它来创建完全配置的系统或应用程序。

在资源有限(如移动设备或基于 applet 的应用程序)的情况下,通常首选 BeanFactory。因此,除非您有充分的理由,否则请使用 ApplicationContext。

示例

让我们更新在 Spring DI - 创建项目 一章中创建的项目。我们添加以下文件:

  • HelloWorld.java - 一个依赖类。

  • MainApp.java - 用于运行和测试的主应用程序。

以下是 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.beans.factory.InitializingBean; 
import org.springframework.beans.factory.xml.XmlBeanFactory; 
import org.springframework.core.io.ClassPathResource;  

public class MainApp { 
   public static void main(String[] args) { 
      XmlBeanFactory factory = new XmlBeanFactory (new ClassPathResource("Beans.xml")); 
      HelloWorld obj = (HelloWorld) factory.getBean("helloWorld");    
      obj.getMessage();    
   }
}

关于主程序,应注意以下两点:

  • 第一步是创建一个工厂对象,我们使用框架 APIXmlBeanFactory() 创建工厂 bean,并使用ClassPathResource() API 加载 CLASSPATH 中可用的 bean 配置文件。XmlBeanFactory() API 负责创建和初始化配置文件中提到的所有对象(即 bean)。

  • 第二步是使用创建的 bean 工厂对象的 getBean() 方法获取所需的 bean。此方法使用 bean ID 返回一个泛型对象,最终可以将其强制转换为实际对象。获得对象后,您可以使用此对象调用任何类方法。

以下是 bean 配置文件 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">
      <property name = "message" value = "Hello World!"/>
   </bean>
</beans>

输出

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

Your Message : Hello World!

Spring DI - ApplicationContext 容器

ApplicationContext 是 Spring 的高级容器。与 BeanFactory 类似,它可以加载 bean 定义、将 bean 连接在一起以及根据请求分配 bean。此外,它还添加了更多特定于企业的功能,例如能够从属性文件解析文本消息和能够将应用程序事件发布给感兴趣的事件侦听器。此容器由 org.springframework.context.ApplicationContext 接口定义。

ApplicationContext 包含 BeanFactory 的所有功能,通常建议使用它而不是 BeanFactory。对于像移动设备或基于 applet 的应用程序这样的轻量级应用程序,仍然可以使用 BeanFactory。

最常用的 ApplicationContext 实现是:

  • FileSystemXmlApplicationContext - 此容器从 XML 文件加载 bean 的定义。这里需要向构造函数提供 XML bean 配置文件的完整路径。

  • ClassPathXmlApplicationContext - 此容器从 XML 文件加载 bean 的定义。这里不需要提供 XML 文件的完整路径,但需要正确设置 CLASSPATH,因为此容器将在 CLASSPATH 中查找 bean 配置 XML 文件。

  • WebXmlApplicationContext - 此容器从 Web 应用程序中加载包含所有 bean 定义的 XML 文件。

示例

让我们更新在 Spring DI - 创建项目 一章中创建的项目。我们添加以下文件:

  • HelloWorld.java - 一个依赖类。

  • MainApp.java - 用于运行和测试的主应用程序。

以下是 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.FileSystemXmlApplicationContext;

public class MainApp {
   public static void main(String[] args) {
      ApplicationContext context = new FileSystemXmlApplicationContext
         ("C:/Users/ZARA/workspace/HelloSpring/src/Beans.xml");
      
      HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
      obj.getMessage();
   }
}

关于主程序,应注意以下两点:

  • 第一步是创建工厂对象,我们使用框架API **FileSystemXmlApplicationContext** 从给定路径加载bean配置后创建工厂bean。**FileSystemXmlApplicationContext()** API负责创建和初始化XML bean配置文件中提到的所有对象,即bean。

  • 第二步是使用已创建上下文的**getBean()**方法获取所需的bean。此方法使用bean ID返回一个泛型对象,最终可以将其转换为实际对象。获得对象后,可以使用此对象调用任何类方法。

以下是 bean 配置文件 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">
      <property name = "message" value = "Hello World!"/>
   </bean>
</beans>

输出

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

Your Message : Hello World!

Spring DI - 创建项目

使用eclipse,选择**文件** → **新建** → **Maven项目**。选中**创建一个简单的项目(跳过原型选择)**并单击下一步。

输入如下所示的详细信息:

  • **groupId** − com.tutorialspoint

  • **artifactId** − springdi

  • **version** − 0.0.1-SNAPSHOT

  • **name** − springdi

  • **description** − Spring依赖注入项目

单击“完成”按钮,将创建一个新项目。

pom.xml

使用Spring Core依赖项更新pom.xml。以下是pom.xml的完整内容:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.tutorialspoint</groupId>
   <artifactId>springdi</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>springdi</name>
   <description>Spring Dependency Injection Project</description>
   <properties>
      <org.springframework.version>5.3.9</org.springframework.version>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <java.version>1.8</java.version>    
   </properties> 
   <dependencies>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-context</artifactId>
         <version>${org.springframework.version}</version>
         <scope>compile</scope>
      </dependency>
   </dependencies>	    
   <build>
      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
               <source>${java.version}</source>
               <target>${java.version}</target>
            </configuration>
         </plugin>
      </plugins>
   </build>
</project>

applicationcontext.xml

在**src → main → resources**中创建applicationcontext.xml,内容如下。

applicationcontext.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">  
</beans> 

Spring DI - 基于构造函数的注入

当容器调用具有多个参数的类构造函数时,每个参数代表对其他类的依赖关系,从而实现基于构造函数的DI。

示例

以下示例显示了一个TextEditor类,它只能通过构造函数注入进行依赖注入。

让我们更新在 Spring DI - 创建项目 一章中创建的项目。我们添加以下文件:

  • **TextEditor.java** − 包含SpellChecker作为依赖项的类。

  • **SpellChecker.java** − 一个依赖类。

  • MainApp.java - 用于运行和测试的主应用程序。

以下是**TextEditor.java**文件的内容:

package com.tutorialspoint;

public class TextEditor {
   private SpellChecker spellChecker;
   
   public TextEditor(SpellChecker spellChecker) {
      System.out.println("Inside TextEditor constructor." );
      this.spellChecker = spellChecker;
   }
   public void spellCheck() {
      spellChecker.checkSpelling();
   }
}

以下是另一个依赖类文件**SpellChecker.java**的内容:

package com.tutorialspoint;
public class SpellChecker {
   public SpellChecker(){
      System.out.println("Inside SpellChecker constructor." );
   }
   public void checkSpelling() {
      System.out.println("Inside checkSpelling." );
   }
}

以下是**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("applicationcontext.xml");

      TextEditor te = (TextEditor) context.getBean("textEditor");
      te.spellCheck();
   }
}

以下是配置文件**applicationcontext.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">

   <!-- Definition for textEditor bean -->
   <bean id = "textEditor" class = "com.tutorialspoint.TextEditor">
      <constructor-arg ref = "spellChecker"/>
   </bean>

   <!-- Definition for spellChecker bean -->
   <bean id = "spellChecker" class = "com.tutorialspoint.SpellChecker"></bean>
</beans>

输出

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

Inside SpellChecker constructor.
Inside TextEditor constructor.
Inside checkSpelling.

Spring DI - 注入内部Bean构造函数

如您所知,Java内部类是在其他类的范围内定义的,同样,**内部bean**是在另一个bean的范围内定义的bean。因此,``元素在``或``元素内被称为内部bean,如下所示。

<?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 = "outerBean" class = "...">
      <constructor-arg name = "target">
         <bean id = "innerBean" class = "..."/>
      </constructor-arg>
   </bean>

</beans>

示例

以下示例显示了一个TextEditor类,它只能使用基于构造函数的注入进行依赖注入。

让我们更新在 Spring DI - 创建项目 一章中创建的项目。我们添加以下文件:

  • **TextEditor.java** − 包含SpellChecker作为依赖项的类。

  • **SpellChecker.java** − 一个依赖类。

  • MainApp.java - 用于运行和测试的主应用程序。

以下是**TextEditor.java**文件的内容:

package com.tutorialspoint;
public class TextEditor {
   private SpellChecker spellChecker;
   
   public TextEditor(SpellChecker spellChecker) {
      System.out.println("Inside TextEditor constructor." );
      this.spellChecker = spellChecker;
   }
   // a getter method to return spellChecker
   public SpellChecker getSpellChecker() {
      return spellChecker;
   }
   public void spellCheck() {
      spellChecker.checkSpelling();
   }
}

以下是另一个依赖类文件**SpellChecker.java**的内容:

package com.tutorialspoint;
public class SpellChecker {
   public SpellChecker(){
      System.out.println("Inside SpellChecker constructor." );
   }
   public void checkSpelling(){
      System.out.println("Inside checkSpelling." );
   }
}

以下是**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("applicationcontext.xml");
      TextEditor te = (TextEditor) context.getBean("textEditor");
      te.spellCheck();
   }
}

以下是配置文件**applicationcontext.xml**,其中包含使用**内部bean**的基于setter的注入配置:

<?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">

   <!-- Definition for textEditor bean using inner bean -->
   <bean id = "textEditor" class = "com.tutorialspoint.TextEditor">
      <constructor-arg name = "spellChecker">
         <bean id = "spellChecker" class = "com.tutorialspoint.SpellChecker"/>
      </constructor-arg>
   </bean>

</beans>

输出

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

Inside SpellChecker constructor.
Inside TextEditor constructor.
Inside checkSpelling.

Spring DI - 注入集合构造函数

您已经了解了如何在Bean配置文件中使用``标记的`value`属性配置基本数据类型,以及使用`ref`属性配置对象引用。这两种情况都涉及将单个值传递给bean。

如果您想传递多个值,例如Java集合类型(如List、Set和Properties),该怎么办?为了处理这种情况,Spring提供了以下类型的集合配置元素:

序号 元素及描述
1

<list>

这有助于连接,即注入一系列值,允许重复。

2

<set>

这有助于连接一系列值,但不允许重复。

3

<props>

这可用于注入名称值对的集合,其中名称和值都是字符串。

您可以使用<list>或<set>连接java.util.Collection的任何实现或**数组**。

在这个例子中,我们展示了传递集合元素的直接值。

示例

以下示例显示了一个JavaCollection类,它使用集合作为通过构造函数参数注入的依赖项。

让我们更新在 Spring DI - 创建项目 一章中创建的项目。我们添加以下文件:

  • **JavaCollection.java** − 包含集合作为依赖项的类。

  • MainApp.java - 用于运行和测试的主应用程序。

以下是**JavaCollection.java**文件的内容:

package com.tutorialspoint;
import java.util.*;

public class JavaCollection {
   List<String> addressList;
   Set<String>  addressSet;
   Properties addressProp;

   public JavaCollection() {}

   public JavaCollection(List<String> addressList, Set<String> addressSet, 
      Properties addressProp) {
      this.addressList = addressList;
      this.addressSet = addressSet;
      this.addressProp = addressProp;
   }
   // a setter method to set List
   public void setAddressList(List<String> addressList) {
      this.addressList = addressList;
   }
   
   // prints and returns all the elements of the list.
   public List<String> getAddressList() {
      System.out.println("List Elements :"  + addressList);
      return addressList;
   }

   // a setter method to set Set
   public void setAddressSet(Set<String> addressSet) {
      this.addressSet = addressSet;
   }

   // prints and returns all the elements of the Set.
   public Set<String> getAddressSet() {
      System.out.println("Set Elements :"  + addressSet);
      return addressSet;
   }

   // a setter method to set Property
   public void setAddressProp(Properties addressProp) {
      this.addressProp = addressProp;
   }

   // prints and returns all the elements of the Property.
   public Properties getAddressProp() {
      System.out.println("Property Elements :"  + addressProp);
      return addressProp;
   }
}

以下是**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("applicationcontext.xml");
      JavaCollection jc=(JavaCollection)context.getBean("javaCollection");

      jc.getAddressList();
      jc.getAddressSet();
      jc.getAddressProp();
   }
}

以下是配置文件**applicationcontext.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 = "javaCollection" class = "com.tutorialspoint.JavaCollection">
      <constructor-arg name = "addressList">
         <list>
            <value>INDIA</value>
            <value>JAPAN</value>
            <value>USA</value>
            <value>UK</value>
         </list>
      </constructor-arg>
      <constructor-arg name = "addressSet">
         <set>
            <value>INDIA</value>
            <value>JAPAN</value>
            <value>USA</value>
            <value>UK</value>
         </set>
      </constructor-arg>
      <constructor-arg name = "addressProp">
         <props>
            <prop key = "one">INDIA</prop>
            <prop key = "two">JAPAN</prop>
            <prop key = "three">USA</prop>
            <prop key = "four">UK</prop>
         </props>
      </constructor-arg>
   </bean>
</beans>

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

List Elements :[INDIA, JAPAN, USA, UK]
Set Elements :[INDIA, JAPAN, USA, UK]
Property Elements :{four=UK, one=INDIA, two=JAPAN, three=USA} 

Spring DI - 注入集合Ref构造函数

您已经了解了如何在Bean配置文件中使用``标记的`value`属性配置基本数据类型,以及使用`ref`属性配置对象引用。这两种情况都涉及将单个值传递给bean。

如果您想传递多个值,例如Java集合类型(如List、Set和Properties),该怎么办?为了处理这种情况,Spring提供了以下类型的集合配置元素:

序号 元素及描述
1

<list>

这有助于连接,即注入一系列值,允许重复。

2

<set>

这有助于连接一系列值,但不允许重复。

您可以使用<list>或<set>连接java.util.Collection的任何实现或**数组**。

在这个例子中,我们展示了使用ref传递集合元素。

示例

以下示例显示了一个JavaCollection类,它使用通过setter注入的依赖项集合。

让我们更新在 Spring DI - 创建项目 一章中创建的项目。我们添加以下文件:

  • **Address.java** − 用作依赖项的类。

  • **JavaCollection.java** − 包含依赖项集合的类。

  • MainApp.java - 用于运行和测试的主应用程序。

以下是**Address.java**文件的内容:

package com.tutorialspoint;

public class Address {
   private String name;

   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }	
   @Override
   public String toString() {
      return name;
   }
}

以下是**JavaCollection.java**文件的内容:

package com.tutorialspoint;
import java.util.*;

public class JavaCollection {
   List<Address> addressList;
   Set<Address>  addressSet;

   public JavaCollection(List<Address> addressList, Set<Address> addressSet) {
      this.addressList = addressList;
      this.addressSet = addressSet;
   }

   // a setter method to set List
   public void setAddressList(List<Address> addressList) {
      this.addressList = addressList;
   }

   // prints and returns all the elements of the list.
   public List<Address> getAddressList() {
      System.out.println("List Elements :"  + addressList);
      return addressList;
   }

   // a setter method to set Set
   public void setAddressSet(Set<Address> addressSet) {
      this.addressSet = addressSet;
   }
   
   // prints and returns all the elements of the Set.
   public Set<Address> getAddressSet() {
      System.out.println("Set Elements :"  + addressSet);
      return addressSet;
   }
}

以下是**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("applicationcontext.xml");
      JavaCollection jc=(JavaCollection)context.getBean("javaCollection");

      jc.getAddressList();
      jc.getAddressSet();
   }
}

以下是配置文件**applicationcontext.xml**,其中包含所有类型集合的配置:

<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 = "address1" class = "com.tutorialspoint.Address">
      <property name="name" value="INDIA"></property>
   </bean>
   <bean id = "address2" class = "com.tutorialspoint.Address">
      <property name="name" value="JAPAN"></property>
   </bean>
   <bean id = "address3" class = "com.tutorialspoint.Address">
      <property name="name" value="USA"></property>
   </bean>
   <bean id = "address4" class = "com.tutorialspoint.Address">
      <property name="name" value="UK"></property>
   </bean>
   <!-- Definition for javaCollection -->
   <bean id = "javaCollection" class = "com.tutorialspoint.JavaCollection">
      <constructor-arg name = "addressList">
         <list>
            <ref bean="address1" />
            <ref bean="address2" />
            <ref bean="address3" />
            <ref bean="address4" />
         </list>
      </constructor-arg>
      <constructor-arg name = "addressSet">
         <set>
            <ref bean="address1" />
            <ref bean="address2" />
            <ref bean="address3" />
            <ref bean="address4" />
         </set>
      </constructor-arg>
   </bean>
</beans>

输出

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

List Elements :[INDIA, JAPAN, USA, UK]
Set Elements :[INDIA, JAPAN, USA, UK]

Spring DI - 注入Map构造函数

您已经了解了如何在Bean配置文件中使用``标记的`value`属性配置基本数据类型,以及使用`ref`属性配置对象引用。这两种情况都涉及将单个值传递给bean。

如果您想传递Map怎么办?在这个例子中,我们展示了使用构造函数注入传递Map的直接值。

示例

以下示例显示了一个JavaCollection类,它使用集合作为通过构造函数参数注入的依赖项。

让我们更新在 Spring DI - 创建项目 一章中创建的项目。我们添加以下文件:

  • **JavaCollection.java** − 包含集合作为依赖项的类。

  • MainApp.java - 用于运行和测试的主应用程序。

以下是**JavaCollection.java**文件的内容:

package com.tutorialspoint;
import java.util.*;

public class JavaCollection {
   Map<String, String>  addressMap;
   public JavaCollection() {}

   public JavaCollection(Map<String, String> addressMap) {
      this.addressMap = addressMap;
   }
   
   // a setter method to set Map
   public void setAddressMap(Map<String, String> addressMap) {
      this.addressMap = addressMap;
   }

   // prints and returns all the elements of the Map.
   public Map<String, String> getAddressMap() {
      System.out.println("Map Elements :"  + addressMap);
      return addressMap;
   }
}

以下是**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("applicationcontext.xml");
      JavaCollection jc=(JavaCollection)context.getBean("javaCollection");
      jc.getAddressMap();
   }
}

以下是配置文件**applicationcontext.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 = "javaCollection" class = "com.tutorialspoint.JavaCollection">
      <constructor-arg name = "addressMap">
         <map>
            <entry key = "1" value = "INDIA"/>
            <entry key = "2" value = "JAPAN"/>
            <entry key = "3" value = "USA"/>
            <entry key = "4" value = "UK"/>
         </map>
      </constructor-arg>
   </bean>
</beans>

输出

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

Map Elements :{1=INDIA, 2=JAPAN, 3=USA, 4=UK}

Spring DI - Map 引用构造器

您已经了解了如何在Bean配置文件中使用``标记的`value`属性配置基本数据类型,以及使用`ref`属性配置对象引用。这两种情况都涉及将单个值传递给bean。

如果您想传递Map怎么办?在这个例子中,我们展示了使用构造函数注入传递Map的直接值。

示例

以下示例显示了一个JavaCollection类,它使用集合作为通过构造函数参数注入的依赖项。

让我们更新在 Spring DI - 创建项目 一章中创建的项目。我们添加以下文件:

  • **Address.java** − 用作依赖项的类。

  • **JavaCollection.java** − 包含依赖项集合的类。

  • MainApp.java - 用于运行和测试的主应用程序。

以下是**Address.java**文件的内容:

package com.tutorialspoint;

public class Address {
   private String name;

   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }	
   @Override
   public String toString() {
      return name;
   }
}

以下是**JavaCollection.java**文件的内容:

package com.tutorialspoint;
import java.util.*;

public class JavaCollection {
   Map<String, Address>  addressMap;
   public JavaCollection() {}

   public JavaCollection(Map<String, Address> addressMap) {
      this.addressMap = addressMap;
   }

   // a setter method to set Map
   public void setAddressMap(Map<String, Address> addressMap) {
      this.addressMap = addressMap;
   }

   // prints and returns all the elements of the Map.
   public Map<String, Address> getAddressMap() {
      System.out.println("Map Elements :"  + addressMap);
      return addressMap;
   }
}

以下是**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("applicationcontext.xml");
      JavaCollection jc=(JavaCollection)context.getBean("javaCollection");
      jc.getAddressMap();
   }
}

以下是配置文件**applicationcontext.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 = "address1" class = "com.tutorialspoint.Address">
      <property name="name" value="INDIA"></property>
   </bean>
   <bean id = "address2" class = "com.tutorialspoint.Address">
      <property name="name" value="JAPAN"></property>
   </bean>
   <bean id = "address3" class = "com.tutorialspoint.Address">
      <property name="name" value="USA"></property>
   </bean>
   <bean id = "address4" class = "com.tutorialspoint.Address">
      <property name="name" value="UK"></property>
   </bean>
   <bean id = "javaCollection" class = "com.tutorialspoint.JavaCollection">
      <constructor-arg name = "addressMap">
         <map>
            <entry key = "1" value-ref = "address1"/>
            <entry key = "2" value-ref = "address2"/>
            <entry key = "3" value-ref = "address3"/>
            <entry key = "4" value-ref = "address4"/>
         </map>
      </constructor-arg>
   </bean>
</beans>

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

Map Elements :{1=INDIA, 2=JAPAN, 3=USA, 4=UK}

Spring DI - 基于Setter的注入

基于Setter的DI是通过容器在调用无参数构造函数或无参数静态工厂方法来实例化bean后,调用bean上的setter方法来实现的。

示例

以下示例显示了一个TextEditor类,它只能使用纯基于setter的注入进行依赖注入。

让我们更新在 Spring DI - 创建项目 一章中创建的项目。我们添加以下文件:

  • **TextEditor.java** − 包含SpellChecker作为依赖项的类。

  • **SpellChecker.java** − 一个依赖类。

  • MainApp.java - 用于运行和测试的主应用程序。

以下是**TextEditor.java**文件的内容:

package com.tutorialspoint;
public class TextEditor {
   private SpellChecker spellChecker;

   // a setter method to inject the dependency.
   public void setSpellChecker(SpellChecker spellChecker) {
      System.out.println("Inside setSpellChecker." );
      this.spellChecker = spellChecker;
   }
   // a getter method to return spellChecker
   public SpellChecker getSpellChecker() {
      return spellChecker;
   }
   public void spellCheck() {
      spellChecker.checkSpelling();
   }
}

您需要检查setter方法的命名约定。为了设置变量spellChecker,我们使用setSpellChecker()方法,这与Java POJO类非常相似。让我们创建另一个依赖类文件SpellChecker.java的内容:

package com.tutorialspoint;

public class SpellChecker {
   public SpellChecker(){
      System.out.println("Inside SpellChecker constructor." );
   }
   public void checkSpelling() {
      System.out.println("Inside checkSpelling." );
   }
}

以下是**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("applicationcontext.xml");

      TextEditor te = (TextEditor) context.getBean("textEditor");
      te.spellCheck();
   }
}

以下是配置文件**applicationcontext.xml**,其中包含基于setter的注入配置:

<?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">

   <!-- Definition for textEditor bean -->
   <bean id = "textEditor" class = "com.tutorialspoint.TextEditor">
      <property name = "spellChecker" ref = "spellChecker"/>
   </bean>

   <!-- Definition for spellChecker bean -->
   <bean id = "spellChecker" class = "com.tutorialspoint.SpellChecker"></bean>
</beans>

您应该注意基于构造函数的注入和基于setter的注入中定义的applicationcontext.xml文件的区别。唯一的区别在于``元素内部,我们对基于构造函数的注入使用了``标记,对基于setter的注入使用了``标记。

第二个需要注意的重要点是,如果您正在传递对对象的引用,则需要使用``标记的`ref`属性;如果您直接传递`value`,则应使用value属性。

输出

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

Inside SpellChecker constructor.
Inside setSpellChecker.
Inside checkSpelling.

Spring DI - 内部 Bean Setter

如您所知,Java内部类是在其他类的范围内定义的,同样,**内部bean**是在另一个bean的范围内定义的bean。因此,``元素在``或``元素内被称为内部bean,如下所示。

<?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 = "outerBean" class = "...">
      <property name = "target">
         <bean id = "innerBean" class = "..."/>
      </property>
   </bean>
</beans>

示例

以下示例显示了一个TextEditor类,它只能使用纯基于setter的注入进行依赖注入。

让我们更新在 Spring DI - 创建项目 一章中创建的项目。我们添加以下文件:

  • **TextEditor.java** − 包含SpellChecker作为依赖项的类。

  • **SpellChecker.java** − 一个依赖类。

  • MainApp.java - 用于运行和测试的主应用程序。

以下是**TextEditor.java**文件的内容:

package com.tutorialspoint;

public class TextEditor {
   private SpellChecker spellChecker;
   
   // a setter method to inject the dependency.
   public void setSpellChecker(SpellChecker spellChecker) {
      System.out.println("Inside setSpellChecker." );
      this.spellChecker = spellChecker;
   }
   // a getter method to return spellChecker
   public SpellChecker getSpellChecker() {
      return spellChecker;
   }
   public void spellCheck() {
      spellChecker.checkSpelling();
   }
}

以下是另一个依赖类文件**SpellChecker.java**的内容:

package com.tutorialspoint;

public class SpellChecker {
   public SpellChecker(){
      System.out.println("Inside SpellChecker constructor." );
   }
   public void checkSpelling(){
      System.out.println("Inside checkSpelling." );
   }
}

以下是**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("applicationcontext.xml");
      TextEditor te = (TextEditor) context.getBean("textEditor");
      te.spellCheck();
   }
}

以下是配置文件**applicationcontext.xml**,其中包含使用**内部bean**的基于setter的注入配置:

<?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">

   <!-- Definition for textEditor bean using inner bean -->
   <bean id = "textEditor" class = "com.tutorialspoint.TextEditor">
      <property name = "spellChecker">
         <bean id = "spellChecker" class = "com.tutorialspoint.SpellChecker"/>
      </property>
   </bean>
</beans>

输出

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

Inside SpellChecker constructor.
Inside setSpellChecker.
Inside checkSpelling.

Spring DI - 集合 Setter

您已经了解了如何在Bean配置文件中使用``标记的`value`属性配置基本数据类型,以及使用`ref`属性配置对象引用。这两种情况都涉及将单个值传递给bean。

如果您想传递多个值,例如Java集合类型(如List、Set、Map和Properties),该怎么办?为了处理这种情况,Spring提供了以下类型的集合配置元素:

序号 元素及描述
1

<list>

这有助于连接,即注入一系列值,允许重复。

2

<set>

这有助于连接一系列值,但不允许重复。

3

<props>

这可用于注入名称值对的集合,其中名称和值都是字符串。

您可以使用<list>或<set>连接java.util.Collection的任何实现或**数组**。

在这个例子中,我们展示了传递集合元素的直接值。

示例

以下示例显示了一个JavaCollection类,它使用通过setter注入的集合作为依赖项。

让我们更新在 Spring DI - 创建项目 一章中创建的项目。我们添加以下文件:

  • **JavaCollection.java** − 包含集合作为依赖项的类。

  • MainApp.java - 用于运行和测试的主应用程序。

以下是**JavaCollection.java**文件的内容:

package com.tutorialspoint;
import java.util.*;

public class JavaCollection {
   List<String> addressList;
   Set<String>  addressSet;
   Properties addressProp;

   // a setter method to set List
   public void setAddressList(List<String> addressList) {
      this.addressList = addressList;
   }
   
   // prints and returns all the elements of the list.
   public List<String> getAddressList() {
      System.out.println("List Elements :"  + addressList);
      return addressList;
   }
   
   // a setter method to set Set
   public void setAddressSet(Set<String> addressSet) {
      this.addressSet = addressSet;
   }
   
   // prints and returns all the elements of the Set.
   public Set<String> getAddressSet() {
      System.out.println("Set Elements :"  + addressSet);
      return addressSet;
   }
   
   // a setter method to set Property
   public void setAddressProp(Properties addressProp) {
      this.addressProp = addressProp;
   }
   
   // prints and returns all the elements of the Property.
   public Properties getAddressProp() {
      System.out.println("Property Elements :"  + addressProp);
      return addressProp;
   }
}

以下是**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("applicationcontext.xml");
      JavaCollection jc=(JavaCollection)context.getBean("javaCollection");

      jc.getAddressList();
      jc.getAddressSet();
      jc.getAddressProp();
   }
}

以下是配置文件**applicationcontext.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">

   <!-- Definition for javaCollection -->
   <bean id = "javaCollection" class = "com.tutorialspoint.JavaCollection">
      <!-- results in a setAddressList(java.util.List) call -->
      <property name = "addressList">
         <list>
            <value>INDIA</value>
            <value>JAPAN</value>
            <value>USA</value>
            <value>UK</value>
         </list>
      </property>

      <!-- results in a setAddressSet(java.util.Set) call -->
      <property name = "addressSet">
         <set>
            <value>INDIA</value>
            <value>JAPAN</value>
            <value>USA</value>
            <value>UK</value>
         </set>
      </property>
      
      <!-- results in a setAddressProp(java.util.Properties) call -->
      <property name = "addressProp">
         <props>
            <prop key = "one">INDIA</prop>
            <prop key = "two">JAPAN</prop>
            <prop key = "three">USA</prop>
            <prop key = "four">UK</prop>
         </props>
      </property>
   </bean>
</beans>

输出

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

List Elements :[INDIA, JAPAN, USA, UK]
Set Elements :[INDIA, JAPAN, USA, UK]
Property Elements :{four=UK, one=INDIA, two=JAPAN, three=USA} 

Spring DI - 集合Ref Setter

您已经了解了如何在Bean配置文件中使用``标记的`value`属性配置基本数据类型,以及使用`ref`属性配置对象引用。这两种情况都涉及将单个值传递给bean。

如果您想传递多个值,例如Java集合类型(如List、Set、Map和Properties),该怎么办?为了处理这种情况,Spring提供了以下类型的集合配置元素:

序号 元素及描述
1

<list>

这有助于连接,即注入一系列值,允许重复。

2

<set>

这有助于连接一系列值,但不允许重复。

您可以使用<list>或<set>连接java.util.Collection的任何实现或**数组**。

在这个例子中,我们展示了使用ref传递集合元素。

示例

以下示例显示了一个JavaCollection类,它使用通过setter注入的依赖项集合。

让我们更新在 Spring DI - 创建项目 一章中创建的项目。我们添加以下文件:

  • **Address.java** − 用作依赖项的类。

  • **JavaCollection.java** − 包含依赖项集合的类。

  • MainApp.java - 用于运行和测试的主应用程序。

以下是**Address.java**文件的内容:

package com.tutorialspoint;

public class Address {
   private String name;

   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }	
   @Override
   public String toString() {
      return name;
   }
}

以下是**JavaCollection.java**文件的内容:

package com.tutorialspoint;
import java.util.*;

public class JavaCollection {
   List<Address> addressList;
   Set<Address>  addressSet;

   // a setter method to set List
   public void setAddressList(List<Address> addressList) {
      this.addressList = addressList;
   }
   
   // prints and returns all the elements of the list.
   public List<Address> getAddressList() {
      System.out.println("List Elements :"  + addressList);
      return addressList;
   }

   // a setter method to set Set
   public void setAddressSet(Set<Address> addressSet) {
      this.addressSet = addressSet;
   }

   // prints and returns all the elements of the Set.
   public Set<Address> getAddressSet() {
      System.out.println("Set Elements :"  + addressSet);
      return addressSet;
   }
}

以下是**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("applicationcontext.xml");
      JavaCollection jc=(JavaCollection)context.getBean("javaCollection");

      jc.getAddressList();
      jc.getAddressSet();
   }
}

以下是配置文件**applicationcontext.xml**,其中包含所有类型集合的配置:

<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 = "address1" class = "com.tutorialspoint.Address">
      <property name="name" value="INDIA"></property>
   </bean>
   <bean id = "address2" class = "com.tutorialspoint.Address">
      <property name="name" value="JAPAN"></property>
   </bean>
   <bean id = "address3" class = "com.tutorialspoint.Address">
      <property name="name" value="USA"></property>
   </bean>
   <bean id = "address4" class = "com.tutorialspoint.Address">
      <property name="name" value="UK"></property>
   </bean>
   
   <!-- Definition for javaCollection -->
   <bean id = "javaCollection" class = "com.tutorialspoint.JavaCollection">
      <!-- results in a setAddressList(java.util.List) call -->
      <property name = "addressList">
         <list>
            <ref bean="address1" />
            <ref bean="address2" />
            <ref bean="address3" />
            <ref bean="address4" />
         </list>
      </property>

      <!-- results in a setAddressSet(java.util.Set) call -->
      <property name = "addressSet">
         <set>
            <ref bean="address1" />
            <ref bean="address2" />
            <ref bean="address3" />
            <ref bean="address4" />
         </set>
      </property>
   </bean>
</beans>

输出

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

List Elements :[INDIA, JAPAN, USA, UK]
Set Elements :[INDIA, JAPAN, USA, UK]

Spring DI - Map Setter

您已经了解了如何在Bean配置文件中使用``标记的`value`属性配置基本数据类型,以及使用`ref`属性配置对象引用。这两种情况都涉及将单个值传递给bean。

如果您想传递Map怎么办?在这个例子中,我们展示了使用setter注入传递Map的直接值。

示例

以下示例显示了一个JavaCollection类,它使用通过setter方法注入的集合作为依赖项。

让我们更新在 Spring DI - 创建项目 一章中创建的项目。我们添加以下文件:

  • **JavaCollection.java** − 包含集合作为依赖项的类。

  • MainApp.java - 用于运行和测试的主应用程序。

以下是**JavaCollection.java**文件的内容:

package com.tutorialspoint;
import java.util.*;

public class JavaCollection {
   Map<String, String>  addressMap;
   public JavaCollection() {}

   public JavaCollection(Map<String, String> addressMap) {
      this.addressMap = addressMap;
   }

   // a setter method to set Map
   public void setAddressMap(Map<String, String> addressMap) {
      this.addressMap = addressMap;
   }

   // prints and returns all the elements of the Map.
   public Map<String, String> getAddressMap() {
      System.out.println("Map Elements :"  + addressMap);
      return addressMap;
   }
}

以下是**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("applicationcontext.xml");
      JavaCollection jc=(JavaCollection)context.getBean("javaCollection");
      jc.getAddressMap();
   }
}

以下是配置文件**applicationcontext.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 = "javaCollection" class = "com.tutorialspoint.JavaCollection">
      <property name = "addressMap">
         <map>
            <entry key = "1" value = "INDIA"/>
            <entry key = "2" value = "JAPAN"/>
            <entry key = "3" value = "USA"/>
            <entry key = "4" value = "UK"/>
         </map>
      </property>
   </bean>
</beans>

输出

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

Map Elements :{1=INDIA, 2=JAPAN, 3=USA, 4=UK}

Spring DI - Map 引用 Setter

您已经了解了如何在Bean配置文件中使用``标记的`value`属性配置基本数据类型,以及使用`ref`属性配置对象引用。这两种情况都涉及将单个值传递给bean。

如果您想传递Map怎么办?在这个例子中,我们展示了使用setter注入传递Map的直接值。

示例

以下示例显示了一个JavaCollection类,它使用通过setter方法注入的集合作为依赖项。

让我们更新在 Spring DI - 创建项目 一章中创建的项目。我们添加以下文件:

  • **Address.java** − 用作依赖项的类。

  • **JavaCollection.java** − 包含依赖项集合的类。

  • MainApp.java - 用于运行和测试的主应用程序。

以下是**Address.java**文件的内容:

package com.tutorialspoint;

public class Address {
   private String name;

   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }	
   @Override
   public String toString() {
      return name;
   }
}

以下是**JavaCollection.java**文件的内容:

package com.tutorialspoint;
import java.util.*;

public class JavaCollection {
   Map<String, Address>  addressMap;
   public JavaCollection() {}

   public JavaCollection(Map<String, Address> addressMap) {
      this.addressMap = addressMap;
   }
   
   // a setter method to set Map
   public void setAddressMap(Map<String, Address> addressMap) {
      this.addressMap = addressMap;
   }

   // prints and returns all the elements of the Map.
   public Map<String, Address> getAddressMap() {
      System.out.println("Map Elements :"  + addressMap);
      return addressMap;
   }
}

以下是**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("applicationcontext.xml");
      JavaCollection jc=(JavaCollection)context.getBean("javaCollection");
      jc.getAddressMap();
   }
}

以下是配置文件**applicationcontext.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 = "address1" class = "com.tutorialspoint.Address">
      <property name="name" value="INDIA"></property>
   </bean>
   <bean id = "address2" class = "com.tutorialspoint.Address">
      <property name="name" value="JAPAN"></property>
   </bean>
   <bean id = "address3" class = "com.tutorialspoint.Address">
      <property name="name" value="USA"></property>
   </bean>
   <bean id = "address4" class = "com.tutorialspoint.Address">
      <property name="name" value="UK"></property>
   </bean>
   <bean id = "javaCollection" class = "com.tutorialspoint.JavaCollection">
      <property name = "addressMap">
         <map>
            <entry key = "1" value-ref = "address1"/>
            <entry key = "2" value-ref = "address2"/>
            <entry key = "3" value-ref = "address3"/>
            <entry key = "4" value-ref = "address4"/>
         </map>
      </property>
   </bean>
</beans>

输出

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

Map Elements :{1=INDIA, 2=JAPAN, 3=USA, 4=UK}

Spring DI - 自动装配

您已经学习了如何在XML配置文件中使用``元素声明bean,以及使用``和``元素注入``。

Spring容器可以**自动装配**协作bean之间的关系,而无需使用``和``元素,这有助于减少为大型基于Spring的应用程序编写的XML配置量。

自动装配模式

以下是自动装配模式,可用于指示Spring容器使用自动装配进行依赖注入。您可以使用``元素的autowire属性为bean定义指定**autowire**模式。

序号 模式及描述
1

no

这是默认设置,这意味着没有自动装配,您应该使用显式bean引用进行连接。您无需为此连接做任何特殊操作。这就是您在依赖注入章节中已经看到的。

2

byName

按属性名称自动装配。Spring容器查看在XML配置文件中将`autowire`属性设置为`byName`的bean的属性。然后,它尝试匹配其属性,并将其与配置文件中定义的同名bean连接。

3

byType

按属性数据类型自动装配。Spring容器查看在XML配置文件中将`autowire`属性设置为`byType`的bean的属性。然后,如果其**类型**与配置文件中正好一个bean名称匹配,它尝试匹配并连接属性。如果存在多个这样的bean,则会抛出致命异常。

4

constructor

类似于byType,但类型适用于构造函数参数。如果容器中没有正好一个构造函数参数类型的bean,则会引发致命错误。

5

autodetect

Spring首先尝试使用`constructor`自动装配,如果失败,则尝试使用`byType`自动装配。

您可以使用byTypeconstructor自动装配模式连接数组和其他类型集合。

自动装配的局限性

当在整个项目中一致地使用自动装配时,效果最佳。如果通常不使用自动装配,则开发人员仅使用它来连接一两个bean定义可能会令人困惑。虽然自动装配可以显著减少指定属性或构造函数参数的需求,但在使用它们之前,您应该考虑自动装配的局限性和缺点。

序号 局限性及描述
1

覆盖可能性

您仍然可以使用``和``设置指定依赖项,这将始终覆盖自动装配。

2

基本数据类型

您无法自动装配所谓的简单属性,例如基元、字符串和类。

3

令人困惑的性质

自动装配不如显式装配精确,因此,如果可能,请优先使用显式装配。

Spring DI - 按名称自动装配

此模式指定按属性名称自动装配。Spring容器查看在XML配置文件中将`auto-wire`属性设置为`byName`的bean。然后,它尝试匹配其属性,并将其与配置文件中定义的同名bean连接。如果找到匹配项,它将注入这些bean。否则,将不会连接bean。

例如,如果bean定义在配置文件中设置为按名称自动装配,并且它包含一个`spellChecker`属性(即,它具有`setSpellChecker(...)`方法),Spring将查找名为spellChecker的bean定义,并使用它来设置属性。您仍然可以使用``标记连接其余属性。以下示例将说明此概念。

示例

以下示例显示了一个TextEditor类,它只能使用纯基于setter的注入进行依赖注入。

让我们更新在 Spring DI - 创建项目 一章中创建的项目。我们添加以下文件:

  • **TextEditor.java** − 包含SpellChecker作为依赖项的类。

  • **SpellChecker.java** − 一个依赖类。

  • MainApp.java - 用于运行和测试的主应用程序。

以下是**TextEditor.java**文件的内容:

package com.tutorialspoint;

public class TextEditor {
   private SpellChecker spellChecker;
   private String name;
   
   public void setSpellChecker( SpellChecker spellChecker ){
      this.spellChecker = spellChecker;
   }
   public SpellChecker getSpellChecker() {
      return spellChecker;
   }
   public void setName(String name) {
      this.name = name;
   }
   public String getName() {
      return name;
   }
   public void spellCheck() {
      spellChecker.checkSpelling();
   }
}

以下是另一个依赖类文件**SpellChecker.java**的内容:

package com.tutorialspoint;

public class SpellChecker {
   public SpellChecker(){
      System.out.println("Inside SpellChecker constructor." );
   }
   public void checkSpelling(){
      System.out.println("Inside checkSpelling." );
   }
}

以下是**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("applicationcontext.xml");
      TextEditor te = (TextEditor) context.getBean("textEditor");
      te.spellCheck();
   }
}

以下是配置文件**applicationcontext.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">

   <!-- Definition for textEditor bean -->
   <bean id = "textEditor" class = "com.tutorialspoint.TextEditor" autowire = "byName">
      <property name = "name" value = "Generic Text Editor" />
   </bean>

   <!-- Definition for spellChecker bean -->
   <bean id = "spellChecker" class = "com.tutorialspoint.SpellChecker"></bean>
</beans>

输出

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

Inside SpellChecker constructor.
Inside checkSpelling.

Spring DI - 按类型自动装配

此模式指定按属性类型自动装配。Spring容器查看在XML配置文件中将`autowire`属性设置为`byType`的bean。然后,如果其**类型**与配置文件中正好一个bean名称匹配,它尝试匹配并连接属性。如果找到匹配项,它将注入这些bean。否则,将不会连接bean。

例如,如果在配置文件中将 Bean 定义设置为按byType自动装配,并且它包含一个SpellChecker类型的spellChecker属性,Spring 会查找名为SpellChecker的 Bean 定义,并用它来设置该属性。您仍然可以使用<property>标签来连接其余的属性。以下示例将说明这个概念。

示例

以下示例显示了一个TextEditor类,它只能使用纯基于setter的注入进行依赖注入。

让我们更新在 Spring DI - 创建项目 一章中创建的项目。我们添加以下文件:

  • **TextEditor.java** − 包含SpellChecker作为依赖项的类。

  • **SpellChecker.java** − 一个依赖类。

  • MainApp.java - 用于运行和测试的主应用程序。

以下是**TextEditor.java**文件的内容:

package com.tutorialspoint;

public class TextEditor {
   private SpellChecker spellChecker;
   private String name;
   
   public void setSpellChecker( SpellChecker spellChecker ){
      this.spellChecker = spellChecker;
   }
   public SpellChecker getSpellChecker() {
      return spellChecker;
   }
   public void setName(String name) {
      this.name = name;
   }
   public String getName() {
      return name;
   }
   public void spellCheck() {
      spellChecker.checkSpelling();
   }
}

以下是另一个依赖类文件**SpellChecker.java**的内容:

package com.tutorialspoint;

public class SpellChecker {
   public SpellChecker(){
      System.out.println("Inside SpellChecker constructor." );
   }
   public void checkSpelling(){
      System.out.println("Inside checkSpelling." );
   }
}

以下是**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("applicationcontext.xml");
      TextEditor te = (TextEditor) context.getBean("textEditor");
      te.spellCheck();
   }
}

以下是配置文件**applicationcontext.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">

   <!-- Definition for textEditor bean -->
   <bean id = "textEditor" class = "com.tutorialspoint.TextEditor" autowire = "byType">
      <property name = "name" value = "Generic Text Editor" />
   </bean>

   <!-- Definition for spellChecker bean -->
   <bean id = "spellChecker" class = "com.tutorialspoint.SpellChecker"></bean>

</beans>

输出

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

Inside SpellChecker constructor.
Inside checkSpelling.

Spring DI - 构造器自动装配

此模式与byType非常相似,但它适用于构造函数参数。Spring 容器查看在 XML 配置文件中autowire属性设置为constructor的 Bean。然后,它尝试将构造函数的参数与配置文件中恰好一个 Bean 名称匹配并连接。如果找到匹配项,它将注入这些 Bean。否则,Bean将不会被连接。

例如,如果在配置文件中将 Bean 定义设置为按constructor自动装配,并且它有一个参数为SpellChecker类型的构造函数,Spring 会查找名为SpellChecker的 Bean 定义,并用它来设置构造函数的参数。您仍然可以使用<constructor-arg>标签来连接其余的参数。以下示例将说明这个概念。

示例

以下示例显示了一个只能使用构造函数进行依赖注入的类TextEditor

让我们更新在 Spring DI - 创建项目 一章中创建的项目。我们添加以下文件:

  • **TextEditor.java** − 包含SpellChecker作为依赖项的类。

  • **SpellChecker.java** − 一个依赖类。

  • MainApp.java - 用于运行和测试的主应用程序。

以下是**TextEditor.java**文件的内容:

package com.tutorialspoint;

public class TextEditor {
   private SpellChecker spellChecker;
   private String name;
   
   public TextEditor(SpellChecker spellChecker, String name) {
      this.spellChecker = spellChecker;
      this.name = name;
   }
   public SpellChecker getSpellChecker() {
      return spellChecker;
   }
   public String getName() {
      return name;
   }
   public void spellCheck() {
      spellChecker.checkSpelling();
   }
}

以下是另一个依赖类文件**SpellChecker.java**的内容:

package com.tutorialspoint;

public class SpellChecker {
   public SpellChecker(){
      System.out.println("Inside SpellChecker constructor." );
   }
   public void checkSpelling(){
      System.out.println("Inside checkSpelling." );
   }
}

以下是**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("applicationcontext.xml");
      TextEditor te = (TextEditor) context.getBean("textEditor");
      te.spellCheck();
   }
}

以下是配置文件**applicationcontext.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">

   <!-- Definition for textEditor bean -->
   <bean id = "textEditor" class = "com.tutorialspoint.TextEditor" autowire = "constructor">
      <constructor-arg name = "name" value = "Generic Text Editor" />
   </bean>

   <!-- Definition for spellChecker bean -->
   <bean id = "spellChecker" class = "com.tutorialspoint.SpellChecker"></bean>
</beans>

输出

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

Inside SpellChecker constructor.
Inside checkSpelling.

Spring DI - 静态工厂

Spring 提供了一个使用factory-method属性注入依赖项的选项。

示例

以下示例显示了一个TextEditor类,它只能使用纯基于setter的注入进行依赖注入。

让我们更新在 Spring DI - 创建项目 一章中创建的项目。我们添加以下文件:

  • **TextEditor.java** − 包含SpellChecker作为依赖项的类。

  • **SpellChecker.java** − 一个依赖类。

  • MainApp.java - 用于运行和测试的主应用程序。

以下是**TextEditor.java**文件的内容:

package com.tutorialspoint;

public class TextEditor {
   private SpellChecker spellChecker;
   private String name;
   
   public void setSpellChecker( SpellChecker spellChecker ){
      this.spellChecker = spellChecker;
   }
   public SpellChecker getSpellChecker() {
      return spellChecker;
   }
   public void setName(String name) {
      this.name = name;
   }
   public String getName() {
      return name;
   }
   public void spellCheck() {
      spellChecker.checkSpelling();
   }
}

以下是另一个依赖类文件**SpellChecker.java**的内容:

此类的构造函数是私有的。因此,它的对象不能由其他对象使用new运算符直接创建。它有一个静态工厂方法来获取实例。

package com.tutorialspoint;

public class SpellChecker {
   private SpellChecker(){
      System.out.println("Inside SpellChecker constructor." );
   }
   public static SpellChecker getInstance() {
      System.out.println("Inside SpellChecker getInstance." );
      return new SpellChecker();
   }	
   public void checkSpelling(){
      System.out.println("Inside checkSpelling." );
   }
}

以下是**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("applicationcontext.xml");
      TextEditor te = (TextEditor) context.getBean("textEditor");
      te.spellCheck();
   }
}

以下是配置文件**applicationcontext.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">

   <!-- Definition for textEditor bean -->
   <bean id = "textEditor" class = "com.tutorialspoint.TextEditor" autowire = "byName">
      <property name = "name" value = "Generic Text Editor" />
   </bean>

   <!-- Definition for spellChecker bean -->
   <bean id = "spellChecker" class = "com.tutorialspoint.SpellChecker" factory-method="getInstance"></bean>
</beans>

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

Inside SpellChecker getInstance.
Inside SpellChecker constructor.
Inside checkSpelling.

Spring DI - 非静态工厂

对于非静态工厂方法,Spring 提供了一个选项,可以使用 factory-method 属性以及 factory-bean 属性来注入依赖项。

示例

以下示例显示了一个TextEditor类,它只能使用纯基于setter的注入进行依赖注入。

让我们更新在 Spring DI - 创建项目 一章中创建的项目。我们添加以下文件:

  • **TextEditor.java** − 包含SpellChecker作为依赖项的类。

  • **SpellChecker.java** − 一个依赖类。

  • MainApp.java - 用于运行和测试的主应用程序。

以下是**TextEditor.java**文件的内容:

package com.tutorialspoint;

public class TextEditor {
   private SpellChecker spellChecker;
   private String name;
   
   public void setSpellChecker( SpellChecker spellChecker ){
      this.spellChecker = spellChecker;
   }
   public SpellChecker getSpellChecker() {
      return spellChecker;
   }
   public void setName(String name) {
      this.name = name;
   }
   public String getName() {
      return name;
   }
   public void spellCheck() {
      spellChecker.checkSpelling();
   }
}

以下是另一个依赖类文件**SpellChecker.java**的内容:

此类的构造函数是私有的。因此,它的对象不能由其他对象使用new运算符直接创建。它有一个非静态工厂方法来获取实例。

package com.tutorialspoint;

public class SpellChecker {
   private SpellChecker(){
      System.out.println("Inside SpellChecker constructor." );
   }
   public SpellChecker getInstance() {
      System.out.println("Inside SpellChecker getInstance." );
      return new SpellChecker();
   }	
   public void checkSpelling(){
      System.out.println("Inside checkSpelling." );
   }
}

以下是**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("applicationcontext.xml");
      TextEditor te = (TextEditor) context.getBean("textEditor");
      te.spellCheck();
   }
}

以下是配置文件**applicationcontext.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">

   <!-- Definition for textEditor bean -->
   <bean id = "textEditor" class = "com.tutorialspoint.TextEditor" autowire = "byName">
      <property name = "name" value = "Generic Text Editor" />
   </bean>
   
   <bean id = "spellCheckFactory" class = "com.tutorialspoint.SpellChecker"></bean>

   <!-- Definition for spellChecker bean -->
   <bean id = "spellChecker" class = "com.tutorialspoint.SpellChecker" factory-method="getInstance">< factory-bean="spellCheckFactory"/bean>
</beans>

输出

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

Inside SpellChecker constructor.
Inside SpellChecker getInstance.
Inside SpellChecker constructor.
Inside checkSpelling.
广告