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>