1

この非常に単純化されたセットアップの表現を考えると、次のようになります。

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'
 */

nullアプリの taglib のメソッドがそのスーパークラス (プラグインの taglib) を呼び出し、そのスーパークラスがサービスのメソッドを呼び出すと、なぜサービスが表示されるのでしょうか?

私が思いつく最良の理論は、サービスは実際にはアプリの taglib クラスでインスタンス化されていないということdefです。すべてのロジックをサービス クラスのメソッドから taglib のメソッドに移動すると、期待どおりに動作するため、これが当てはまると思います。

(全体像を描くために:MyExampleService.doMungeは他の場所で呼び出されますが、その後のフィルタリング ( MyTagLib.doMungeAndFilter) は taglib にのみ必要です。)

または、別のサービス クラスに移動doMungeAndFilterして、プラグインでベース バージョンを作成し、それをアプリで拡張すると、問題なく動作します。そのようなtaglibをサポートするためだけに別のサービスクラスを作成するのは肥大化しているように感じますが、これは受け入れられる結論だと思います.

考え?チップ?明らかな誤りや脱落?

4

2 に答える 2

1

def myExampleServiceサブクラスtaglibからを削除します。Groovyのそのようなプロパティは、プライベートフィールドに加えてパブリックゲッターとセッターにコンパイルされるため、スーパークラスtaglibでは暗黙的に

private Object myExampleService;

public void setMyExampleService(Object svc) {
  this.myExampleService = svc;
}
// getter similar

サブクラスで再度宣言myExampleServiceすると、サブクラスは(同じ名前の)独自のプライベートフィールドを取得し、セッターはオーバーライドされて、スーパークラスではなくこのサブクラスフィールドに指定された値を格納します。Springはsetterを呼び出してサービスを注入するため、最終的にはスーパークラスprivatemyExampleServiceが設定されないためmyExampleService.doMunge、スーパークラスを呼び出そうとするとnullポインター例外が発生します。

サブクラスは、継承されたゲッターとセッターを介してスーパークラスプロパティにアクセスできるため、再宣言する必要はありません。

于 2012-11-12T17:57:18.887 に答える
1

これは簡単な推測ですが、taglib クラス ファイルは /grails-app/taglib の下にありますか、それとも /src ディレクトリのどこかにありますか? /grails-app フォルダーの外にあるクラスに (少なくとも自動的に) サービスを挿入できないことに気付きました。

于 2012-05-25T12:46:08.413 に答える