Reputation: 3984
I have a parent abstract class and a concrete child class. The abstract one has one concrete method and one other abstract method, which the child class implements. Both of these classes are configured as Spring beans. The code snippets are similar to below:
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.-->
Class definitions:
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.
}
}
Both of these classes have appropriate getter/setter methods for cacheMan
. I don't understand how cacheMan
is being null in the doProcess1()
method. However, if i change that line from
cacheMan == null
to getCacheMan() == null
, the error is not thrown.
I think the getCacheMan()
is retrieving the object injected to the child class, since parent
is of the instance Child
and that's why it's not being null.
Please shed some light on it and let me know if this is not clear.
Upvotes: 1
Views: 3410
Reputation: 340693
This problem is not related to Spring but to Java language - method overriding to be specific.
You have setCacheMan()
(that's what I assume) method defined in both abstract parent and child class. When Spring calls that method, it always calls the overriden version in child - and that version modifies cacheMan
reference in child as well. cacheMan
reference in parent is never really touched because the only method that accesses it is overriden in child.
if i change that line from
cacheMan == null
togetCacheMan() == null
, the error is not thrown.
That is quite obvious from what has already been said - getCacheMan()
is also overriden! cacheMan
reference in parent is null
(see above), but since getCacheMan()
is overriden, it accesses cacheMan
in child, not in parent. Effectively you have two variables, but the one in child can't be upated.
Solution: the idea of parent bean is to have common dependencies in one place and avoid duplicating them in every child:
<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>
And either declare cacheMan
protected or have at least protected getter so that child classes can access it. Do not create cacheMan
field in child classes.
Upvotes: 2