Spring:将对象同时注入基类bean和子类bean时,值为null

Spring:将对象同时注入基类bean和子类bean时,值为null,spring,dependency-injection,Spring,Dependency Injection,我有一个父抽象类和一个具体的子类。抽象类有一个具体方法和另一个抽象方法,由子类实现。这两个类都配置为Springbean。代码片段类似于以下内容: 弹簧配置: <bean id="parent" class="Parent" abstract="true"> <property name="propA" ref="propA"/> <property name="cacheMan" ref="cacheMan"/> </bean> <

我有一个父抽象类和一个具体的子类。抽象类有一个具体方法和另一个抽象方法,由子类实现。这两个类都配置为Springbean。代码片段类似于以下内容:

弹簧配置:

<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.-->
这两个类都有适合
cacheMan
的getter/setter方法。我不明白在
doProcess1()
方法中,
cacheMan
是如何为null的。但是,如果我从

cacheMan==null
getCacheMan()==null
,不会引发错误

我认为
getCacheMan()
正在检索注入子类的对象,因为
parent
属于实例
child
,这就是它不为null的原因


请解释一下,如果不清楚,请告诉我。

这个问题与Spring无关,而是与Java语言有关,具体来说是方法重写

您在抽象父类和子类中都定义了
setCacheMan()
(我假设是这样)方法。当Spring调用该方法时,它总是在child中调用覆盖的版本,并且该版本也会修改child中的
cacheMan
引用<父对象中的code>cacheMan引用从未真正被触及,因为访问它的唯一方法在子对象中被重写

如果我将该行从
cacheMan==null
更改为
getCacheMan()==null
,则不会引发错误

这一点在前面已经说过的话中非常明显-
getCacheMan()
也被覆盖<父级中的code>cacheMan引用为
null
(见上文),但由于
getCacheMan()
被重写,因此它访问子级中的
cacheMan
,而不是父级中的
。实际上,您有两个变量,但child中的一个变量无法升级

解决方案:父bean的思想是在一个地方有公共依赖项,并避免在每个子项中重复它们:

<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
受保护,或者至少具有受保护的getter,以便子类可以访问它。不要在子类中创建
cacheMan
字段。

Tomasz,我相信你给了我一个我猜到的解释,但我真的不明白。为什么《抽象》不能单独拥有一个cacheMan呢。我知道child类会覆盖它,但问题可能是“为什么我要获取子实例而不是父实例?”我不知道null是如何被注入到父类的cacheMan字段中的限定值。@asgs:就是这样,
null
永远不会被注入到父类中!我认为Spring调用了两次
setCacheMan()
,一次用于父级,一次用于子级,在两次调用中都提供了正确的
cacheMan
引用。但是,由于该方法已被重写,因此子级中的
setCacheMan()
将被调用两次,而父级中的
setCacheMan()
将被调用-从不。同样,这与Spring关系不大,Java就是这样工作的。请将
System.out
添加到两个
setCacheMan()
实现中,并查看何时调用它们。我打赌永远不会调用parent中的版本,parent中的
cacheMan
引用也永远不会更新。我在两个setter中都添加了一个SOP,它确实会按顺序调用这两个setter:parent和child(在服务器启动期间),因为child依赖于parent。我不知道在那之后会发生什么,这使得父对象的cacheMan设置为null。
<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>