Is it possible from Spring to inject the result of calling a method on a ref bean?
JavaSpringJava Problem Overview
Is it possible from Spring to inject the result of calling a method on a ref bean?
I'm trying to refactor some cut/pasted code from two separate projects into a common class. In one of the projects, the code lives in a class I'll call "MyClient" that is being instantiated from Spring. It is injected with another spring-instantiated class "MyRegistry", then the MyClient class uses that class to look up an endpoint. All I really need is the endpoint String in my refactored class, which can be initialized via a Setter. I really cannot have a dependency on MyRegistry from MyClient in the refactored code.
So, my question is this... is there a way I can inject the endpoint String from spring that was looked up in the MyRegistry class. So, I currently have:
<bean id="registryService" class="foo.MyRegistry">
...properties set etc...
</bean>
<bean id="MyClient" class="foo.MyClient">
<property name="registry" ref="registryService"/>
</bean>
But I'd like to have (and I know this is imaginary Spring syntax)
<bean id="MyClient" class="foo.MyClient">
<property name="endPoint" value="registryService.getEndPoint('bar')"/>
</bean>
where MyRegistry will have a method getEndPoint(Stirng endPointName)
Hope that makes sense from a the standpoint of what I'm trying to achieve. Please let me know if something like this is possible in Spring!
Java Solutions
Solution 1 - Java
It's possible in Spring 3.0 via http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch07s04.html">Spring Expression Language:
<bean id="registryService" class="foo.MyRegistry">
...properties set etc...
</bean>
<bean id="MyClient" class="foo.MyClient">
<property name="endPoint" value="#{registryService.getEndPoint('bar')}"/>
</bean>
Solution 2 - Java
The nicest solution is to use Spring 3's expression language as described by @ChssPly76, but if you're using an older version of Spring, it's almost as easy:
<bean id="MyClient" class="foo.MyClient">
<property name="endPoint">
<bean factory-bean="registryService" factory-method="getEndPoint">
<constructor-arg value="bar"/>
</bean>
</property>
</bean>
Solution 3 - Java
Or in Spring 2.x, by using a BeanPostProcessor
> Typically, bean post processors are used for checking the validity of bean properties or altering bean properties (what you want to) according to particular criteria.
public class MyClientBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if((bean instanceof MyClient)) && (beanName.equals("MyClient"))) {
Myregistry registryService = (Myregistry) applicationContext.getBean("registryService");
((MyClient) bean).setEndPoint(registryService.getEndPoint("bar"));
}
return bean;
}
}
And register your BeanPostProcessor
<bean class="br.com.somthing.MyClientBeanPostProcessor"/>