4

I have a spring bean defined outside my control. I want to set a property in that spring bean, is that possible from spring XML?

e.g. a.xml (not controlled by me):

<bean id="a" class="A"/>
<bean id="b" class="B">
    <constructor-arg ref="a"/>
</bean>

b.xml (controlled by me)

<import resource="classpath:META-INF/a.xml"/>
<bean id="c" class="C"/>
<!-- here i want to set a property in bean a -->

One option, but I dont' like it is to set the property programatically. I'm using spring 2.5 in java.

Tomas
  • 1,725
  • 2
  • 18
  • 27

4 Answers4

3

You can define the property in the spring configuration.

<bean id="myBean"class="myClass">
  <property name="myProperty">
  </property>
</bean>

Beans with the same name can be configured and the last bean will win (maybe the first one I'm not so sure about this). If you order the configuration xml files in a way that your definition is loaded as the last one it will redefine the bean.

Thomas Jung
  • 32,428
  • 9
  • 84
  • 114
  • Maybe thats possible, but the bean is injected in other beans in the same spring file, those references would then point to the "wrong" bean. – Tomas Dec 30 '09 at 08:13
  • try defining it at the top of your xml then. – Bozho Dec 30 '09 at 08:19
  • Try to redefine `` in b.xml before the import (or after it. one has to work: http://forum.springsource.org/archive/index.php/t-25878.html). – Thomas Jung Dec 30 '09 at 08:37
3

You could inject the bean-a into another class and set it's property there

<bean id="foo" class="...MySetterClass" init-method="init">
    <property name="candidateBean" ref="a"/>
    <property name="candidateProperty" value="bar"/>
</bean>

So your class MySetterClass could do something like

class MySetterClass {
    /*... Setter boilerplate */
    public void init(){
        candidateBean.setCandidateProperty(candidateProperty);
    }
}

This is a pretty ugly approach, but it should work.

Paul McKenzie
  • 19,646
  • 25
  • 76
  • 120
0

When importing the a.xml:

<bean id="a" class="A"/>
<bean id="b" class="B">
    <constructor-arg ref="a"/>
</bean>

This is ugly to an init method on a client class to modify the bean a.

I don't really undestand the problem here: some framework is probably providing you an already prepared, ready to run, spring context. If you don't like this already prepared stuff, why do you want to modify it at runtime with fancy strategies? It is just a context.

You can reuse the beans you want in that context, and if you don't like the bean a, just declare your own bean a2.

This is only a problem when the bean a is used in many beans of the context you import. If this is the case, then you can copy the a.xml context and customize it.


If you use a namespace because it is easier, sometimes you find out that some options are not possibles when using the namespace, and you finally go with using a FactoryBean or declaring manually the beans. When importing an external xml context it is the same: sometimes it doesn't do what you want.

Spring helps you wire objets together. A namespace or external context is a predefined wiring. If you don't like the predefined wiring, just do it yourself with your own xml or FactoryBean.


If the wiring to copy and customize is quite large (multiple xml files etc...) and you just want to perform a little modification on a single bean, then you should give it a try to what Thomas Jung tells you: override the bean you don't like. It works! Spring's overriding bean

Community
  • 1
  • 1
Sebastien Lorber
  • 89,644
  • 67
  • 288
  • 419
  • This was a bit late, code is in production since some years :-) To respond to what you write, I need that instance modified, not a new instance. Further more copying all the XML is not very update friendly (as the 3rd party dependency may need a update at some point), nor the solution with override bean. I still think that there is no perfect solution for this, but thanks for trying to improve the answer anyway. – Tomas Jan 02 '13 at 20:20
  • Then the best solution is probably to open a ticket to your third party library and to tell them to provide a factory bean which includes a pluggable strategy to customize the bean creation, like it is done inside Spring – Sebastien Lorber Jan 02 '13 at 21:32
  • Or you could have used a BeanPostProcessor that would modify only the beans of type A (or with the "a" name) just after its creation. But it shouldn't be the client side of a context that modify the context itself :) I know I'm late, just wanted to give my opinion in case someone reads it. – Sebastien Lorber Jan 02 '13 at 21:34
  • BeanPostProcessor would probably have been a feasible solution, I'll think of that in a similar problem. And yes I agree that the 3rd party is wrongly designed. In fact its not the context that is being edited, rather the default behavior of a class loaded in a context. – Tomas Jan 03 '13 at 09:09
0

Without knowing more:

You could make the supplied bean the parent of another bean and inject the property value in the second bean. Then, use the bean you created instead of the supplied one.

<bean id="myNewBean" parent="suppliedBean">
    <property key="prop" value="foo"/>
</bean>

If there are other beans with a reference to the first bean that need to have the property value you injected, or there is code looking up this bean by name, then this won't work. Likewise, there are several situations where this wouldn't be what you want depending on your transaction and aop configurations. However, if all you need to do is inject a property on a plain old bean for your own code, this should be okay.

Paul Morie
  • 15,528
  • 9
  • 52
  • 57