鉴于这种简化的设置再现:
package net.myexample.plugin
class MyExampleService {
Map doMunge(Map m) {
// do stuff to 'm'
return m
}
}
/****************************** BREAK: NEXT FILE ******************************/
package net.myexample.plugin
class MyTagLib {
static namespace = 'p'
def myExampleService
def tag = { attrs, body ->
def m = doMungeAndFilter(attrs.remove('m'))
out << g.render(template: '/template', plugin: 'my-example-plugin', model: m)
}
Map doMungeAndFilter(def m) {
def mm = myExampleService.doMunge(m)
// do stuff to 'm'
return mm
}
}
/****************************** BREAK: NEXT FILE ******************************/
package net.myexample.app
import net.myexample.plugin.MyExampleService
class MyExampleService extends net.myexample.plugin.MyExampleService {
def doMunge(def m) {
def mm = super.doMunge(m)
// do more stuff to 'mm'
return mm
}
}
/****************************** BREAK: NEXT FILE ******************************/
package net.myexample.app
import net.myexample.plugin.MyTagLib
class MyTagLib extends net.myexample.plugin.MyTagLib {
static namespace = 'a'
def myExampleService
def tag = { attrs, body ->
def m = doMungeAndFilter(attrs.remove('m'))
out << g.render(template: '/template', plugin: 'my-example-plugin', model: m)
}
Map doMungeAndFilter(def m) {
def mm = super.doMungeAndFilter(m)
// do more stuff to 'mm'
return mm
}
}
/**
* But we get an exception that cites that it cannot call 'doMunge' on a null
* object -- which could only be 'myExampleService'
*/
当应用程序的taglib上的方法调用其超类(插件上的taglib)时,为什么服务看起来是null
,而超类又调用服务上的方法?
我能想到的最好的理论是该服务实际上并没有在app的taglib类中实例化,因为除def
之外没有明确的引用。我认为是这种情况,因为如果我将所有逻辑从服务类的方法移动到taglib的方法中,它就会按预期工作。
(为了绘制完整的图片:MyExampleService.doMunge
在其他地方被调用,而后续过滤(在MyTagLib.doMungeAndFilter
中)只需要taglib。)
或者:如果我将doMungeAndFilter
移动到另一个服务类,在插件中创建基本版本并在应用程序中扩展它,这很好。我认为这是一个可以接受的结论,尽管创建另一个服务类只是为了支持这样的taglib感觉很臃肿。
思考?提示?明显的错误或遗漏?
答案 0 :(得分:1)
这只是一个快速的猜测,但你是/ grails-app / taglib下的taglib类文件,还是/ src目录中的某个地方?我注意到我无法获得服务(至少自动注入)/ grails-app文件夹之外的类。
答案 1 :(得分:1)
从子类taglib中删除def myExampleService
。像Groovy中的属性编译为私有字段加上公共getter和setter,所以在超类taglib中你隐式地
private Object myExampleService;
public void setMyExampleService(Object svc) {
this.myExampleService = svc;
}
// getter similar
当您在子类中再次声明myExampleService
时,子类获取其自己的私有字段(具有相同名称),并且重写setter以将提供的值存储在此子类字段中超类一。 Spring调用setter来注入服务,因此最终结果是超类私有myExampleService
永远不会被设置,因此在尝试调用超类中的myExampleService.doMunge
时会出现空指针异常。
子类可以通过继承的getter和setter访问超类属性,因此不需要重新声明它。