我们在项目中使用 Groovy 和 Guice,我遇到了以下错误:
groovy.lang.MissingPropertyException: No such property: myService for class: com.me.api.services.SomeService$$EnhancerByGuice$$536bdaec
花了一点时间才弄清楚,但这是因为我引用了一个私有(private)类成员,它被注入(inject)到一个闭包中。任何人都可以阐明为什么会发生这种情况吗?
此外,还有更好的方法吗?
这是类的一个片段:
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class MyService extends BaseService<Thing> {
@Inject
private ThingDao thingDao
@Inject
private OtherService<Thing> otherService
@Override
List<Thing> findAll() {
List<Thing> things = this.dao.findAll()
things.each {
//Note: This doesn't work!
otherService.doSomething()
}
things
}
我要么必须使用标准的 for 循环,要么不使用注入(inject)的成员,这往往会导致代码重复。
最佳答案
TLDR;
要么声明otherService
public (删除 private
修饰符)或添加一个 getter OtherService<Thing> getOtherService(){otherService}
如果您绝对想避免通过属性公开该字段,您可以使用以下技巧:在引用您的服务的 Closure 范围之外创建一个局部变量:
OtherService<Thing> otherService=this.otherService
things.each {
//Note: This will work! Because now there is a local variable in the scope.
//This is handled by normal anonymous inner class mechanisms in the JVM.
otherService.doSomething()
}
说明
在幕后,您的闭包是匿名类的对象,而不是具有您的私有(private)字段的对象,otherService
.
这意味着它无法解析对该字段的直接引用。访问闭包内的符号将首先查看局部变量,如果未找到匹配项,则 getProperty()
Closure
中的方法将被调用以查找属性,具体取决于您定义的解析策略。默认情况下,这是 OWNER_FIRST
.
如果您查看 Closure#getProperty
的代码:
switch(resolveStrategy) {
case DELEGATE_FIRST:
return getPropertyDelegateFirst(property);
case DELEGATE_ONLY:
return InvokerHelper.getProperty(this.delegate, property);
case OWNER_ONLY:
return InvokerHelper.getProperty(this.owner, property);
case TO_SELF:
return super.getProperty(property);
default:
return getPropertyOwnerFirst(property);
}
您看到所有者、委托(delegate)和声明对象需要具有匹配的属性。
在 groovy 中,如果你声明一个字段 private
,您不会获得自动生成的访问器方法,因此不会为外部对象公开公开任何属性。
关于groovy - 为什么 Groovy 闭包不能访问注入(inject)的类成员?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40915407/