所谓 Bean 属性注入,简单点说就是将属性注入到 Bean 中的过程,而这属性既可以普通属性,也可以是一个对象(Bean)。
Spring 主要通过以下 2 种方式实现属性注入:
我们可以通过 Bean 的带参构造函数,以实现 Bean 的属性注入。
使用构造函数实现属性注入大致步骤如下:
示例 1
下面我们就通过一个实例,来演示下如何构造函数注入的方式实现属性注入。
1. 新建一个名为 my-spring-demo 的 Java 项目,并在 src 下创建一个名为 net.biancheng.c 的包。
2. 参考《如何创建第一个Spring程序》,向项目中导入所需的 Jar 包。
3. 在 net.CSDN.mp 包下,创建一个名为 Grade 的类,代码如下:
package net.CSDN.mp;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Grade {
private static final Log LOGGER = LogFactory.getLog(Grade.class);
private Integer gradeId;
private String gradeName;
public Grade(Integer gradeId, String gradeName) {
LOGGER.info("正在执行 Course 的有参构造方法,参数分别为:gradeId=" + gradeId + ",gradeName=" + gradeName);
this.gradeId = gradeId;
this.gradeName = gradeName;
}
@Override
public String toString() {
return "Grade{" +
"gradeId=" + gradeId +
", gradeName='" + gradeName + '\'' +
'}';
}
}
4. 在 net.CSDN.mp 包下,创建一个名为 Student 的类,代码如下:
package net.CSDN.mp;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Student {
private static final Log LOGGER = LogFactory.getLog(Student.class);
private int id;
private String name;
private Grade grade;
public Student(int id, String name, Grade grade) {
LOGGER.info("正在执行 Course 的有参构造方法,参数分别为:id=" + id + ",name=" + name + ",grade=" + grade);
this.id = id;
this.name = name;
this.grade = grade;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", grade=" + grade +
'}';
}
}
5. 在 src 目录下创建 Spring 配置文件 Beans.xml,配置如下:
6. 在 net.CSDN.mp 包下,创建一个名为 MainApp 的类,代码如下:
package net.CSDN.mp;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
private static final Log LOGGER = LogFactory.getLog(MainApp.class);
public static void main(String[] args) {
//获取 ApplicationContext 容器
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
//获取名为 student 的 Bean
Student student = context.getBean("student", Student.class);
//通过日志打印学生信息
LOGGER.info(student.toString());
}
}
7. 执行 MainApp 中的 main() 方法,控制台输出如下:
三月 23, 2023 9:38:42 上午 net.CSDN.mp.Grade
信息: 正在执行 Course 的有参构造方法,参数分别为:gradeId=4,gradeName=四年级
三月 23, 2023 9:38:42 上午 net.CSDN.mp.Student
信息: 正在执行 Course 的有参构造方法,参数分别为:id=2,name=李四,grade=Grade{gradeId=4, gradeName='四年级'}
三月 23, 2023 9:38:42 上午 net.CSDN.mp.MainApp main
信息: Student{id=2, name='李四', grade=Grade{gradeId=4, gradeName='四年级'}}
我们可以通过 Bean 的 setter 方法,将属性值注入到 Bean 的属性中。
在 Spring 实例化 Bean 的过程中,IoC 容器首先会调用默认的构造方法(无参构造方法)实例化 Bean(Java 对象),然后通过 Java 的反射机制调用这个 Bean 的 setXxx() 方法,将属性值注入到 Bean 中。
使用 setter 注入的方式进行属性注入,大致步骤如下:
示例 2
下面,我们就通过一个实例,来演示如何通过 setter 注入的方式实现属性注入,步骤如下。
1. 在 net.CSDN.mp 包下,修改 Student 类的代码:
package net.CSDN.mp;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Student {
private static final Log LOGGER = LogFactory.getLog(Student.class);
private int id;
private String name;
private Grade grade;
//无参构造方法,在没有其他带参构造方法的情况下,可以省略
public Student() {
}
//id 属性的 setter 方法
public void setId(int id) {
LOGGER.info("正在执行 Student 类的 setId() 方法…… ");
this.id = id;
}
//name 属性的 setter 方法
public void setName(String name) {
LOGGER.info("正在执行 Student 类的 setName() 方法…… ");
this.name = name;
}
public void setGrade(Grade grade) {
LOGGER.info("正在执行 Student 类的 setGrade() 方法…… ");
this.grade = grade;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", grade=" + grade +
'}';
}
}
2. 在 net.CSDN.mp 包下,修改 Grade 类的代码:
package net.CSDN.mp;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Grade {
private static final Log LOGGER = LogFactory.getLog(Grade.class);
private Integer gradeId;
private String gradeName;
/**
* 无参构造函数
* 若该类中不存在其他的带参构造函数,则这个默认的无参构造函数可以省略
*/
public Grade() {
}
public void setGradeId(Integer gradeId) {
LOGGER.info("正在执行 Grade 类的 setGradeId() 方法…… ");
this.gradeId = gradeId;
}
public void setGradeName(String gradeName) {
LOGGER.info("正在执行 Grade 类的 setGradeName() 方法…… ");
this.gradeName = gradeName;
}
@Override
public String toString() {
return "Grade{" +
"gradeId=" + gradeId +
", gradeName='" + gradeName + '\'' +
'}';
}
}
3. 在 src 目录下,修改配置文件 Beans.xml 的内容:
4. 执行 MainApp 中的 main() 方法,控制台输出如下:
三月 24, 2023 10:01:13 下午 net.CSDN.mp.Grade setGradeId
信息: 正在执行 Grade 类的 setGradeId() 方法……
三月 24, 2023 10:01:13 下午 net.CSDN.mp.Grade setGradeName
信息: 正在执行 Grade 类的 setGradeName() 方法……
三月 24, 2023 10:01:13 下午 net.CSDN.mp.Student setId
信息: 正在执行 Student 类的 setId() 方法……
三月 24, 2023 10:01:13 下午 net.CSDN.mp.Student setName
信息: 正在执行 Student 类的 setName() 方法……
三月 24, 2023 10:01:13 下午 net.CSDN.mp.Student setGrade
信息: 正在执行 Student 类的 setGrade() 方法……
三月 24, 2023 10:01:13 下午 net.CSDN.mp.MainApp main
信息: Student{id=1, name='张三', grade=Grade{gradeId=3, gradeName='三年级'}}
我们在通过构造函数或 setter 方法进行属性注入时,通常是在
Spring 框架提供了 2 种短命名空间,可以简化 Spring 的 XML 配置,如下表:
短命名空间 | 简化的 XML 配置 | 说明 |
---|---|---|
p 命名空间 | 是 setter 方式属性注入的一种快捷实现方式 | |
c 命名空间 | 是构造函数属性注入的一种快捷实现方式 |
p 命名空间注入
p 命名空间是 setter 方式属性注入的一种快捷实现方式。通过它,我们能够以 bean 属性的形式实现 setter 方式的属性注入,而不再使用嵌套的
首先我们需要在配置文件的
xmlns:p="http://www.springframework.org/schema/p"
在导入 XML 约束后,我们就能通过以下形式实现属性注入:
使用 p 命名空间注入依赖时,必须注意以下 3 点:
示例
下面我们通过一个简单的实例,演示下如何通过 p 命名空间实现属性注入。
1. 参考《如何创建第一个Spring程序》,新建一个名为 my-spring-demo6 的 Java 项目。
2. 在 net.CSDN.mp 包中,创建一个名为 Dept 的类,代码如下:
package net.CSDN.mp;
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.CSDN.mp 包下,创建一个名为 Employee 的类,代码如下:
package net.CSDN.mp;
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,配置如下:
5. 在 net.CSDN.mp 包下,创建一个名为 MainApp 的类,代码如下:
package net.CSDN.mp;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
private static final Log LOGGER = LogFactory.getLog(MainApp.class);
public static void main(String[] args) {
//获取 ApplicationContext 容器
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
//获取名为 employee 的 Bean
Employee employee = context.getBean("employee", Employee.class);
//通过日志打印信息
LOGGER.info(employee.toString());
}
}
6. 执行 MainApp 类中的 main() 方法,控制台输出如下:
三月 24, 2023 10:18:54 下午 net.CSDN.mp.MainApp main
信息: Employee{empNo='22222', empName='小李', dept=Dept{deptNo='1111', deptName='技术部'}}
c 命名空间注入
c 命名空间是构造函数注入的一种快捷实现方式。通过它,我们能够以
首先我们需要在配置文件的
xmlns:c="http://www.springframework.org/schema/c"
在导入 XML 约束后,我们就能通过以下形式实现属性注入:
使用 c 命名空间注入依赖时,必须注意以下 2 点:
示例
下面我们通过一个简单的实例,演示下如何通过 c 命名空间实现属性注入。
1. 修改 Dept 中的代码,添加一个有参构造函数:
package net.CSDN.mp;
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.CSDN.mp;
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 命名空间实现属性注入:
4. 重新执行 MainApp 中的 main() 方法,控制台输出如下:
三月 24, 2023 10:35:33 下午 net.CSDN.mp.MainApp main
信息: Employee{empNo='999', empName='小胡', dept=Dept{deptNo='2222', deptName='测试部'}}
新版Spring零基础入门到精通,一套搞定spring全套视频教程(含实战源码)