2010-03-13 3 views
9

Je tente d'implémenter un fournisseur de service de délégué en remplaçant la définition de bean pour le service d'origine avec mon service de délégué. Toutefois, comme son nom l'indique, le service délégué a besoin d'une référence au service d'origine auquel déléguer les appels.Comment remplacer une définition de bean Spring tout en référençant le bean surchargé?

Je n'arrive pas à déterminer comment remplacer la définition du bean tout en utilisant le bean def d'origine sans rencontrer de problème de référence circulaire.

Par exemple:

<!-- Original service def in spring-context.xml --> 
<bean id="service" class="com.mycompany.Service"/> 

<!-- Overridden definition in spring-plugin-context.xml --> 
<bean id="service" class="com.mycompany.DelegatedService"/> 
    <constructor-arg ref="service"/> 
</bean> 

Est-ce possible?

Répondre

10

répondre à votre question est que vous ne pouvez pas avoir deux définitions de bean avec le même nom. Si vous essayez, l'un cachera l'autre et une seule définition sera utilisable.

L'exemple de votre question semble suggérer que vous essayez d'envelopper le bean original service dans un objet proxy, avec l'encapsuleur effectuant un certain travail avant et après les appels au service. Une façon d'y parvenir, sans définir deux haricots service, et sans modifier le haricot d'origine service, est d'utiliser un ressort AutoProxyCreator, probablement un BeanNameAutoProxyCreator.

Cela vous permet de répertorier un ou plusieurs beans devant être automatiquement envoyés par proxy. Vous spécifiez les intercepteurs que vous souhaitez appliquer aux appels sur le bean cible. Vous implémenteriez ces intercepteurs pour faire le travail que vous devez faire. Spring créerait automatiquement un proxy de délégation pour vous, avec l'identifiant de bean service comme auparavant, mais avec vos fonctionnalités supplémentaires.

+0

Cette réponse a été la plus utile bien que mon problème soit devenu insoluble. Afin de représenter la classe, elle doit être tissée par un aspect. Étant donné que la classe que je tentais d'utiliser comme proxy était déjà compilée et exécutée dans un classloader différent, je n'ai pas été capable de l'utiliser par procuration. – Kevin

+0

@ Kevin: Un 'AutoProxyCreator' ne classe pas proxy, il proxie haricots. Peu importe le classloader qui charge la classe cible, c'est l'objet cible qui est mandaté et Spring instancie cet objet cible. – skaffman

+0

pour répondre à la question initiale, un modèle est de simplement déclarer un « nu » haricot sous-jacent. dans une configuration alias le nom du bean cible, dans l'autre configuration, définissez votre wrapper qui est injecté avec le bean sous-jacent. cela nécessite une planification préalable cependant. – aaron

2

Vous pouvez créer proxies and interceptors. Alors maintenant, le bean nommé service deviendra un proxy à l'original service qui doit être renommé en quelque chose d'autre. Les modifications seront donc limitées au Spring XML uniquement et ne seront pas propagées à votre code Java.

<bean id="personTarget" class="com.mycompany.PersonImpl"> 
    <property name="name"><value>Tony</value></property> 
    <property name="age"><value>51</value></property> 
</bean> 

<bean id="myAdvisor" class="com.mycompany.MyAdvisor"> 
    <property name="someProperty"><value>Custom string property value</value></property> 
</bean> 

<bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor"> 
</bean> 

<bean id="person" 
    class="org.springframework.aop.framework.ProxyFactoryBean"> 
    <property name="proxyInterfaces"><value>com.mycompany.Person</value></property> 

    <property name="target"><ref local="personTarget"/></property> 
    <property name="interceptorNames"> 
     <list> 
      <value>myAdvisor</value> 
      <value>debugInterceptor</value> 
     </list> 
    </property> 
</bean> 
+0

Je ne peux pas renommer l'original « service » haricot à rien d'autre parce qu'il est défini dans un contexte de ressort qui est hors de mon contrôle – Kevin

+0

autant que je sache, cela est impossible au printemps. De plus, même s'il était possible, il serait une mauvaise pratique, si quelqu'un a écrit le grain avec une fonctionnalité particulière à l'esprit et fermé à modification, vous pourriez finir par casser la fonctionnalité originale. un (mauvais) travail autour sera que vous définissez votre propre classe avec la même signature et d'utiliser un chargeur de classe personnalisée pour charger la classe d'origine et déléguer. Ce serait mieux si vous pouviez poster votre exigence finale. – saugata

1

Il semble que vous essayez de réinventer l'AOP de printemps. S'il vous plaît envisager d'utiliser printemps-AOP pour cela.

Il est possible de modifier par programme le nom du service existant et de créer un nouveau bean avec l'ancien nom. Le code autoproxieux dans le cadre du printemps fait cela et vous pourriez jeter un coup d'oeil à cela. Une recherche rapide de code pour Auto Proxy * dans le cadre de printemps devrait vous y parvenir.

Alternativement, si vous contrôlez les sites clients (les consommateurs), vous pouvez ajouter un qualificateur à votre wrapper, et utiliser des qualificateurs pour contraindre les implémentations appropriées aux consommateurs. Le wrapper peut utiliser l'implémentation non qualifiée pour accéder à l'original. (Il peut également être possible de monter un qualificateur vers l'implémentation d'origine en ajoutant une autre définition de bean pour le service avec un qualificatif dans le code XML que vous contrôlez, mais cela devrait fonctionner)

Questions connexes