Spring Bean定义继承
就像面向对象语言中使用OOPS继承概念一样,子类可以继承父类的属性和方法,这与Spring框架中子bean可以从父定义继承配置数据的方式相同。在这篇文章中,我们将看到bean定义继承在Spring中的工作方式。
Spring中的Bean定义继承
Bean定义可以包含许多配置信息,包括构造函数参数,属性值和特定于容器的信息,例如初始化方法,静态工厂方法名称等。子bean定义可以从父bean继承该配置信息,而不必再次定义所有内容。子定义可以覆盖某些值或者根据需要添加其他值。
bean定义继承如何工作
使用<bean>元素的parent属性指定在子bean定义中继承的父bean定义。例如,在以下配置中,empBean使用父属性继承了父bean定义,它从父bean定义继承了属性company,并添加了自己的name属性。
<bean id="baseEmpBean" class="com.theitroad.Employee">
<property name="company" value="XYZ"/>
</bean>
<bean id="empBean" parent="baseEmpBean">
<property name="name" value="Hyman" />
</bean>
在配置中,我们可以看到子bean定义未指定bean类。
子bean定义不需要指定bean类,它可以使用父定义中的bean类。尽管子bean定义也可以覆盖bean类,但如果这样做,则子bean类必须与父类兼容(也就是说,它必须接受父类的属性值)。例如
<bean id="parentBean" class="com.theitroad.TestBean"> <property name="name" value="parent"/> <property name="mode" value="inherit"/> </bean> <bean id="childBean" class="org.springframework.beans.DerivedTestBean" parent="inheritedTestBean" > <property name="name" value="override"/> <!-- mode property value will be inherited from parent --> </bean>
Spring Bean定义继承示例
在示例中,有一个Bean类Employee,其属性为empId,empName,company,dept。在公司属性的父定义值中,分配了由子bean定义继承的值。
public class Employee {
int empId;
String empName;
String company;
String dept;
public int getEmpId() {
return empId;
}
public void setEmpId(int empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public String getDept() {
return dept;
}
public void setDept(String dept) {
this.dept = dept;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
@Override
public String toString() {
return "Id= " + getEmpId() + " Name= " +
getEmpName() + " Dept= "+ getDept()
+ " Company= " + getCompany();
}
}
组态
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="baseEmpBean" class="com.theitroad.springproject.model.Employee">
<property name="company" value="XYZ"/>
</bean>
<bean id="empBean" parent="baseEmpBean">
<property name="empId" value="1" />
<property name="empName" value="Hyman" />
<property name="dept" value="HR" />
</bean>
</beans>
我们可以将以下类与main方法一起使用以读取配置并访问Bean。
public class App {
public static void main( String[] args ){
// create context using configuration
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("appcontext.xml");
Employee emp = context.getBean("empBean", Employee.class);
System.out.println(emp);
context.close();
}
}
输出:
20:09:24.009 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'baseEmpBean' 20:09:24.140 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'empBean' Id= 1 Name= Hyman Dept= HR Company= XYZ
Spring Bean定义继承中的Abstract属性
如果要限制父bean的实例化,则可以将其标记为abstract =" true"来实现。
Spring 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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- acts as a template -->
<bean id="baseEmpBean" abstract="true" class="com.theitroad.springproject.model.Employee">
<property name="company" value="XYZ"/>
</bean>
<bean id="empBean" parent="baseEmpBean" >
<property name="empId" value="1" />
<property name="empName" value="Hyman" />
<property name="dept" value="HR" />
</bean>
</beans>
将parent标记为抽象时,尝试访问父bean会导致错误。
Exception in thread "main" org.springframework.beans.factory.BeanIsAbstractException: Error creating bean with name 'baseEmpBean': Bean definition is abstract at org.springframework.beans.factory.support.AbstractBeanFactory.checkMergedBeanDefinition(AbstractBeanFactory.java:1335) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:295) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:204) at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1111) at com.theitroad.springproject.App.main(App.java:14)
父bean作为Spring bean继承中的模板
通过将父bean定义标记为abstract =" true"而不指定类,我们可以将父仅用作纯模板bean定义,用作子定义的父定义。
注意,如果父定义未指定类,则需要将父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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- acts as a template -->
<bean id="baseEmpBean" abstract="true">
<property name="company" value="XYZ"/>
</bean>
<bean id="empBean" parent="baseEmpBean" class="com.theitroad.springproject.model.Employee">
<property name="empId" value="1" />
<property name="empName" value="Hyman" />
<property name="dept" value="HR" />
</bean>
</beans>

