Spring Bean属性注入

8个月前 (04-28)
所谓 Bean 属性注入,简单点说就是将属性注入到 Bean 中的过程,而这属性既可以普通属性,也可以是一个对象(Bean)。

Spring 主要通过以下 2 种方式实现属性注入:
  • 构造函数注入

  • setter 注入(又称设值注入)

构造函数注入

我们可以通过 Bean 的带参构造函数,以实现 Bean 的属性注入。

使用构造函数实现属性注入大致步骤如下:

  1. 在 Bean 中添加一个有参构造函数,构造函数内的每一个参数代表一个需要注入的属性;

  2. 在 Spring 的 XML 配置文件中,通过 <beans> 及其子元素 <bean> 对 Bean 进行定义;

  3. 在 <bean> 元素内使用 <constructor-arg> 元素,对构造函数内的属性进行赋值,Bean 的构造函数内有多少参数,就需要使用多少个 <constructor-arg> 元素。

示例 1

下面我们就通过一个实例,来演示下如何构造函数注入的方式实现属性注入。

1. 新建一个名为 my-spring-demo 的 Java 项目,并在 src 下创建一个名为 net.biancheng.c 的包。

2. 参考《个Spring程序》,向项目中导入所需的 Jar 包。

3. 在 net.biancheng.c 包下,创建一个名为 Grade 的类,代码如下。

package net.biancheng.c;

import org.apac站站点" rel="nofollow" />

package net.biancheng.c;

import org.apac站站点" rel="nofollow" />

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework网站站点" rel="nofollow" />

package net.biancheng.c;

import org.apac站站点" rel="nofollow" />

十二月 16, 2021 4:38:42 下午 net.biancheng.c.Grade <init>

信息: 正在执行 Course 的有参构造方法,参数分别为:gradeId=4,gradeName=四年级

十二月 16, 2021 4:38:42 下午 net.biancheng.c.Student <init>

信息: 正在执行 Course 的有参构造方法,参数分别为:id=2,name=李四,grade=Grade{gradeId=4, gradeName='四年级'}

十二月 16, 2021 4:38:42 下午 net.biancheng.c.MainApp main

信息: Student{id=2, name='李四', grade=Grade{gradeId=4, gradeName='四年级'}}

setter 注入

我们可以通过 Bean 的 setter 方法,将属性值注入到 Bean 的属性中。

在 Spring 实例化 Bean 的过程中,IoC 容器首先会调用默认的构造方法(无参构造方法)实例化 Bean(Java 对象),然后通过 Java 的反射机制调用这个 Bean 的 setX () 方法,将属性值注入到 Bean 中。

使用 setter 注入的方式进行属性注入,大致步骤如下:

  1. 在 Bean 中提供一个默认的无参构造函数(在没有其他带参构造函数的情况下,可省略),并为所有需要注入的属性提供一个 setX () 方法;

  2. 在 Spring 的 XML 配置文件中,使用 <beans> 及其子元素 <bean> 对 Bean 进行定义;

  3. 在 <bean> 元素内使用  <property> 元素对各个属性进行赋值。

示例 2

下面,我们就通过一个实例,来演示如何通过 setter 注入的方式实现属性注入,步骤如下。

1. 在 net.biancheng.c 包下,修改 Student 类的代码。

package net.biancheng.c;

import org.apac站站点" rel="nofollow" />

package net.biancheng.c;

import org.apac站站点" rel="nofollow" />

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework网站站点" rel="nofollow" />

十二月 16, 2021 4:01:13 下午 net.biancheng.c.Grade setGradeId

信息: 正在执行 Grade 类的 setGradeId() 方法……

十二月 16, 2021 4:01:13 下午 net.biancheng.c.Grade setGradeName

信息: 正在执行 Grade 类的 setGradeName() 方法……

十二月 16, 2021 4:01:13 下午 net.biancheng.c.Student setId

信息: 正在执行 Student 类的 setId() 方法……

十二月 16, 2021 4:01:13 下午 net.biancheng.c.Student setName

信息: 正在执行 Student 类的 setName() 方法……

十二月 16, 2021 4:01:13 下午 net.biancheng.c.Student setGrade

信息: 正在执行 Student 类的 setGrade() 方法……

十二月 16, 2021 4:01:13 下午 net.biancheng.c.MainApp main

信息: Student{id=1, name='张三', grade=Grade{gradeId=3, gradeName='三年级'}}

短名空间注入

我们在通过构造函数或 setter 方法进行属性注入时,通常是在 <bean> 元素中嵌套 <property> 和 <constructor-arg> 元素来实现的。这种方式虽然结构清晰,但书写较繁琐。

Spring 框架提供了 2 种短名空间,可以简化 Spring 的 XML 配置,如下表。

短名空间

简化的 XML 配置

说明

p 名空间

<bean> 元素中嵌套的 <property> 元素

是 setter 方式属性注入的一种快捷实现方式

c 名空间

<bean> 元素中嵌套的 <constructor> 元素

是构造函数属性注入的一种快捷实现方式

p 名空间注入

p 名空间是 setter 方式属性注入的一种快捷实现方式。通过它,我们能够以 bean 属性的形式实现 setter 方式的属性注入,而不再使用嵌套的 <property> 元素,以实现简化 Spring 的 XML 配置的目的。

首先我们需要在配置文件的 <beans> 元素中导入以下 XML 约束。

xmlns:p="http://www.springframework网站站点" rel="nofollow" />

<bean id="Bean 标志符" class="包名+类名" p:普通属性="普通属性值" p:对象属性-ref="对象的引用">


使用 p 名空间注入依赖时,必须注意以下 3 点:

  • Java 类中必须有 setter 方法;

  • Java 类中必须有无参构造器(类中不包含任何带参构造函数的情况,无参构造函数默认存在);

  • 在使用 p 名空间实现属性注入前,XML 配置的 <beans> 元素内必须先导入 p 名空间的 XML 约束。

示例

下面我们通过一个简单的实例,演示下如何通过 p 名空间实现属性注入。

1. 参考《个 Spring程序》,新建一个名为 my-spring-demo6 的 Java 项目。

2. 在 net.biancheng.c 包中,创建一个名为 Dept 的类,代码如下。

package net.biancheng.c;

public class Dept {

//部门编号

private String deptNo;

//部门名称

private String deptName;

public void setDeptNo(String deptNo) {

this.deptNo = deptNo;

}

public void setDeptName(String deptName) {

this.deptName = deptName;

}

@Override

public String toString() {

return "Dept{" +

"deptNo='" + deptNo + '\'' +

", deptName='" + deptName + '\'' +

'}';

}

}


3. 在 net.biancheng.c 包下,创建一个名为 Employee 的类,代码如下。

package net.biancheng.c;

public class Employee {

//员工编号

private String empNo;

//员工姓名

private String empName;

//部门信息

private Dept dept;

public void setEmpNo(String empNo) {

this.empNo = empNo;

}

public void setEmpName(String empName) {

this.empName = empName;

}

public void setDept(Dept dept) {

this.dept = dept;

}

public Dept getDept() {

return dept;

}

@Override

public String toString() {

return "Employee{" +

"empNo='" + empNo + '\'' +

", empName='" + empName + '\'' +

", dept=" + dept +

'}';

}

}


4. 在 src 目录下创建 Spring 配置文件 Beans.xml,配置如下。

<beans xmlns="http://www.springframework网站站点" rel="nofollow" />

package net.biancheng.c;

import org.apac站站点" rel="nofollow" />

十二月 20, 2021 3:18:54 下午 net.biancheng.c.MainApp main

信息: Employee{empNo='22222', empName='小李', dept=Dept{deptNo='1111', deptName='技术部'}}

c 名空间注入

c 名空间是构造函数注入的一种快捷实现方式。通过它,我们能够以 <bean> 属性的形式实现构造函数方式的属性注入,而不再使用嵌套的 <constructor-arg> 元素,以实现简化 Spring 的 XML 配置的目的。

首先我们需要在配置文件的 <beans> 元素中导入以下 XML 约束。

xmlns:c="http://www.springframework网站站点" rel="nofollow" />

<bean id="Bean 标志符" class="包名+类名" c:普通属性="普通属性值" c:对象属性-ref="对象的引用">


使用 c 名空间注入依赖时,必须注意以下 2 点:

  • Java 类中必须包含对应的带参构造器;

  • 在使用 c 名空间实现属性注入前,XML 配置的 <beans> 元素内必须先导入 c 名空间的 XML 约束。

示例

下面我们通过一个简单的实例,演示下如何通过 c 名空间实现属性注入。

1. 修改 Dept 中的代码,添加一个有参构造函数。

package net.biancheng.c;

public class Dept {

//部门编号

private String deptNo;

//部门名称

private String deptName;

public Dept(String deptNo, String deptName) {

this.deptNo = deptNo;

this.deptName = deptName;

}

@Override

public String toString() {

return "Dept{" +

"deptNo='" + deptNo + '\'' +

", deptName='" + deptName + '\'' +

'}';

}

}


2. 修改 Employee 中的代码,添加一个有参构造函数。

package net.biancheng.c;

public class Employee {

//员工编号

private String empNo;

//员工姓名

private String empName;

//部门信息

private Dept dept;

public Employee(String empNo, String empName, Dept dept) {

this.empNo = empNo;

this.empName = empName;

this.dept = dept;

}

@Override

public String toString() {

return "Employee{" +

"empNo='" + empNo + '\'' +

", empName='" + empName + '\'' +

", dept=" + dept +

'}';

}

}


3. 修改 Beans.xml 中的配置,使用 c 名空间实现属性注入。

<beans xmlns="http://www.springframework网站站点" rel="nofollow" />

十二月 20, 2021 3:35:33 下午 net.biancheng.c.MainApp main

信息: Employee{empNo='999', empName='小胡', dept=Dept{deptNo='2222', deptName='测试部'}}