0

Wir haben eine Hierarchie von Handler-Klassen in unserer Codebasis, die eine Art von Verantwortung-Prinzip implementieren. Es ist eine abstrakte Superklasse und sie von mehreren untergeordneten Klassen erweitert, die auch die Zusammenfassung in ihrem Konstruktor erhaltenVerwenden Sie abstrakte Spring Bean als Konstruktor-Arg

public abstract class AbstractHandler { 
    public AbstractHandler(final AbstractHandler next, final PropertyName propertyName) { 
    this.next = next; 
    this.propertyName = propertyName; 
    } 
    ... 

public class OneConcreteChildHandler extends AbstractHandler { 
    public OneConcreteChildHandler(final AbstractHandler next) { 
    super(next, PropertyName.OneConcreteChild); 
    } 
    ... 

Wir würden jetzt eine Instanz eines der konkreten Kind-Klassen in einen neu implementierten Service injizieren müssen Klasse, und wir sollten dies in XML konfigurieren. Wir können eine abstrakte Bohne für die abstrakte Superklasse konfigurieren, aber diese dann scheint nicht für die konkrete Kind bean

<bean id="abstractHandler" abstract="true" class="...AbstractHandler" /> 

<bean id="oneConcreteChildHandler" class="...OneConcreteChildHandler" parent="abstractHandler"> 
    <constructor-arg ref="abstractHandler"/> //"abstract bean can not be used here" 
</bean> 

<bean id="someService" class="...SomeService"> 
    <constructor-arg ref="oneConcreteChildHandler"/> 
    ... 

Gibt es eine Möglichkeit, dies zu überwinden als Konstruktor-Arg- verwendet werden soll erlaubt zu sein? Die Handlerklassenhierarchie ist Legacy-Code und wir können ihre Quellen zu diesem Zeitpunkt nicht ändern.

Antwort

2

Das Hauptproblem hier ist, dass Sie versuchen, eine abstrakte Bohne zu injizieren. Du solltest das nicht tun. Diese abstractHandler sollte nur für die Zuordnung der parent in untergeordneten Bean verwendet werden. Trotzdem sieht es nicht so aus, wie du es willst/brauchst. Sie würden in diesem Konstruktor kein abstraktes Objekt übergeben, sondern das Objekt einer anderen untergeordneten Klasse. Sie Kette muss einen Endpunkt hat, wo das Argument des Konstruktor next wie die null sein wird:

<bean id="abstractHandler" abstract="true" class="...AbstractHandler" /> 

<bean id="oneConcreteChildHandler" class="...OneConcreteChildHandler" parent="abstractHandler"> 
     <constructor-arg ref="twoConcreteChildHandler"/> 
    </bean> 

<bean id="twoConcreteChildHandler" class=".." parent="abstractHandler"> 
    <constructor-arg name="next"> 
     <null /> 
    </constructor-arg> 
</bean> 

<bean id="someService" class="...SomeService"> 
    <constructor-arg ref="oneConcreteChildHandler"/> 
    ... 
+1

Vielen Dank. Wir haben gerade bemerkt, dass es unter den konkreten Child-Klassen tatsächlich eine TailChildHandler-Klasse zum Schließen der CoR-Kette gibt (ihr Konstruktor enthält super (null, null)) und wir können sie in der config auf die gleiche Weise wie twoConcreteChildHandler in Ihrem verwenden Beispiel. Dies behebt das Problem. – hammerfest

0

Spring abstrakte Bohne Konzept als Java abstrakte Klasse Konzept ist nicht das Gleiche.

In Java können Sie eine Instanz einer abstrakten Klasse nicht instanziieren, und daher wird der Versuch, eine abstrakte Bean einem abstrakten Java-Typ zuzuordnen, nicht funktionieren, wenn es Zeit ist, sie zu instanziieren.

Ich würde empfehlen, dass Sie stattdessen betrachten, wie Servlet Filters arbeiten (über den FilterChain) oder Spring's HandlerInterceptor pattern.