Spring beans support basic inheritance for inheriting constructors and properties. A bean definition that is a base or template
for other beans that should never be instantiated can have the abstract attribute on the bean element set to true. The abstract attribute defaults to false.
ApplicationContext's will eagerly instantiate beans which will result in errors while they are starting when abstract beans not marked as abstract.
The abstract attribute needs to be set to true if a bean doesn't have required constructor and setter information or if
the class attribute is not set. BeanFactory's will not eagerly instantiate beans so when using
a BeanFactory it is not an issue, but for clarity it is still best to mark the bean as being abstract.
The attributes abstract, scope, lazy-init, depends-on,
autowire, and dependency-check are never inherited and are only taken from the current bean definition.
The examples only show only one level of inheritance, but Spring supports as many levels of inheritance as logically make sense for your configuration.
Example 3.32. Property Inheritance
The following example uses a SimplePerson class that can contain name and address information. The base bean definition sets
the class attribute and the first & last name properties. This bean definition isn't complete and
has it's abstract attribute set to true. In this example, the person has two different addresses, but obviously their name stays the same.
The bean definitions extending the simplePersonBase bean now only have to set
their id & parent attributes and also any properties to be set or overridden.
Although none are overridden in this case.
<bean id="simplePersonBase"
class="org.springbyexample.springindepth.chapter03.beanInheritance.SimplePerson"
abstract="true">
<property name="firstName" value="Joe" />
<property name="lastName" value="Smith" />
</bean>
<bean id="simplePersonAddress01"
parent="simplePersonBase">
<property name="address" value="1060 W. Addison St" />
<property name="city" value="Chicago" />
<property name="state" value="IL" />
<property name="zipPostalCode" value="60613" />
</bean>
<bean id="simplePersonAddress02"
parent="simplePersonBase">
<property name="address" value="2 Penn Plaza #15" />
<property name="city" value="New York" />
<property name="state" value="NY" />
<property name="zipPostalCode" value="10121" />
</bean>
Collections can not only be inherited, but can also merge with the parent's Collection. Spring supports collection merging
for Lists, Sets, Maps, and Properties. The merge attribute on
the different collection elements defaults to false. When it is set to true, the parent and child lists will be merged.
The order of merging starts with the first parent and keeps merging values from children into the collection.
For Maps and Properties any key in the child that matches a key from the parent will override the parent's key/value.
Spring does not support merging between different types of collections. To change the activate merging for all beans,
the root beans element default-merge attribute can be set to 'true'.
Example 3.33. Collection Inheritance
This example uses a Person class that has first and last name properties. It also has can have a list of Address instances.
This is a better design than the previous example since it can easily associate multiple addresses with a person.
In a real world example there could be types set. Such as home, office, second home, etc.
The personCompanyBase bean has one address set on it. It is meant to represent a base configuration for a companies address and anyone working there can extend it without having to set the same address again. The person01 bean sets the first & last name and also this person's home address. The list element sets the merge attribute to true. This indicates that the parent's list will be merged with the child's list. The resulting list will have parent address first and the child's address second in the merged list.
Excerpt from chapter03-bean-inheritance/src/main/resources/applicationContext.xml
<bean id="personCompanyBase"
class="org.springbyexample.springindepth.bean.Person"
abstract="true">
<property name="addressList">
<list>
<bean class="org.springbyexample.springindepth.bean.Address">
<property name="address" value="1060 W. Addison St" />
<property name="city" value="Chicago" />
<property name="state" value="IL" />
<property name="zipPostalCode" value="60613" />
</bean>
</list>
</property>
</bean>
<bean id="person01"
parent="personCompanyBase">
<property name="firstName" value="Joe" />
<property name="lastName" value="Smith" />
<property name="addressList">
<list merge="true">
<bean class="org.springbyexample.springindepth.bean.Address">
<property name="address" value="2 Penn Plz #15" />
<property name="city" value="New York" />
<property name="state" value="NY" />
<property name="zipPostalCode" value="10121" />
</bean>
</list>
</property>
</bean>