I have a spring bean my_bean
with a property my_map
, and I want to inject it with the value "X" or with the value "Y". The bean:
<bean id="my_bean">
<property name="my_map">
<map>
<entry key="p" value="X" />
</map>
</property>
</bean>
It's referenced in a very deep hierarchy by the bean root_a
:
<bean id="root_a">
<ref bean="root_a_a"/>
</bean>
<bean id="root_a_a">
<ref bean="root_a_a_a"/>
</bean>
<bean id="root_a_a_a">
<ref bean="my_bean"/>
</bean>
and this entire deep hierarchy is referenced again from the bean root_b
. In the ref of my_bean from this hierarchy I would the property to be injected with the value "Y", but I would not like to duplicate the entire hierarchy twice.
<bean id="root_b">
<ref bean="root_a_a"/>
</bean>
How do I do this in the spring XML? can you think of a clever spring EL solution? something else? I prefer all my configuration to be done in the XML and no Java code...
By default Spring beans are singletons, which means that once bean="my_bean"
is created it is shared between other components e.g. shared between A => bean id="root_a_a_a"
and B => bean id="root_b_b_b"
The answer to your question depends on what exactly you are trying to achieve.
If bean="my_bean"
does not need to be shared between A and B, then create two beans:
inject this one to A
<bean id="myBeanX" class="My">
<property name="culprit" value="X"/>
</bean>
and this one to B
<bean id="myBeanY" class="My">
<property name="culprit" value="Y"/>
</bean>
notice they both are instances of the same class.
You can also inline them into collaborators (A / B) if you don't need them for anything else:
<bean id="root_a_a_a">
<constructor-arg>
<bean class="My">
<property name="culprit" value="X"/>
</bean>
</constructor-arg>
</bean>
You can also have a factory bean that creates root_a_a_a
given the property for a class My
, but that would be an overkill.
In case A and B needs to share the exact same reference to bean="my_bean"
, the question is: are you ok with A and B changing my_bean
's state after my_bean
is created? Probably not.
If you are, which would be 0.41172% chance, you can change my_bean
's value to whatever you need in A's or B's constructors => would not recommend
Hence you either would go with the Two Bean
approach (which is most likely what you want), or you would need to refactor a property for "X" and "Y" into another e.g. myConfig
component.
If root_a
and root_b
will not be used together in the same instance of the context,you can use Spring Profiles (example), or SpEL / Property Based solutions (example)
e.g.
<bean id="my_bean">
<property name="my_map">
<map>
<entry key="p" value="${ENV_SYSTEM:X}" />
</map>
</property>
</bean>
It will set it to X
by default, unless a ENV_SYSTEM system variable is set (e.g. to Y
).