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 站点 - Java SE 下载下载最新版本的 SDK 。您将在下载的文件中找到安装 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 变量。

Eclipse 可以通过在 Windows 机器上执行以下命令来启动,或者只需双击 eclipse.exe

%C:\eclipse\eclipse.exe 

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

$/usr/local/eclipse/eclipse

成功启动后,如果一切正常,那么它应该显示以下结果 -

Eclipse 主页

设置Maven

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

Spring DI - IoC 容器

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

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

Spring IoC 容器

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。BeanFactory 仍然可以用于轻量级应用程序,例如数据量和速度都非常重要的移动设备或基于小程序的应用程序。

Spring DI - BeanFactory 容器

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

Spring 有许多开箱即用的 BeanFactory 接口实现。最常用的 BeanFactory 实现是XmlBeanFactory类。该容器从 XML 文件中读取配置元数据,并使用它来创建完全配置的系统或应用程序。

当资源有限(例如移动设备或基于小程序的应用程序)时,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。BeanFactory 仍然可以用于轻量级应用程序,例如移动设备或基于小程序的应用程序。

最常用的 ApplicationContext 实现是 -

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

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

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

例子

让我们更新一下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();
   }
}

关于主程序应注意以下两个要点 -

  • 第一步是创建工厂对象,在从给定路径加载 bean 配置文件后,我们使用框架 API FileSystemXmlApplicationContext创建工厂 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,选择FileNewMaven Project。勾选“创建一个简单项目(跳过原型选择)”,然后单击“下一步”。

输入详细信息,如下所示 -

  • groupId - com.tutorialspoint

  • artifactId - springdi

  • 版本- 0.0.1-SNAPSHOT

  • 名称- springdi

  • 描述- 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>

应用程序上下文.xml

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

应用程序上下文.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。因此,<property/> 或 <constructor-arg/> 元素内的 <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,它具有基于 setter 的注入的配置,但使用内部 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">

   <!-- 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 配置文件中 <property> 标记的ref属性和值属性来配置原始数据类型和对象引用。这两种情况都涉及将奇异值传递给 bean。

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

先生编号 元素和描述
1

<列表>

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

2

<设置>

这有助于连接一组值,但没有任何重复。

3

<道具>

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

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

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

例子

以下示例显示了一个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 - 注入集合引用构造函数

您已经了解了如何使用Bean 配置文件中 <property> 标记的ref属性和值属性来配置原始数据类型和对象引用。这两种情况都涉及将奇异值传递给 bean。

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

先生编号 元素和描述
1

<列表>

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

2

<设置>

这有助于连接一组值,但没有任何重复。

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

在此示例中,我们展示了使用 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 - 注入映射构造函数

您已经了解了如何使用Bean 配置文件中 <property> 标记的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 - 地图引用构造函数

您已经了解了如何使用Bean 配置文件中 <property> 标记的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 方法来完成的。

例子

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

让我们更新一下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 方法的命名约定。为了设置变量pellChecker,我们使用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 文件的差异。唯一的区别是在 <bean> 元素内部,我们使用 <constructor-arg> 标签进行基于构造函数的注入,使用 <property> 标签进行基于 setter 的注入。

第二个需要注意的要点是,如果您要传递对对象的引用,则需要使用<property> 标记的ref属性,如果您直接传递,则应该使用 value 属性。

输出

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

Inside SpellChecker constructor.
Inside setSpellChecker.
Inside checkSpelling.

Spring DI - 内部 Bean Setter

正如您所知,Java 内部类是在其他类的范围内定义的,类似地,内部 bean是在另一个 bean 的范围内定义的 bean。因此,<property/> 或 <constructor-arg/> 元素内的 <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>

例子

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

让我们更新一下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,它具有基于 setter 的注入的配置,但使用内部 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">

   <!-- 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 - 集合设置器

您已经了解了如何使用Bean 配置文件中 <property> 标记的ref属性和值属性来配置原始数据类型和对象引用。这两种情况都涉及将奇异值传递给 bean。

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

先生编号 元素和描述
1

<列表>

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

2

<设置>

这有助于连接一组值,但没有任何重复。

3

<道具>

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

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

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

例子

以下示例显示了一个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} 

Sprint DI - 系列参考设置器

您已经了解了如何使用Bean 配置文件中 <property> 标记的ref属性和值属性来配置原始数据类型和对象引用。这两种情况都涉及将奇异值传递给 bean。

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

先生编号 元素和描述
1

<列表>

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

2

<设置>

这有助于连接一组值,但没有任何重复。

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

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

例子

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

让我们更新在中创建的项目