Monday, March 6, 2023

Bean Definition Inheritance in Spring

In object-oriented programming there is a parent-child relationship among classes where child class inherits properties and methods of the parent class through inheritance. Same concept of inheritance is provided in Spring also where bean definition is inherited. In this post we'll learn about bean definition inheritance in Spring along with examples.

A bean definition can contain a lot of configuration information, including constructor arguments, property values, and container-specific information such as initialization method, static factory method name and so on. So common things can be moved to one bean (parent bean) and other beans (child beans) can use it by inheriting that parent bean. A child bean definition inherits configuration data from a parent definition. In addition to that child definition can override some values, or add others, as needed.


Spring Bean definition inheritance configuration

In XML-based configuration metadata, you specify a parent-child relationship by using the parent attribute in bean definition, specifying the parent bean as the value of this attribute.

A child bean definition uses the bean class from the parent definition if none is specified, but can also override it. In the latter case, the child bean class must be compatible with the parent, that is, it must accept the parent's property values.

A child bean definition inherits scope, constructor argument values, property values, and method overrides from the parent, with the option to add new values. Any scope, initialization method, destroy method, and/or static factory method settings that you specify will override the corresponding parent settings.

The remaining settings are always taken from the child definition: depends on, autowire mode, dependency check, singleton, lazy init.

Spring Bean definition inheritance Example

Let's see an example where we have a Payment class with two fields in it paymentType and amount. If you want to have a configuration where by default paymentType is "cash" then it can be done using bean definition inheritance.

Payment class

public class Payment {
  private String paymentType;
  private double amount;
  public String getPaymentType() {
    return paymentType;
  }
  public void setPaymentType(String paymentType) {
    this.paymentType = paymentType;
  }
  public double getAmount() {
    return amount;
  }
  public void setAmount(double amount) {
    this.amount = amount;
  }

  @Override
  public String toString() {
    StringBuffer sb = new StringBuffer();
    sb.append("Payment Type ").append(getPaymentType());
    sb.append(" Amount ").append(getAmount());
    return sb.toString();
  }
}

XML Configuration

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
 
<!--<context:component-scan base-package="org.netjs.prog" /> --> 

  <bean id="basePaymentBean" class="org.netjs.prog.Payment">
    <property name="paymentType" value="cash"/>
  </bean> 
  
  <bean id="paymentBean" parent="basePaymentBean">
    <property name="amount" value="50.15" />
    <!-- paymentType value will be inherited from parent -->
  </bean>
</beans>

You can run it using the following program.

import org.netjs.prog.Payment;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {

  public static void main(String[] args) {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext
      ("appcontext.xml");
    Payment bean = (Payment) context.getBean("paymentBean");
    System.out.println("Values " + bean);
    context.close();
  }
}

Output

Values Payment Type cash Amount 50.15

Overriding values in child bean

As already stated child bean definition can override the properties inherited from the parent bean. For example, if you want to override the default option of "cash" provided through parent bean definition and have the value as "credit card" for the paymentType then it can be done as shown in below XML configuration.

<bean id="basePaymentBean" class="org.netjs.prog.Payment" abstract="true">
  <property name="paymentType" value="cash"/>
</bean> 
    
<bean id="paymentBean" parent="basePaymentBean">
  <property name="paymentType" value="credit card"/>
  <property name="amount" value="50.15" />
</bean>

Output

Values Payment Type credit card Amount 50.15

If you have observed in the XML configuration the parent class has an attribute "abstract" as true. Marking the bean as abstract means that it can't be instantiated.

Actually that's how inheritance with in the bean definition must be used. Parent class must be defined with common property values and the child beans should define values for the other values.

Since parent definition has values for common values so it is more of a template which should be inherited and then values for the other values should be provided by the child bean. In that case it doesn't make sense to instantiate the parent class itself as it is just a template.

In fact parent bean can be defined as a pure template itself let's see how it can be done.

Spring Bean definition inheritance- Parent bean as Template

If you want to use parent bean as a template then you don't need to have a class defined for the parent bean and it has to have abstract attribute as true. In that case XML configuration will look like this-

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

  <bean id="basePaymentBean" abstract="true">
    <property name="paymentType" value="cash"/>
  </bean> 

  <bean id="ccPaymentBean" parent="basePaymentBean" class="org.netjs.prog.CCPayment">
    <property name="paymentType" value="credit card"/>
    <property name="amount" value="50.15" />
  </bean>
 
</beans>

CCPayment class

public class CCPayment {
 private String paymentType;
 private double amount;
 public String getPaymentType() {
  return paymentType;
 }
 public void setPaymentType(String paymentType) {
  this.paymentType = paymentType;
 }
 public double getAmount() {
  return amount;
 }
 public void setAmount(double amount) {
  this.amount = amount;
 }
 
 @Override
 public String toString() {
  StringBuffer sb = new StringBuffer();
  sb.append("Payment Type ").append(getPaymentType());
  sb.append(" Amount ").append(getAmount());
  return sb.toString();
 }
}

You can run it using the following class -

public class App {

 public static void main(String[] args) {
   ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext
    ("appcontext.xml");
   CCPayment bean = (CCPayment) context.getBean("ccPaymentBean");
   System.out.println("Values " + bean);
   context.close();
 }
}

Output

Values Payment Type credit card Amount 50.15

That's all for this topic Bean Definition Inheritance in Spring. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Spring Tutorial Page


Related Topics

  1. Spring Bean Life Cycle
  2. Bean Scopes in Spring With Examples
  3. Injecting Inner Bean in Spring
  4. Spring p-namespace For Shorter XML Configuration
  5. Difference Between component-scan And annotation-config in Spring

You may also like-

  1. Autowiring in Spring Using @Autowired and @Inject Annotations
  2. Spring NamedParameterJdbcTemplate Select Query Example
  3. How to Read Properties File in Spring Framework
  4. Circular Dependency in Spring Framework
  5. static block in Java
  6. Difference Between Comparable and Comparator in Java
  7. CopyOnWriteArrayList in Java With Examples
  8. Find All Permutations of a Given String Java Program

No comments:

Post a Comment