9.1 Overview of Spring Bean Configuration Inheritance
In general Inheritance is a mechanism in which one object acquires all the properties and behaviours of parent object. With inheritance ,we can create new classes that are built upon existing classes. When we inherit from an existing class, we can reuse methods and fields of parent class, and can add new methods and fields also.
Similarly Spring framework provides out of the box support of inheritance for beans defined in beans in a xml file ( beans configuration file). A child bean definition inherits configuration data from a parent definition and the child definition can override some values, or add others, as needed. Conceptually beans configuration inheritance is similar to the java inheritance.
9.2 Spring Bean Inheritance Ways
Bean Inheritance can be done in a XML file using following ways -
9.2.1 A bean in a xml file can extend other bean using parent attribute in bean tag.
<bean id="parent_bean” class="class_name”/> <bean id="child_bean” parent="parent_bean’/>
In this case we need not to define class attribute in children bean
9.2.1.1 Lets discuss bean inheritance using parent attribute. For this
a) Create a class ParentBean which defines two fields
public class ParentBean { private String message; private String title; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
b) Define bean entry of ParentBean and ChildBean. ParentBean will set message property and ChildBean will have a parent attribute and will have set title property
<?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-3.0.xsd" > <bean id="parentBean" class="ParentBean" > <property name="message" value="Test Message by Parent bean "> </property> </bean> <bean id="childBean" parent="parentBean" > <property name="title" value="Title by Child Bean "> </property> </bean> </beans>
c) Create a TestInheritance Class as below
import org.springframework.context.ApplicationContext; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestInheritance { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); ParentBean parentBean = (ParentBean)context.getBean("parentBean"); System.out.println("=====Parent Bean===="); System.out.println("Message ::" + parentBean.getMessage()); System.out.println("Title ::" + parentBean.getTitle()); ParentBean childrenBean = (ParentBean)context.getBean("childBean"); System.out.println("=====Child Bean===="); System.out.println("Message ::" + childrenBean.getMessage()); System.out.println("Title ::" + childrenBean.getTitle()); ((AbstractApplicationContext) context).registerShutdownHook(); } }
d) Output- We can see that message field has the value set by parent
9.2.1.2 Change the above program to demonstrate overriding
Solution – Overriding means redefine the property or methods. Lets change the bean.xml file for child tag to set the message field as well (refer below )
<?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-3.0.xsd" > <bean id="parentBean" class="ParentBean" > <property name="message" value="Test Message by Parent bean "> </property> </bean> <bean id="childBean" parent="parentBean" > <property name="title" value="Title by Child Bean "> </property> <property name="message" value="Test Message by Child bean "> </property> </bean> </beans>
Run the TestInheritance program again and we will see the message is updated with the value of child
9.2.2 Inheritance using abstract (Define parent bean as abstract)
We can define the parent class as abstract like below
<bean id="parent_bean" class="class_name" abstract=”true”/> <bean id="child_bean" parent="parent_bean"/>
In this case we parent class will be considered as abstract and we will not be able to call getBean() method on parent bean (as object of abstract class cannot be created) .
Note: adding abstract as true does not mean we will make out java class as abstract.
9.2.2.1 Lets discuss bean inheritance using abstract attribute. For this
a) Create a class AbstractParentBean which defines two fields
public class AbstractParentBean{ private String message; private String title; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
b) Define bean entry of AbstractParentBean and ChildBean. ParentBean will set message property and ChildBean will have a parent attribute and will have set title property
<?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-3.0.xsd" > <bean id="abstractParentBean" class="AbstractParentBean" abstract="true" > <property name="message" value="Test Message by Parent bean "> </property> </bean> <bean id="childBean" parent="abstractParentBean" > <property name="title" value="Title by Child Bean "> </property> </bean> </beans>
c) Create a TestAbstractInheritance Class as below
import org.springframework.context.ApplicationContext; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestAbstractInheritance { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); AbstractParentBean childrenBean = (AbstractParentBean)context.getBean("childBean"); System.out.println("=====Child Bean===="); System.out.println("Message ::" + childrenBean.getMessage()); System.out.println("Title ::" + childrenBean.getTitle()); ((AbstractApplicationContext) context).registerShutdownHook(); } }
d) Output- We can see that message field has the value set by parent
9.2.2.2 Try to create a bean of AbstractParentBean and see what happens
a) Update the TestAbstractInheritance class as below
import org.springframework.context.ApplicationContext; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestAbstractInheritance { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); AbstractParentBean parentBean = (AbstractParentBean)context.getBean("abstractParentBean"); System.out.println("=====Parent Bean===="); System.out.println("Message ::" + parentBean.getMessage()); System.out.println("Title ::" + parentBean.getTitle()); ((AbstractApplicationContext) context).registerShutdownHook(); } }
b) Run the TestAbstractInheritance program and you will see error “Bean definition is abstract” (refer below )
9.2.3 Define parent class as template –
Sometimes we have got several beans and they have some common fields in them. In such scenario ,we can define parent class as template. In such case , parent bean does not need a “class” attribute, instead defines in child beans.
<bean id=”parent_bean” abstract=”true”/> <bean id=”child_bean” parent=”parent_bean” class=”class_name” />
9.2.3.1 Lets discuss bean inheritance using abstract attribute. Parent bean is not necessary to define class attribute
a) Create a class ChildBean which defines two fields
public class ChildBean{ private String message; private String title; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
b) Define bean entry of TemplateParentBean and ChildBean. ParentBean will set message property and ChildBean will have a parent attribute and will have set title property . Also child bean will define a class attribute
<?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-3.0.xsd" > <bean id="templateParentBean" abstract="true"> <property name="message" value="Test Message by Parent bean "> </property> </bean> <bean id="childBean" parent="templateParentBean" class="ChildBean" > <property name="title" value="Title by Child Bean "> </property> </bean> </beans>
c) Create a TestTemplateInheritance Class as below
import org.springframework.context.ApplicationContext; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestTemplateInheritance { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); ChildBean parentBean = (ChildBean)context.getBean("childBean"); System.out.println("=====Child Bean===="); System.out.println("Message ::" + parentBean.getMessage()); System.out.println("Title ::" + parentBean.getTitle()); ((AbstractApplicationContext) context).registerShutdownHook(); } }
- Output- We can see that message field has the value set by parent
9.3 Conclusion
In all above three, we need to create corresponding java class only if we have defined class attribute. Also if we define abstract attribute does not mean we need to make the java class as abstract. It is just that you will not be able to instantiate that class using Spring.