使用抽象 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。
我们的代码库中有一个处理程序层次结构 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。