[ACCEPTED]-How to modify beans defined in a spring container-ioc-container

Accepted answer
Score: 11

You could use a BeanFactoryPostProcessor to change the bean's metadata 3 before the Spring container instantiates 2 the CodeBase bean. For example:

public class CodebaseOverrider implements BeanFactoryPostProcessor {

    private List<String> sourceCodeLocations;

    public void postProcessBeanFactory(
            ConfigurableListableBeanFactory beanFactory) throws BeansException {        
        CodeBase codebase = (CodeBase)beanFactory.getBean("codebase");
        if (sourceCodeLocations != null)
        {
            codebase.setSourceCodeLocations(sourceCodeLocations);
        }
    }

    public void setSourceCodeLocations(List<String> sourceCodeLocations) {
        this.sourceCodeLocations = sourceCodeLocations;
    }

}

Then in 1 contextSpecial.xml:

<beans>
    <import resource="context1.xml" />

    <bean class="com.example.CodebaseOverrider">
        <property name="sourceCodeLocations">
            <list>
                <value>src/handmade/productive</value>
                <value>src/generated/productive</value>
            </list>
        </property>
    </bean>
</beans>
Score: 3

Yes. A bean definition can have a "parent" attribute 10 that references a parent bean definition. The 9 new "child" definition inherits 8 most of the properties of the parent and 7 any of those properties can be overridden.

See 6 Bean Definition Inheritance

Also you can use Collection Merging to merge the list property 5 definition from the parent and child bean 4 definitions. This way you can specify some 3 list items in the parent bean definition 2 and add more items to it in the child bean 1 definition.

Score: 1

3 approaches:

  1. Simple: have two lists defaultSourceCodeLocations 23 and additionalSourceCodeLocations and have 22 your accessor methods check both of these 21 (or combine them). I've seen this done in 20 some frameworks - a default list of handlers 19 is populated then additional user created 18 ones are added...

  2. More complicated but keeps 17 the original class clean: You could then 16 create a CodeBaseModifier class. This would 15 have a init-method to alter an injected 14 instance of the bean.

    <bean id="codebaseModifier" class="com.example.CodeBase" init-method="populateCodeBase">
        <property name="sourceCodeLocations" ref="codebase"/>
        <property name="additionalSourceCodeLocations">
        <list>
            <value>src/handmade/productive</value>
        </list>
        </property>
    </bean>
    

If you wanted to make 13 this really generic you could make a bean 12 modifier that would do this by reflection. Be 11 careful of the ordering if use this approach. Dependent 10 beans of CodeBase would have to make sure 9 this class was instantiated first (with 8 depends on)

3 A variation on 2... Instead 7 of directly creating a CodeBase class instead 6 create a factory that returns a populated 5 bean. This factory could then be configured 4 with Spring in a similar fashion to 2. Have 3 a defaultSourceCodeLocations and additionalSourceCodeLocations 2

Unless you need a lot of extensible properties 1 I would go with option 1.

Score: 1

Is there a way to define the list in a properties 5 or other configuration before hand?

It 4 seems like the app configuration and wiring 3 are tightly coupled. From my experience, if 2 it is hard to do something in Spring, likely 1 there is a different easier way to do it.

Score: 1

In Spring 3.0, you can specify merge="true" on 1 the 'list' tag. See http://forum.springsource.org/archive/index.php/t-97501.html for details.

More Related questions