Spring Dependency Injection 简明教程
Spring DI - Overview
Spring 是一个最受欢迎的应用程序开发框架,用于企业级 Java。全世界数百万开发人员使用 Spring Framework 创建高性能、易于测试的代码,可以重复使用。
Spring Framework 是一个开源 Java 平台。它最初由 Rod Johnson 编写,并于 2003 年 6 月首次在 Apache 2.0 许可证下发布。
Spring 提供 Ioc 容器,与 EJB 容器相比,它们往往更轻量级。这对在具有受限内存和 CPU 资源的计算机上开发和部署应用程序非常有利。
Dependency Injection (DI)
Spring 最常与其相关联的技术是反转控制的依赖项注入 (DI) 风格。反转控制 (IoC) 是一个通用概念,并且可以用许多不同的方式来表达。依赖项注入仅仅是反转控制的一个具体示例。
在编写复杂的 Java 应用程序时,应用程序类与其它的 Java 类应该尽可能独立,以提高在单元测试时独立于其他类来重复利用和测试这些类的可能性。依赖关系注入有助于将这些类粘合在一起,并同时保持它们的独立性。
依赖关系注入到底是什么?让我们分别看一下这两个词。这里的依赖部分转换成了两个类之间的关联。例如,类 A 依赖于类 B。现在,让我们看一下第二部分,注入。它的全部含义是,类 B 将由 IoC 注入到类 A 中。
依赖关系注入可以通过向构造函数传递参数或通过使用 setter 方法而在构建后执行。由于依赖关系注入是 Spring 框架的核心,因此我们将在一个单独的章节中使用相关的示例来解释这个概念。
Spring DI - Environment Setup
本章将在您开始使用 Spring 框架时,指导您如何准备开发环境。它还将教您在设置 Spring 框架之前如何在您的机器上设置 JDK、Maven 和 Eclipse −
Setup Java Development Kit (JDK)
你可以从 Oracle 的 Java 站点下载 SDK 的最新版本 − Java SE Downloads. 你在下载文件中可以找到安装 JDK 的说明,按照给定的说明进行安装和配置。最后设置 PATH 和 JAVA_HOME 环境变量以引用包含 java 和 javac 的目录,通常分别为 java_install_dir/bin 和 java_install_dir。
如果您运行的是 Windows 且在 C:\jdk-11.0.11 中安装了 JDK,那么您将不得不把以下代码行放入您的 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
或者,如果你使用诸如 Borland JBuilder、Eclipse、IntelliJ IDEA 或 Sun ONE Studio 这样的集成开发环境 (IDE),则必须编译并运行一个简单程序来确认 IDE 知道你在何处安装了 Java。否则,你必须按照 IDE 文档中给出的内容执行正确的设置。
Setup 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
成功启动后,如果一切正常,它应该显示以下结果 −
Set Maven
在本教程中,我们使用 maven 来运行和构建基于 Spring 的示例。请按照 Maven - Environment Setup 安装 maven。
Spring DI - IoC Containers
Spring 容器是 Spring Framework 的核心。容器将创建对象,将它们连接在一起,配置它们,并管理它们从创建到销毁的整个生命周期。Spring 容器使用 DI 来管理构成应用程序的组件。这些对象称为 Spring Bean,我们将在下一章中讨论它们。
容器通过读取提供的配置元数据来获取有关实例化、配置和组装对象的指令。该配置元数据可由 XML、Java 注释或 Java 代码表示。下图展示了 Spring 的工作原理的概述图。Spring IOC 容器利用 Java POJO 类和配置元数据来生成完全配置和可执行的系统或应用程序。
Spring 提供了下列两种不同类型的容器。
Sr.No. |
Container & Description |
1 |
Spring BeanFactory Container 这是最简单的容器,提供对 DI 的基本支持,由 org.springframework.beans.factory.BeanFactory 接口定义。BeanFactory 和相关接口,如 BeanFactoryAware、InitializingBean、DisposableBean,仍然存在于 Spring 中,目的是向大量与 Spring 集成的第三方框架提供向后兼容性。 |
2 |
Spring ApplicationContext Container 此容器增加了更多企业特定的功能,例如能够从属性文件解析文本消息以及向感兴趣的事件侦听器发布应用程序事件。此容器由 org.springframework.context.ApplicationContext 接口定义。 |
ApplicationContext 容器包含 BeanFactory 容器的所有功能,因此通常建议优于 BeanFactory。对于数据量和速度很重要的轻量级应用程序(如移动设备或基于小应用程序的应用程序),仍然可以使用 BeanFactory。
Spring DI - BeanFactory Container
这是提供基本 DI 支持的最简单的容器,由 org.springframework.beans.factory.BeanFactory 接口定义。BeanFactory 及其相关接口(例如 BeanFactoryAware、InitializingBean、DisposableBean)仍然存在于 Spring 中,以便向与 Spring 集成的众多第三方框架提供向后兼容性。
有许多 BeanFactory 接口的实现是 Spring 中自带的。最常用的 BeanFactory 实现是 XmlBeanFactory 类。此容器从 XML 文件中读取配置元数据,并使用该元数据创建一个完全配置的系统或应用程序。
在诸如移动设备或基于小程序的应用程序等资源有限的情况下,通常首选 BeanFactory。因此,除非你有充分的理由不这样做,否则请使用 ApplicationContext。
Example
让我们更新在 Spring DI - Create Project 章节中创建的项目。我们将添加以下文件 −
-
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>
Spring DI - ApplicationContext Container
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 − 此容器从 Web 应用程序中加载包含所有 bean 定义的 XML 文件。
Example
让我们更新在 Spring DI - Create Project 章节中创建的项目。我们将添加以下文件 −
-
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>
Spring DI - Create Project
使用 Eclipse 选择 File → New * → *Maven Project 。勾选 创建简单项目(跳过原型选择),然后单击下一步。
按照以下所示输入详细信息 −
-
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 - Constructor-Based
当容器使用一系列参数调用类构造函数,每个参数表示对其他类的依赖关系时,就完成了基于构造函数的 DI。
Example
以下示例展示了一个类 TextEditor,它只能通过构造函数注入进行依赖注入。
让我们更新在 Spring DI - Create Project 章节中创建的项目。我们将添加以下文件 −
-
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>
Spring DI - Injecting Inner Beans Constructor
众所周知,Java 内部类在其他类的范围内内定义,类似地, inner beans 是在另一个 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>
Example
以下示例显示了一个只能使用基于构造函数的注入进行依赖注入的类 TextEditor。
让我们更新在 Spring DI - Create Project 章节中创建的项目。我们将添加以下文件 −
-
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();
}
}
以下是已配置了基于 setter 的注入,但使用 inner beans 的配置文件 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 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>
Spring DI - Injecting Collections Constructor
您已经看到如何使用 Bean 配置文件中的 <property> 标记的 value 属性配置原始数据类型,以及使用 ref 属性配置对象引用。这两种情况都涉及将奇异值传递给 Bean。
现在,如果您想传递像 Java Collection 类型(比如 List、Set 和 Properties)这样的复数值该怎么办?为了应对这种情况,Spring 提供了以下类型的集合配置元素,如下所示 −
Sr.No |
Element & Description |
1 |
<list> 这有助于进行接线,即注入一个值列表,同时允许重复。 |
2 |
<set> 这有助于接线一组值,但没有任何重复。 |
3 |
<props> 这可用于注入名称-值对的集合,其中名称和值都是字符串。 |
您可以使用 <list> 或 <set> 来接线任何 java.util.Collection 的实现或 array 。
在该示例中,我们展示的是传递集合元素的直接值。
Example
下面的示例展示了 JavaCollection 类,它使用集合作为依赖项,这些集合使用构造函数参数进行注入。
让我们更新在 Spring DI - Create Project 章节中创建的项目。我们将添加以下文件 −
-
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 - Injecting Collections Ref Constructor
您已经看到如何使用 Bean 配置文件中的 <property> 标记的 value 属性配置原始数据类型,以及使用 ref 属性配置对象引用。这两种情况都涉及将奇异值传递给 Bean。
现在,如果您想传递像 Java Collection 类型(比如 List、Set 和 Properties)这样的复数值该怎么办?为了应对这种情况,Spring 提供了以下类型的集合配置元素,如下所示 −
Sr.No |
Element & Description |
1 |
<list> 这有助于进行接线,即注入一个值列表,同时允许重复。 |
2 |
<set> 这有助于接线一组值,但没有任何重复。 |
您可以使用 <list> 或 <set> 来接线任何 java.util.Collection 的实现或 array 。
在此示例中,我们展示了使用 ref 传递集合元素。
Example
以下示例展示了一个 JavaCollection 类,它使用通过 setter 注入的依赖关系集合。
让我们更新在 Spring DI - Create Project 章节中创建的项目。我们将添加以下文件 −
-
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>
Spring DI - Injecting Map Constructor
您已经看到如何使用 Bean 配置文件中的 <property> 标记的 value 属性配置原始数据类型,以及使用 ref 属性配置对象引用。这两种情况都涉及将奇异值传递给 Bean。
现在,如果你想传递 Map,在这个示例中,我们将展示如何使用构造函数注入传递 Map 的直接值。
Example
下面的示例展示了 JavaCollection 类,它使用集合作为依赖项,这些集合使用构造函数参数进行注入。
让我们更新在 Spring DI - Create Project 章节中创建的项目。我们将添加以下文件 −
-
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>
Spring DI - Map Ref Constructor
您已经看到如何使用 Bean 配置文件中的 <property> 标记的 value 属性配置原始数据类型,以及使用 ref 属性配置对象引用。这两种情况都涉及将奇异值传递给 Bean。
现在,如果你想传递 Map,在这个示例中,我们将展示如何使用构造函数注入传递 Map 的直接值。
Example
下面的示例展示了 JavaCollection 类,它使用集合作为依赖项,这些集合使用构造函数参数进行注入。
让我们更新在 Spring DI - Create Project 章节中创建的项目。我们将添加以下文件 −
-
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-Based
基于 Setter 的 DI 由在调用无参数构造函数或无参数静态工厂方法来实例化 bean 之后,容器通过调用你 bean 上的 setter 方法来完成。
Example
以下示例展示了 TextEditor 类,它只能使用纯基于 setter 的注入进行依赖项注入。
让我们更新在 Spring DI - Create Project 章节中创建的项目。我们将添加以下文件 −
-
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();
}
}
以下是用于基于 setter 的注入的配置的配置文件 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">
<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> 标签,对基于 Setter 的注入使用了 <property> 标签。
需要记住的第二项重要内容是如果您传递了对象引用,则需要使用 <property> 标签的 ref 属性,如果您直接传递了 value ,则应该使用 value 属性。
Spring DI - Inner Beans Setter
众所周知,Java 内部类在其他类的范围内内定义,类似地, inner beans 是在另一个 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>
Example
以下示例展示了 TextEditor 类,它只能使用纯基于 setter 的注入进行依赖项注入。
让我们更新在 Spring DI - Create Project 章节中创建的项目。我们将添加以下文件 −
-
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();
}
}
以下是已配置了基于 setter 的注入,但使用 inner beans 的配置文件 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 using inner bean -->
<bean id = "textEditor" class = "com.tutorialspoint.TextEditor">
<property name = "spellChecker">
<bean id = "spellChecker" class = "com.tutorialspoint.SpellChecker"/>
</property>
</bean>
</beans>
Spring DI - Collections Setter
您已经看到如何使用 Bean 配置文件中的 <property> 标记的 value 属性配置原始数据类型,以及使用 ref 属性配置对象引用。这两种情况都涉及将奇异值传递给 Bean。
现在,如果您想传递 Java 集合类型之类的复数值,例如列表、集合、映射和属性,该怎么办。为了应对该情况,Spring 提供了以下类型的集合配置元素:
Sr.No |
Element & Description |
1 |
<list> 这有助于进行接线,即注入一个值列表,同时允许重复。 |
2 |
<set> 这有助于接线一组值,但没有任何重复。 |
3 |
<props> 这可用于注入名称-值对的集合,其中名称和值都是字符串。 |
您可以使用 <list> 或 <set> 来接线任何 java.util.Collection 的实现或 array 。
在该示例中,我们展示的是传递集合元素的直接值。
Example
以下示例显示了一个使用集合作为 Setter 注入的依赖项的 JavaCollection 类。
让我们更新在 Spring DI - Create Project 章节中创建的项目。我们将添加以下文件 −
-
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>
Sprint DI - Collections Ref Setter
您已经看到如何使用 Bean 配置文件中的 <property> 标记的 value 属性配置原始数据类型,以及使用 ref 属性配置对象引用。这两种情况都涉及将奇异值传递给 Bean。
现在,如果您想传递 Java 集合类型之类的复数值,例如列表、集合、映射和属性,该怎么办。为了应对该情况,Spring 提供了以下类型的集合配置元素:
Sr.No |
Element & Description |
1 |
<list> 这有助于进行接线,即注入一个值列表,同时允许重复。 |
2 |
<set> 这有助于接线一组值,但没有任何重复。 |
您可以使用 <list> 或 <set> 来接线任何 java.util.Collection 的实现或 array 。
在此示例中,我们展示了使用 ref 传递集合元素。
Example
以下示例展示了一个 JavaCollection 类,它使用通过 setter 注入的依赖关系集合。
让我们更新在 Spring DI - Create Project 章节中创建的项目。我们将添加以下文件 −
-
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>
Spring DI - Map Setter
您已经看到如何使用 Bean 配置文件中的 <property> 标记的 value 属性配置原始数据类型,以及使用 ref 属性配置对象引用。这两种情况都涉及将奇异值传递给 Bean。
现在,如果你想传递 Map,该怎么办?在本示例中,我们展示使用 setter 注入传递 Map 的直接值。
Example
以下示例展示了一个类 JavaCollection,该类使用集合作为依赖关系,并使用 setter 方法进行注入。
让我们更新在 Spring DI - Create Project 章节中创建的项目。我们将添加以下文件 −
-
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>
Spring DI - Map Ref Setter
您已经看到如何使用 Bean 配置文件中的 <property> 标记的 value 属性配置原始数据类型,以及使用 ref 属性配置对象引用。这两种情况都涉及将奇异值传递给 Bean。
现在,如果你想传递 Map,该怎么办?在本示例中,我们展示使用 setter 注入传递 Map 的直接值。
Example
以下示例展示了一个类 JavaCollection,该类使用集合作为依赖关系,并使用 setter 方法进行注入。
让我们更新在 Spring DI - Create Project 章节中创建的项目。我们将添加以下文件 −
-
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>
Spring DI - Autowiring
你已了解如何使用 <bean> 元素声明 bean,并使用 XML 配置文件中的 <constructor-arg> 和 <property> 元素注入 <bean>。
Spring 容器可以在不使用 <constructor-arg> 和 <property> 元素的情况下确定协作 bean 之间的关系,这有助于减少为大型基于 Spring 的应用程序编写的 XML 配置量。
Autowiring Modes
以下是自动装配模式,可以用于指示 Spring 容器对依赖项注入使用自动装配。你可以使用 <bean/> 元素的 autowire 属性来为 bean 定义指定 autowire 模式。
Sr.No |
Mode & Description |
1 |
no 这是默认设置,表示没有自动装配,你应该使用显式 bean 引用进行装配。你不需要做任何特殊的事情进行这种装配。这就是你已经在依赖注入章节中看到的内容。 |
2 |
byName 按属性名称自动装配。Spring 容器会查看 XML 配置文件中将 autowire 属性设置为 byName 的 Bean 的属性。然后,它会尝试匹配并将其属性与配置文件中同名 bean 进行装配。 |
3 |
byType 按属性数据类型自动装配。Spring 容器会查看 XML 配置文件中将 autowire 属性设置为 byType 的 Bean 的属性。然后,如果 bean 名称中的一个与属性 type 完全匹配,它会尝试匹配并装配该属性。如果存在多个这样的 bean,就会抛出致命异常。 |
4 |
constructor 类似于 byType,但类型适用于构造函数参数。如果容器中构造函数参数的 bean 不完全是一个,则会引发致命错误。 |
5 |
autodetect Spring 先尝试使用构造函数按参数自动装配,如果不能,Spring 会尝试按类型自动装配。 |
你可以使用 byType 或 constructor 自动装配模式来连接数组和其他类型集合。
Limitations with autowiring
当在整个项目中一致使用时,自动装配效果最好。如果通常不使用自动装配,开发人员仅将其用于连接一个或两个 Bean 定义可能会令人迷惑。尽管如此,自动装配可以显著减少指定属性或构造函数参数的需要,但你应在使用自动装配前考虑其局限性和缺点。
Sr.No. |
Limitations & Description |
1 |
Overriding possibility 你仍然可以使用 <constructor-arg> 和 <property> 设置来指定依赖,这将始终覆盖自动装配。 |
2 |
Primitive data types 你不能自动装配原始类型、字符串和类等所谓的简单属性。 |
3 |
Confusing nature 自动装配不像显式装配那么精确,所以如果可能,最好使用显式装配。 |
Spring DI - Autowiring ByName
该模式指定按属性名称自动注入。Spring 容器查看在 XML 配置文件中将 auto-wire 属性设置为 byName 的 bean。然后,它尝试匹配并将其属性与配置中由相同名称定义的 bean 进行关联。如果找到匹配项,它将注入这些 bean。否则,将不关联 bean。
例如,如果将 bean 定义设置为在配置按 byName 自动关联,并且它包含一个 spellChecker 属性(也就是说,它有一个 setSpellChecker(…)方法),Spring 将寻找名为 spellChecker 的 bean 定义,并使用它设置该属性。您仍然可以使用 <property> 标记关联剩余的属性。以下示例将说明该概念。
Example
以下示例展示了 TextEditor 类,它只能使用纯基于 setter 的注入进行依赖项注入。
让我们更新在 Spring DI - Create Project 章节中创建的项目。我们将添加以下文件 −
-
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>
Spring DI - Autowiring ByType
这种模式通过属性类型指定自动装配。Spring 容器查找那些在 XML 配置文件中将自动装配属性设置为按类型(byType)的 Bean。然后,它尝试匹配和连接一个属性,如果它的 type 准确地匹配配置文件中的一个 Bean 名称。如果找到匹配,它将注入这些 Bean。否则,将不会连接 Bean。
例如,如果将 Bean 定义设置为在配置文件中按类型自动装配,并且它包含 SpellChecker 类型名为 spellChecker 的属性,Spring 将查找名为 SpellChecker 的 Bean 定义,并使用它来设置该属性。您仍然可以使用 <property> 标记连接剩余的属性。以下示例将说明这个概念。
Example
以下示例展示了 TextEditor 类,它只能使用纯基于 setter 的注入进行依赖项注入。
让我们更新在 Spring DI - Create Project 章节中创建的项目。我们将添加以下文件 −
-
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>
Spring DI - Autowiring Constructor
该模式与 byType 非常相似,但适用于构造函数参数。Spring 容器查看在 XML 配置文件中将 autowire 属性设置为 constructor 的 bean。然后,它尝试匹配并将其构造函数的参数与配置中恰好一个 bean 名称关联。如果找到匹配项,它将注入这些 bean。否则,将不关联 bean。
例如,如果将 bean 定义设置为在配置按构造函数自动关联,并且它有一个构造函数,该构造函数的一个参数为 SpellChecker 类型,Spring 将寻找名为 SpellChecker 的 bean 定义,并使用它设置构造函数的参数。您仍然可以使用 <constructor-arg> 标记关联剩余的参数。以下示例将说明这个概念。
Example
以下示例显示了一个只能使用构造函数进行依赖注入的 TextEditor 类。
让我们更新在 Spring DI - Create Project 章节中创建的项目。我们将添加以下文件 −
-
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>
Spring DI - Static Factory
Spring 提供了一个使用 factory-method 属性注入相关依赖项的选项。
Example
以下示例展示了 TextEditor 类,它只能使用纯基于 setter 的注入进行依赖项注入。
让我们更新在 Spring DI - Create Project 章节中创建的项目。我们将添加以下文件 −
-
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 - Non-Static Factory
Spring 提供了一个选项,可以使用工厂方法和工厂 bean 属性注入依赖项,以用于非静态工厂方法。
Example
以下示例展示了 TextEditor 类,它只能使用纯基于 setter 的注入进行依赖项注入。
让我们更新在 Spring DI - Create Project 章节中创建的项目。我们将添加以下文件 −
-
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>