Ist es ab Spring möglich, das Ergebnis des Aufrufs einer Methode auf eine ref-Bean zu injizieren?

73

Ist es ab Spring möglich, das Ergebnis des Aufrufs einer Methode auf eine ref-Bean zu injizieren?

Ich versuche, einen ausgeschnittenen / eingefügten Code aus zwei separaten Projekten in eine gemeinsame Klasse umzuwandeln. In einem der Projekte befindet sich der Code in einer Klasse, die ich "MyClient" nenne und die von Spring instanziiert wird. Es wird eine andere federinstanziierte Klasse "MyRegistry" injiziert, und die MyClient-Klasse verwendet diese Klasse, um einen Endpunkt zu suchen. Alles, was ich wirklich brauche, ist der Endpunkt-String in meiner überarbeiteten Klasse, der über einen Setter initialisiert werden kann. Ich kann im überarbeiteten Code wirklich keine Abhängigkeit von MyRegistry von MyClient haben.

Meine Frage lautet also: Gibt es eine Möglichkeit, den Endpunkt-String aus dem Frühling einzufügen, der in der MyRegistry-Klasse nachgeschlagen wurde? Also habe ich derzeit:

<bean id="registryService" class="foo.MyRegistry">
...properties set etc...
</bean>

<bean id="MyClient" class="foo.MyClient">
    <property name="registry" ref="registryService"/>
</bean>

Aber ich hätte gerne (und ich weiß, dass dies eine imaginäre Spring-Syntax ist)

<bean id="MyClient" class="foo.MyClient">
    <property name="endPoint" value="registryService.getEndPoint('bar')"/>
</bean>

Dabei hat MyRegistry eine Methode getEndPoint (Stirng endPointName).

Hoffe, das macht Sinn vom Standpunkt dessen, was ich erreichen will. Bitte lassen Sie mich wissen, ob so etwas im Frühling möglich ist!

Alex Worden
quelle

Antworten:

50

Die schönste Lösung ist die Verwendung der Ausdruckssprache von Spring 3, wie von @ ChssPly76 beschrieben. Wenn Sie jedoch eine ältere Version von Spring verwenden, ist dies fast genauso einfach:

<bean id="MyClient" class="foo.MyClient">
   <property name="endPoint">
      <bean factory-bean="registryService" factory-method="getEndPoint">
         <constructor-arg value="bar"/>
      </bean>
   </property>
</bean>
Skaffman
quelle
1
Sehr cool - und ein bisschen hinterhältig. Wir verwenden hier Spring 2.5.6, daher werde ich versuchen, diese Technik zu verwenden. Ich verstehe, was Sie jetzt tun ... Sie behandeln die getEndPoint () -Methode als Factory-Methode in registryService - die "fabrikkonstruierte" Klasse ist eine einfache Zeichenfolge, die den EndPoint darstellt. Sehr cool! Ich hoffe das funktioniert!
Alex Worden
4
"Devious" in der Tat, wie kannst du es wagen :) Dies ist genau wie factory-beanund factory-methodsoll verwendet werden, ich werde dich wissen lassen :)
Skaffman
117

Es ist in Spring 3.0 über Spring Expression Language möglich :

<bean id="registryService" class="foo.MyRegistry">
...properties set etc...
</bean>

<bean id="MyClient" class="foo.MyClient">
  <property name="endPoint" value="#{registryService.getEndPoint('bar')}"/>
</bean>
ChssPly76
quelle
1
@ ChssPly76 Willkommen, Sie sind zurück
Arthur Ronald
Verdammt, das ist praktisch
Pieter De Bie
1
Funktioniert dies, wenn die getEndPoint () -Logik eine Abhängigkeit für die darin enthaltene Logik aufweist, die zur Laufzeit nicht festgelegt wurde? Zum Beispiel ist "endPoint" eine Variable, in der foo.MyRegistrynoch kein Wert festgelegt ist. Zur Laufzeit ist sie also null und die endPointIn- MyClientBean ist sehr verwirrt, wenn versucht wird, sie festzulegen.
Beckah
3

Oder in Spring 2.x mithilfe eines BeanPostProcessors

In der Regel werden Bean-Postprozessoren verwendet, um die Gültigkeit von Bean-Eigenschaften zu überprüfen oder die Bean-Eigenschaften (was Sie möchten) nach bestimmten Kriterien zu ändern .

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;
    }
}

Und registrieren Sie Ihren BeanPostProcessor

<bean class="br.com.somthing.MyClientBeanPostProcessor"/>
Arthur Ronald
quelle