7.2 Spring Bean 注入内部 Bean
我们将定义在 <bean>
元素的 <property>
或 <constructor-arg>
元素内部的 Bean,称为 内部 Bean 。
1. 构造函数方式注入
我们可以通过构造方法注入内部 Bean。此时,我们只需要在 <bean>
标签下的 <constructor-arg>
元素中,再次使用 <bean>
元素对内部 Bean 进行定义。
格式如下:
<bean id="……" class="……">
<constructor-arg name="……">
<!--内部 Bean-->
<bean class="……">
<constructor-arg name="……" value="……"></constructor-arg>
……
</bean>
</constructor-arg>
</bean>
例 1
下面我们就通过一个实例,演示下如何在通过构造方法的方式注入内部 Bean。
创建命名为 Department 的类,代码如下:
package section2.demo1;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* ClassName: Department
* Description: TODO
*
* @author chuanlu
* @version 1.0.0
*/
public class Department {
private static final Log LOGGER = LogFactory.getLog(Department.class);
// 部门编号
private String deptNo;
// 部门名称
private String deptName;
public Department(String deptNo, String deptName) {
LOGGER.info("正在执行 Course 的有参构造方法,参数分别为:deptNo=" + deptNo + ",deptName=" + deptName);
this.deptNo = deptNo;
this.deptName = deptName;
}
@Override
public String toString() {
return "Dept{" +
"deptNo='" + deptNo + '\'' +
", deptName='" + deptName + '\'' +
'}';
}
}
创建命名为 Employee 的类,代码如下:
package section2.demo1;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* ClassName: Employee
* Description: TODO
*
* @author chuanlu
* @version 1.0.0
*/
public class Employee {
private static final Log LOGGER = LogFactory.getLog(Employee.class);
// 员工编号
private String empNo;
// 员工姓名
private String empName;
// 员工所属部门
private Department dept;
public Employee(String empNo, String empName, Department dept) {
LOGGER.info("正在执行 Course 的有参构造方法,参数分别为:empNo=" + empNo + ",empName=" + empName + ",dept=" + dept);
this.empNo = empNo;
this.empName = empName;
this.dept = dept;
}
@Override
public String toString() {
return "Employee{" +
"empNo='" + empNo + '\'' +
", empName='" + empName + '\'' +
", dept=" + dept +
'}';
}
}
修改 Spring 配置文件 spring-config.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.xsd">
<bean id="employee" class="section2.demo1.Employee">
<constructor-arg name="empNo" value="9527"/>
<constructor-arg name="empName" value="传陆"/>
<constructor-arg name="dept">
<!--内部 Bean-->
<bean class="section2.demo1.Department">
<constructor-arg name="deptNo" value="007"/>
<constructor-arg name="deptName" value="研发部"/>
</bean>
</constructor-arg>
</bean>
</beans>
创建命名为 MainApp 的类,代码如下:
package section2.demo1;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* ClassName: MainApp
* Description: TODO
*
* @author chuanlu
* @version 1.0.0
*/
public class MainApp {
private static final Log LOGGER = LogFactory.getLog(MainApp.class);
public static void main(String[] args) {
//获取 ApplicationContext 容器
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
//获取名为 employee 的 Bean
Employee employee = context.getBean("employee", Employee.class);
//通过日志打印信息
LOGGER.info(employee.toString());
}
}
执行 MainApp 中的 main 方法,控制台输出如下:
4月 08, 2022 12:14:15 下午 section2.demo1.Department <init>
信息: 正在执行 Course 的有参构造方法,参数分别为:deptNo=007,deptName=研发部
4月 08, 2022 12:14:15 下午 section2.demo1.Employee <init>
信息: 正在执行 Course 的有参构造方法,参数分别为:empNo=9527,empName=传陆,dept=Dept{deptNo='007', deptName='研发部'}
4月 08, 2022 12:14:15 下午 section2.demo1.MainApp main
信息: Employee{empNo='9527', empName='传陆', dept=Dept{deptNo='007', deptName='研发部'}}
2. setter 方法注入
我们可以通过 setter 方法注入内部 Bean。此时,我们只需要在 <bean>
标签下的 <constructor-arg>
元素中,再次使用 <bean>
元素对内部 Bean 进行定义。
格式如下:
<bean id="outerBean" class="……">
<property name="……" >
<!-- 定义内部 Bean -->
<bean class="……">
<property name="……" value="……" ></property>
……
</bean>
</property>
</bean>
注意:内部 Bean 都是匿名的,不需要指定 id 和 name 的。即使制定了,IoC 容器也不会将它作为区分 Bean 的标识符,反而会无视 Bean 的 Scope 标签。因此内部 Bean 几乎总是匿名的,且总会随着外部的 Bean 创建。内部 Bean 是无法被注入到它所在的 Bean 以外的任何其他 Bean 的。
例 2
下面我们就通过一个实例,演示下如何使用 setter 方法注入内部 Bean。
创建命名为 Department 的类,代码如下:
package section2.demo2;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* ClassName: Department
* Description: TODO
*
* @author chuanlu
* @version 1.0.0
*/
public class Department {
private static final Log LOGGER = LogFactory.getLog(Department.class);
// 部门编号
private String deptNo;
// 部门名称
private String deptName;
// 无参构造方法,在没有其他带参构造方法的情况下,可以省略
public Department() {
}
public void setDeptNo(String deptNo) {
LOGGER.info("正在执行 Department 类的 setDeptNo() 方法…… ");
this.deptNo = deptNo;
}
public void setDeptName(String deptName) {
LOGGER.info("正在执行 Department 类的 setDeptName() 方法…… ");
this.deptName = deptName;
}
@Override
public String toString() {
return "Dept{" +
"deptNo='" + deptNo + '\'' +
", deptName='" + deptName + '\'' +
'}';
}
}
创建命名为 Employee 的类,代码如下:
package section2.demo2;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* ClassName: Employee
* Description: TODO
*
* @author chuanlu
* @version 1.0.0
*/
public class Employee {
private static final Log LOGGER = LogFactory.getLog(Employee.class);
// 员工编号
private String empNo;
// 员工姓名
private String empName;
// 部门信息
private Department dept;
// 无参构造方法,在没有其他带参构造方法的情况下,可以省略
public Employee() {
}
public void setEmpNo(String empNo) {
LOGGER.info("正在执行 Employee 类的 setEmpNo() 方法…… ");
this.empNo = empNo;
}
public void setEmpName(String empName) {
LOGGER.info("正在执行 Employee 类的 setEmpName() 方法…… ");
this.empName = empName;
}
public void setDept(Department dept) {
LOGGER.info("正在执行 Employee 类的 setDept() 方法…… ");
this.dept = dept;
}
@Override
public String toString() {
return "Employee{" +
"empNo='" + empNo + '\'' +
", empName='" + empName + '\'' +
", dept=" + dept +
'}';
}
}
修改 Spring 配置文件 spring-config.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.xsd">
<bean id="employee" class="section2.demo2.Employee">
<property name="empNo" value="9527"/>
<property name="empName" value="小王"/>
<property name="dept">
<!--内部 Bean-->
<bean class="section2.demo2.Department">
<property name="deptNo" value="007"/>
<property name="deptName" value="研发部"/>
</bean>
</property>
</bean>
</beans>
创建命名为 MainApp 的类,代码如下:
package section2.demo2;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* ClassName: MainApp
* Description: TODO
*
* @author chuanlu
* @version 1.0.0
*/
public class MainApp {
private static final Log LOGGER = LogFactory.getLog(MainApp.class);
public static void main(String[] args) {
//获取 ApplicationContext 容器
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
//获取名为 employee 的 Bean
Employee employee = context.getBean("employee", Employee.class);
//通过日志打印信息
LOGGER.info(employee.toString());
}
}
执行 MainApp 中的 main 方法,控制台输出如下:
4月 08, 2022 12:20:00 下午 section2.demo2.Department setDeptNo
信息: 正在执行 Department 类的 setDeptNo() 方法……
4月 08, 2022 12:20:00 下午 section2.demo2.Department setDeptName
信息: 正在执行 Department 类的 setDeptName() 方法……
4月 08, 2022 12:20:00 下午 section2.demo2.Employee setEmpNo
信息: 正在执行 Employee 类的 setEmpNo() 方法……
4月 08, 2022 12:20:00 下午 section2.demo2.Employee setEmpName
信息: 正在执行 Employee 类的 setEmpName() 方法……
4月 08, 2022 12:20:00 下午 section2.demo2.Employee setDept
信息: 正在执行 Employee 类的 setDept() 方法……
4月 08, 2022 12:20:00 下午 section2.demo2.MainApp main
信息: Employee{empNo='9527', empName='小王', dept=Dept{deptNo='007', deptName='研发部'}}