web-dev-qa-db-ja.com

Java抽象クラスでのロギング

私はプロジェクトに取り組んでおり、現在log4jでいくつかのロギングの実装に取り​​組んでおり、ログの実装についてどうすればいいのか興味がありました。私がキックしている2つの実装は次のとおりです。

最初のオプション

そのクラスとすべてのサブクラスに対して、スーパークラスからの単一のログを使用します。

public abstract class AbstractFoo {
    protected static Log LOG = LogFactory.getLog(AbstractFoo.class);

    ...
}

public class Foo extends AbstractFoo {
    public void someMethod() {
        LOG.info("Using abstract log");
    }
}

2番目のオプション

クラス、スーパー、サブごとに個別のログを使用します。

public abstract class AbstractFoo {
    private static Log LOG = LogFactory.getLog(AbstractFoo.class);

    ...
}

public class Foo extends AbstractFoo {
    private static Log LOG = LogFactory.getLog(Foo.class);        

    public void someMethod() {
        LOG.info("Using own log");
    }
}

何がより理にかなっていて、なぜですか?

51
shuniar

私もしません。代わりに、両方のケースで正しいクラスを使用するようにします。

public abstract class AbstractFoo {
    protected final Log log = LogFactory.getLog(getClass());

    ...
}

public class Foo extends AbstractFoo {
    public void someMethod() {
        log.info("Using abstract log");
    }
}

多くのロギングを実行していない場合(とにかく良い方法です)、代わりにメソッドを使用できます。

public abstract class AbstractFoo {
    protected Log log() { return LogFactory.getLog(getClass()); }

    ...
}

これを頻繁に呼び出すクラスがある場合は、それをオーバーライドしてキャッシュされたインスタンスを提供できます。

90
Peter Lawrey

これが私の解決策です(最終的な静的ロガー):

public abstract class AbstractFoo {
     protected abstract Log getLogger();
     public doSomething() {
          getLogger().info("log something");
     }
}

public class Foo extends AbstractFoo {
    private static final Log log = Log.getLogger(Foo.class);

    protected Log getLogger() {
         return log;
    }
    public doSomethingElse() {
          log.info("log somethingElse");
    }
}
11
n1cr4m

両方とも理にかなっています。アプリケーションによって異なります。

私は、より頻繁に使用されるプラクティスは、各クラスのプライベートロガーを持つことだと思います。これにより、クラスごとおよびパッケージごとにロギングを設定できます。 AbstractFooFooは異なるパッケージに属している可能性があり、おそらくFooからのログのみを表示することを忘れないでください。

さらに、protectedフィールドを書きたい場合は、常に考え直してください。完全に禁止されているわけではありませんが、よく知られている悪い習慣です。コードが読みにくくなり、保守が難しくなります。

5
AlexR

同じことは、コンストラクターで遊ぶことで実現できます。 Baseクラスレベルでロガーを追加し、すべてのから設定しますDerived super()を使用したクラス。コードがあります:

public abstract class AbstractFoo {

    protected Log log;  // base abstract class has a Log object.

    public AbstractFoo(Log logger) {   // parameterized constructor for logger, to be used by the derived class.
        this.log = logger;
    }

    public doSomething() {        // common method for all the derived classes.
      log.info("log something");
    }
    // rest of business logic.
}

public class Foo extends AbstractFoo {

    public Foo(){
        super(LogFactory.getLog(AbstractFoo.class));
    }

    public void someMethod() {
        log.info("Using own log");     // this uses its own logger.
    }
}
2
Shubham Mishra

抽象クラスでロガーを作成すると、ログはすべてAbstractFooから発信されたものとしてタグ付けされます。ログが発生した子クラスでタグ付けされたログを表示する/必要がある場合は、子クラスのロガーを作成します。

1
herrtim