tags:

views:

61

answers:

2

We have a white labeled application (one application supporting a branded experience for multiple customers). We would like to be able to load a co-brand version of a component to support custom components per customer. For example something like:

<!-- default service -->
<bean id="service" class="com.blah.myService" primary="true">
  <property name="myBean" ref="bean" />
</bean>
<!-- custom service for client 123 -->
<bean id="service_123" class="com.blah.myService">
  <property name="myBean" ref="bean" />
</bean>

<!-- default bean -->
<bean id="bean" class="com.blah.Bean" primary="true"/>
<!-- bean for client 123 -->
<bean id="bean_123" class="com.blah.Bean" />

We have tried subclassing the ApplicationContext, and this works for the top-level bean, but the autowired collaborators are wired and cached during the loading of spring.

As an example, if I invoke getBean("service"), I can intercept the call in my custom ApplicationContext and return service_123, but the "bean" property uses the cached version and does not invoke the getBean method again, thus I am unable to wire in the custom version.

Is there an easy way to achieve this type of runtime custom injection?

+1  A: 

First of all, you perhaps don't need to subclass ApplicationContext to implement this kind of custom instantiation logic - you can create a BeanPostProcessor instead.

To solve a problem with the cached version of a bean, you can wrap the returned bean into some kind of proxy - either using AOP or manually (for example, see TargetSource and its subclasses).

axtavt
By Adding a CoBrandTargetSource, I was able to wire the dependencies at runtime, but the selection of the top level bean was not participating (either through the BeanPostProcessor or TargetSource). Do you have an idea to solve this? Your answer is spot on otherwise.
Rich Kroll
A: 

One way it would be manually loading these beans:

myAppContext.getBean("bean_" + customer.getId());

If you need your class to access an instance of the ApplicationContext, make your class implement ApplicationContextAware.

Alex
This works for selecting the top level bean, but all dependencies will by wired at load time, and thus will not support the "cobranding"
Rich Kroll