Grails:为什么这个服务类是null?

时间:2012-05-25 01:03:12

标签: grails groovy

鉴于这种简化的设置再现:

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感觉很臃肿。

思考?提示?明显的错误或遗漏?

2 个答案:

答案 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访问超类属性,因此不需要重新声明它。