【发布时间】:2014-09-10 20:49:15
【问题描述】:
我有一个抽象类,它实现了由注册为 bean 的大量具体类继承的大部分功能。 bean 是在开启自动装配的情况下定义的。例如:
abstract class MyAbstract {
MyService myService
MyBean myBean
def doSomething() {
def value = myService.something(myBean)
}
}
class MyConcrete extends MyAbstract {
def concreteField
def doSomethingElse() {
def value = myService.somethingElse(myBean)
}
}
conf/spring/resources.groovy:
myConcrete(MyConcrete) { bean ->
bean.autowire = true
myBean = ref(MySpecificBeanImpl)
}
我的问题:
当我在 MyConcrete 实例中运行方法 doSomethingElse 时,一切都按预期工作,并且 myService 和 myBean 值由 DI 填充了正确的值。当我在 MyConcrete 实例中执行 doSomething 方法时,myService 和 myBean 值都为空。似乎 DI 值在子类继承的抽象方法中不可见。真的很烂。
我可以使用方法中的上下文持有者手动访问这些值,或者我可以使用接受这些值作为参数的修改方法签名将值从子类传递到抽象父类,但这些都不是好的解决方案。它完全破坏了抽象类实现的用处,并且需要大量我不想维护的重复代码。
更糟糕的是,在我的具体情况下,myBean 的值实际上对于每个具体类都不同,在 resources.groovy 文件中显式连接,因此通用持有人方法不起作用。
我浏览了许多与此相关的帖子,包括Grails services in abstract class,但并没有弄清楚发生了什么。抽象bean定义似乎是关于抽象bean定义属性,与抽象类和子类继承没有任何关系。
(1) 这是对 Grails/Spring DI 支持的限制吗? (2) 抽象类还有什么我需要做的吗?
【问题讨论】:
-
您是否在resources.groovy 中将抽象类定义为抽象bean?
-
正如我上面提到的,抽象 bean 定义更像是一个 bean 属性模板,与 Groovy 类继承没有任何关系——至少文档是这么说的。我确实为了咯咯笑而尝试了它,但它并没有像我想要的那样做任何事情。根据文档的预期。
-
这对我有用(grails 2.4.3)。对我来说没有意义的是 doSomethingElse 有效,但 doSomething 无效。如果您在 same bean 上调用这两种方法,则它使用相同的成员变量。为什么它们对于一种方法为空,而对于另一种方法为空(除非有一些副作用会清除成员)。您是否在同一个对象上调用了这两种方法?
-
是的,这两种方法都在 MyConcrete 实例中运行。是的,从抽象基类继承的方法中的值为 null 是非常令人惊讶的。它破坏了类继承和它提供的有用的代码重用。我推测注入发生在对象生命周期的某个地方,因此注入的值仅在子类提供的方法中可见。很奇怪。不过我是在 2.3.11 中运行的,所以我会在 2.4.3 中进行一些小测试,看看是否有所不同。
-
“我推测注入发生在对象生命周期的某个地方,因此注入的值仅在子类提供的方法中可见。” - 在生命周期中实际上没有任何一点可以进行 DI 来导致此处描述的行为。必须有其他的解释。您确定您的子类中没有任何可能相关的数据隐藏吗?拥有演示问题的可运行代码将使这更容易理解。我希望原因很简单。