5

このコードがそのように機能する理由を誰か説明できますか? Loggable トレイトの概念実証を自分で作成したかったのです。計画は、継承されたクラスがその作業を行う必要がないように、ロガー インスタンスをインスタンス化することでした。しかし、私が見ることができるように、これは私が望んでいたものではありません.

コードは次のとおりです。

package hu.jonas.simple

trait Loggable {
  val logger = java.util.logging.Logger.getLogger(this.getClass.getName)

  def whoAmI = {
    logger.info(this.getClass.getName)
  }
}

class Service extends Loggable {
  def answer = {
    whoAmI
  }
}

object Main extends App {
  new Service().answer
}

次のログ メッセージが生成されました。

Jan 25, 2013 2:02:07 PM hu.jonas.simple.Loggable$class whoAmI
INFO: hu.jonas.simple.Service

2 つの this.getClass.getName が異なるのはなぜですか? さらに、これを取得するためにロガーをインスタンス化するときに何を書く必要がありますか:

Jan 25, 2013 2:02:07 PM hu.jonas.simple.Service whoAmI
INFO: hu.jonas.simple.Service
4

2 に答える 2

4

あなたのコードでは、両方の出現がgetClass.getName同じ値を返します。ただし、ロガーは、出力メッセージをフォーマットするときに、ロガーの名前 (この場合は に対応するgetClass.getName) の代わりにソース クラス (スタックを調べることで知ることができる) を使用するだけです。したがって、ログ レコードのヘッダーを出力するときのロガーは、実際には呼び出しlogが行われたクラスの名前を使用していますが、ログ メッセージの内容はインスタンスの名前のランタイム クラスです。したがって、これは静的タイプとランタイムタイプの問題のようなものです。どこLoggable$classから来たのか疑問に思っているなら、 という名前のトレイトのメソッド実装が という名前Tの JVM クラスにあるのはたまたまですT$class

そして今、イラストのために。以下のコードでは、ログ ハンドラーを変更して、ソース クラスから情報を消去します。これにより、ロガーはソース クラス名ではなくロガー名を使用するようになり、期待した動作が返されます。

import java.util.logging._
trait Loggable {
  val logger = Logger.getLogger(this.getClass.getName)

  logger.getParent.getHandlers.foreach{ handler => 
    val formatter = handler.getFormatter
    handler.setFormatter( new java.util.logging.Formatter {
      def format( record: LogRecord ) = {
        record.setSourceClassName( null )
        formatter.format( record )
      }
    })
  }


  def whoAmI = {
    logger.info(this.getClass.getName)
  }
}

class Service extends Loggable {
  def answer = {
    whoAmI
  }
}

object Main extends App {
  new Service().answer
}

現在、問題を適切に修正するjava.util.logging.SimpleFormatter.formatために、デフォルトのログ形式を変更するために設定できるという名前のプロパティがあります。これを使用して、ソース クラスの代わりにロガー名を使用するログを作成します。http://docs.oracle.com/javase/7/docs/api/index.html?java/util/logging/SimpleFormatter.htmlを参照してください。Java 7 が必要であることに注意してください。

于 2013-01-25T14:24:40.653 に答える
0

そこで見ているのは、必ずしもロガーのクラスではなく、ロガーを呼び出したメソッドです。あなたの場合、それはLoggable.whoAmIです。インスタンス化されたクラスは typehu.jonas.simple.Serviceですが、メソッドがオンになっているため、Loggableそれが表示されます。その情報は通常、スタック トレースを調べることによって取得されます。

以下の例では、スタック トレースを自分でプルしても同じ結果が得られます。

trait Loggable { 
  val logger = java.util.logging.Logger.getLogger(this.getClass.getName)

  def whoAmI = {
    val stackTrace = Thread.currentThread.getStackTrace();
    logger.info("Class: %s, Method: %s".format(stackTrace(1).getClassName, 
      stackTrace(1).getMethodName))
    logger.info(this.getClass.getName)
  }
}

それは出力をもたらします:

Jan 25, 2013 9:39:28 AM $line99.$read$$iw$$iw$Loggable$class whoAmI
INFO: Class: $line99.$read$$iw$$iw$Loggable$class, Method: whoAmI

Jan 25, 2013 9:39:28 AM $line99.$read$$iw$$iw$Loggable$class whoAmI
INFO: $line100.$read$$iw$$iw$Service

あなたが見ることができるものは、ロガーが表示しているものと一致しています. スタックを下降し続けると、呼び出し階層にたどり着き、stackTrace(3)最終的に次の結果が得られることがわかります。

Jan 25, 2013 9:43:58 AM $line107.$read$$iw$$iw$Loggable$class whoAmI
INFO: Class: $line108.$read$$iw$$iw$Service, Method: answer

それを変更する方法が正確にはわかりませんjava.util.Loggerが、他の回答で指定されているように、おそらくフォーマッターを使用すると、目的の出力が得られます。それ以外の場合は、別のログ エンジンを試すか、上記の情報を使用して独自のログ エンジンを作成することができます。

于 2013-01-25T14:49:12.630 に答える