Is it possible from Spring to inject the result of calling a method on a ref bean?

JavaSpring

Java 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"/>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlex WordenView Question on Stackoverflow
Solution 1 - JavaChssPly76View Answer on Stackoverflow
Solution 2 - JavaskaffmanView Answer on Stackoverflow
Solution 3 - JavaArthur RonaldView Answer on Stackoverflow