使用抽象 Spring bean 作为构造函数参数

Use abstract Spring bean as constructor-arg

我们的代码库中有一个处理程序层次结构 classes,它实现了一种责任链原则。有一个抽象父 class 并且它由几个子 class 扩展,它们也在它们的构造函数中接收抽象

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

我们现在需要将具体子 class 之一的实例注入到新实现的服务 class 中,我们应该在 XML 中配置它。我们可以为抽象父类配置一个抽象 bean class,但是这个 bean 似乎不允许用作具体子 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"/>
    ...

有什么办法可以克服这个问题吗?处理程序 class 层次结构是遗留代码,我们目前无法修改它们的源代码。

这里的主要问题是您试图注入抽象 bean。你不应该这样做。此 abstractHandler 应该仅用于映射子 bean 中的 parent。尽管如此,它看起来并不是真正的您 want/need。您不会在此构造函数中传递一个抽象对象,而是另一个子 class 的对象。您 Chain 必须有一个终点,构造函数的参数 next 将像这样为空:

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

Spring 的抽象 bean 概念与 Java 的抽象 class 概念不同。

在 Java 中,您无法实例化抽象 class 的实例,因此尝试将抽象 bean 映射到抽象 java 类型将无法正常工作实例化它。

我建议您改为查看 Servlet Filters work (via the FilterChain), or Spring's HandlerInterceptor pattern