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

时间:2012-04-24 22:03:31

标签: spring dependency-injection

我有一个父抽象类和一个具体的子类。抽象的方法有一个具体的方法和另一个抽象的方法,子类实现。这两个类都配置为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 == nullgetCacheMan() == null,不会抛出错误。

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

请详细说明一下,如果不清楚,请告诉我。

1 个答案:

答案 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}}字段。