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

时间:2017-05-02 14:14:18

标签: java spring dependency-injection constructor-injection spring-ioc

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

中接收抽象
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);
  }
  ...

我们现在需要将一个具体子类的实例注入到一个新实现的服务类中,我们应该用XML配置它。我们可以为抽象父类配置一个抽象bean,但是这个bean似乎不允许被用作具体子bean的constructor-arg

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

有没有办法克服这个问题?处理程序类层次结构是遗留代码,此时我们无法修改其源代码。

2 个答案:

答案 0 :(得分:2)

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

<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 :(得分:0)

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

在Java中,您无法实例化抽象类的实例,因此在实例化抽象类时,尝试将抽象bean映射到抽象java类型将不起作用。

我建议您改为查看Servlet Filters的工作方式(通过FilterChain)或Spring's HandlerInterceptor pattern