我有一个父抽象类和一个具体的子类。抽象的方法有一个具体的方法和另一个抽象的方法,子类实现。这两个类都配置为Spring bean。代码段类似于以下内容:
Spring Config:
<bean id="parent" class="Parent" abstract="true">
<property name="propA" ref="propA"/>
<property name="cacheMan" ref="cacheMan"/>
</bean>
<bean id="child" class="Child" parent="parent">
<property name="propB" ref="propB"/>
<property name="cacheMan" ref="cacheMan"/>
</bean>
<!-- Of course, cacheMan is defined elsewhere and not relevant here.-->
班级定义:
public abstract class Parent {
private A propA; // A is irrelevant.
private CacheManager cacheMan; // This is the object in question.
public void doProcess1() {
//code logic
if (cacheMan == null) {
// Error!
}
}
public void doProcess2();
}
public class Child extend Parent {
private B propB; // Again, B is irrelevant.
private CacheManager cacheMan; // This is the object in question.
public void doProcess2() {
//code logic
}
}
public class Test {
private Parent parent; //Assume this is Spring injected and it's of type Child.
public void doTest() {
parent.doProcess1(); // Error thrown since cacheMan is null.
}
}
这两个类都有适用于cacheMan
的getter / setter方法。我不明白cacheMan
方法中doProcess1()
如何为空。但是,如果我从
cacheMan == null
到getCacheMan() == null
,不会抛出错误。
我认为getCacheMan()
正在检索注入子类的对象,因为parent
属于实例Child
,这就是它不为空的原因。
请详细说明一下,如果不清楚,请告诉我。
答案 0 :(得分:2)
此问题与Spring无关,而与Java语言无关 - 方法覆盖是特定的。
您在抽象父类和子类中定义了setCacheMan()
(这是我假设的)方法。当Spring调用该方法时,它总是调用子代中的覆盖版本 - 该版本也会修改子代中的cacheMan
引用。父项中的cacheMan
引用永远不会被触及,因为访问它的唯一方法在子项中被覆盖。
如果我将该行从
cacheMan == null
更改为getCacheMan() == null
,则不会抛出错误。
从已经说过的内容中可以看出这一点很明显 - getCacheMan()
也被覆盖了!父cacheMan
中的null
引用为getCacheMan()
(见上文),但由于cacheMan
被覆盖,因此它访问子级中的<bean id="parent" class="Parent" abstract="true">
<property name="propA" ref="propA"/>
<property name="cacheMan" ref="cacheMan"/>
</bean>
<bean id="child" class="Child" parent="parent">
<property name="propB" ref="propB"/>
</bean>
,而不是父级中的cacheMan
。实际上你有两个变量,但是孩子中的变量不能被提升。
解决方案:父bean的想法是在一个地方有共同的依赖关系,并避免在每个孩子中重复它们:
cacheMan
要么声明{{1}}受保护,要么至少保护getter,以便子类可以访问它。不要在子类中创建{{1}}字段。