Spring:将对象同时注入基类bean和子类bean时,值为null
我有一个父抽象类和一个具体的子类。抽象类有一个具体方法和另一个抽象方法,由子类实现。这两个类都配置为Springbean。代码片段类似于以下内容: 弹簧配置: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> <
<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>