Search code examples
javaspringapplicationcontext

How to reduce duplication in Spring application context


I have some beans which I create which all use a similar pattern for bean instantiation. The top objects are all very similar, but the objects they contain differ by string constructor arguments. Everything in the each top-level bean is the same except for two instances of THIS CHANGES A and one instance of THIS CHANGES B. Below is one of my beans. The others are exactly the same except for the THIS CHANGES values.

<bean id="mover1" class="CustomDataMover">
        <constructor-arg ref="session"/>
        <constructor-arg>
            <bean class="DataCache">
                <constructor-arg>
                    <bean class="AllValuesReader">
                        <constructor-arg ref="databaseConnector"/>
                        <constructor-arg value="THIS CHANGES A"/>
                        <constructor-arg value="v1"/>
                        <constructor-arg value="v2"/>
                    </bean>
                </constructor-arg>
            </bean>
        </constructor-arg>
        <constructor-arg ref="customUpdate"/>
        <constructor-arg value="THIS CHANGES B"/>
        <constructor-arg>
            <bean class="ValueGenerator">
                <constructor-arg>
                    <bean class="LatestValueRetriever">
                        <constructor-arg ref="databaseConnector"/>
                        <constructor-arg value="v3"/>
                        <constructor-arg value="v4"/>
                        <constructor-arg value="THIS CHANGES A"/>
                    </bean>
                </constructor-arg>
            </bean>
        </constructor-arg>
</bean>

How can I reduce the amount of duplication in my beans? I'm looking for some way to make some sort of template. Also, please note that I do have references to other beans.


Solution

  • You can use abstract bean definitions as templates to reduce duplication. For example:

    <bean id="parent" abstract="true">
        <constructor-arg value="ARG0"/>
    
        <property name="propertyA" value="A"/>
        <property name="propertyB" value="B"/>
        <property name="propertyC" ref="beanC"/>
    </bean>
    
    <bean id="child1" class="SomeClass" parent="parent">
        <property name="propertyD" value="D1"/>
    </bean>
    
    <bean id="child2" class="SomeOtherClass" parent="parent">
        <property name="propertyD" value="D2"/>
    </bean>
    

    Beans "child1" and "child2" will share values from "parent" for arg0, "propertyA", "propertyB", and "propertyC", and still be able to configure their own values for "propertyD".

    Note that "parent" has no class and therefore cannot be instantiated. Also note that "child1" and "child2" can be children of the same abstract bean definition while being completely different classes - this hierarchy has nothing to do with the class hierarchy.