我们的代码库中有一个处理程序类层次结构,它实现了一种责任链原则。有一个抽象的父类,它由几个子类扩展,这些子类也在它们的构造函数
中接收抽象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"/>
...
有没有办法克服这个问题?处理程序类层次结构是遗留代码,此时我们无法修改其源代码。
答案 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。