Spring bean inheritance
In java, we have already seen the benefit of inheritance which is Reusability.
That is, if we have some properties in the base class then child class will inherit those properties and its values.
We can also override those values in the Child class.
Similarly in Spring, we can inherit the beans properties and its values and we can also override them.
Let us consider a class called Customer
- package com.kb.beans.inheritance;
- public class Customer {
- private String name;
- private String email;
- private String country;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getEmail() {
- return email;
- }
- public void setEmail(String email) {
- this.email = email;
- }
- public String getCountry() {
- return country;
- }
- public void setCountry(String country) {
- this.country = country;
- }
- @Override
- public String toString() {
- return "Name :"+name+" Email :"+email+" Country :"+country;
- }
- }
package com.kb.beans.inheritance; public class Customer { private String name; private String email; private String country; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } @Override public String toString() { return "Name :"+name+" Email :"+email+" Country :"+country; } }
Now create a spring beans.xml file which shows how we can inherit the 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"
- xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.2.xsd">
- <bean id="baseCustomer" class="com.kb.beans.inheritance.Customer">
- <property name="country" value="India"/>
- </bean>
- <bean id="customer" parent="baseCustomer">
- <property name="name" value="kb"/>
- <property name="email" value="kb@gmail.com"/>
- </bean>
- </beans>
<?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" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"> <bean id="baseCustomer" class="com.kb.beans.inheritance.Customer"> <property name="country" value="India"/> </bean> <bean id="customer" parent="baseCustomer"> <property name="name" value="kb"/> <property name="email" value="kb@gmail.com"/> </bean> </beans>
We have defined 2 beans in the configuration file
Bean with the id baseCustomer acts as parent bean and second bean with the id customer acts as a child bean.
So child bean customer is inheriting country property and its value, and then adding 2 new properties to it.
Now create a class which loads the these 2 beans and shows the output containing inherited value
- package com.kb.beans.inheritance;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class BeanInheritanceTest {
- public static void main(String[] args) {
- ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
- Customer baseCustomer = (Customer) applicationContext.getBean("baseCustomer");
- System.out.println(baseCustomer.toString());
- Customer customer = (Customer) applicationContext.getBean("customer");
- System.out.println(customer.toString());
- }
- }
package com.kb.beans.inheritance; import org.springframework.context.support.ClassPathXmlApplicationContext; public class BeanInheritanceTest { public static void main(String[] args) { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); Customer baseCustomer = (Customer) applicationContext.getBean("baseCustomer"); System.out.println(baseCustomer.toString()); Customer customer = (Customer) applicationContext.getBean("customer"); System.out.println(customer.toString()); } }
Run the above class and see the output
Parent bean is having value only for Country property.
Child bean has the values for all 3 properties even though we have added only 2 properties for Child.
So, we have successfully inherited the Country property from the Parent bean to our Child bean.
Abstract Bean
As we know already in Java that we make Abstract classes to make sure that it should not be instantiated if it’s not complete.
So the same thing can be achieved even in spring for beans.
We just need to add abstract attribute inside < bean > tag.
In the above spring configuration file, just make the first bean as abstract
See the complete file 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" xmlns:context="http://www.springframework.org/schema/context"
- xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.2.xsd">
- <bean id="baseCustomer" abstract="true">
- <property name="country" value="India"/>
- </bean>
- <bean id="customer" parent="baseCustomer" class="com.kb.beans.inheritance.Customer">
- <property name="name" value="kb"/>
- <property name="email" value="kb@gmail.com"/>
- </bean>
- </beans>
<?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" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"> <bean id="baseCustomer" abstract="true"> <property name="country" value="India"/> </bean> <bean id="customer" parent="baseCustomer" class="com.kb.beans.inheritance.Customer"> <property name="name" value="kb"/> <property name="email" value="kb@gmail.com"/> </bean> </beans>
When we make bean as abstract , then mentioning class name is optional.
If we don’t mention class name, then it is called Pure Inheritance Template as it can be used by any Child bean which shares the same properties.
Since first bean has value only for Country and all other values are null, we will not allow this bean to instantiate.
So to achieve this, we will make this bean as abstract.
Now create a test class as below
- package com.kb.beans.inheritance;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class BeanInheritanceTest {
- public static void main(String[] args) {
- ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
- Customer baseCustomer = (Customer) applicationContext.getBean("baseCustomer");
- System.out.println(baseCustomer.toString());
- Customer customer = (Customer) applicationContext.getBean("customer");
- System.out.println(customer.toString());
- }
- }
package com.kb.beans.inheritance; import org.springframework.context.support.ClassPathXmlApplicationContext; public class BeanInheritanceTest { public static void main(String[] args) { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); Customer baseCustomer = (Customer) applicationContext.getBean("baseCustomer"); System.out.println(baseCustomer.toString()); Customer customer = (Customer) applicationContext.getBean("customer"); System.out.println(customer.toString()); } }
Run the above class and see the output
The above exception is coming as we are trying to instantiate the abstract bean
How to override the parent bean properties in Child bean ?
To override any properties values inside the Child bean, we can just specify that property and its new value in the Child bean.
See below beans.xml for the same
- <?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"
- xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.2.xsd">
- <bean id="baseCustomer" abstract="true">
- <property name="country" value="India"/>
- </bean>
- <bean id="customer" parent="baseCustomer" class="com.kb.beans.inheritance.Customer">
- <property name="country" value="USA"/>
- <property name="name" value="kb"/>
- <property name="email" value="kb@gmail.com"/>
- </bean>
- </beans>
<?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" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"> <bean id="baseCustomer" abstract="true"> <property name="country" value="India"/> </bean> <bean id="customer" parent="baseCustomer" class="com.kb.beans.inheritance.Customer"> <property name="country" value="USA"/> <property name="name" value="kb"/> <property name="email" value="kb@gmail.com"/> </bean> </beans>
So we have overridden the country property in Child bean.
In parent, its set as India and in Child we changed it to USA.
Create test class to check the same
- package com.kb.beans.inheritance;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class BeanInheritanceTest {
- public static void main(String[] args) {
- ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
- /*Customer baseCustomer = (Customer) applicationContext.getBean("baseCustomer");
- System.out.println(baseCustomer.toString());*/
- Customer customer = (Customer) applicationContext.getBean("customer");
- System.out.println(customer.toString());
- }
- }
package com.kb.beans.inheritance; import org.springframework.context.support.ClassPathXmlApplicationContext; public class BeanInheritanceTest { public static void main(String[] args) { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); /*Customer baseCustomer = (Customer) applicationContext.getBean("baseCustomer"); System.out.println(baseCustomer.toString());*/ Customer customer = (Customer) applicationContext.getBean("customer"); System.out.println(customer.toString()); } }
Run the above class and see the output
So , we have got new value for Country which is USA as its overridden in the child bean.
So above concept of inheritance in beans is very useful when we want to create multiple beans where each bean will have the same values for some of the properties and new values for some of the properties as compared to the existing bean.
Hi KB,
All examples are self explanatory for everyone. Thanks for coming up with such innovative examples to make the concepts clear.
Much Thanks,
Bharath
Very very useful content and very easy way of explaining. step by step.. with simple examples.. helps a lot as I am a beginner for Spring. Thank you.