1. 序章

このチュートリアルでは、Java 9 で新しく導入された Logging API を調べ、いくつかの例を実装して、最も一般的なケースをカバーします。

このAPIはJavaで導入され、すべてのプラットフォームログを処理し、ライブラリとアプリケーションでカスタマイズできるサービスインターフェイスを公開するための共通のメカニズムを提供します。このように、JDKプラットフォームログは同じものを使用できますアプリケーションとしてのロギングフレームワーク、およびプロジェクトの依存関係を減らすことができます。

2. カスタム実装の作成

このセクションでは、新しいロガーを作成するために実装する必要がある Logging API の主要なクラスを示します。 これを行うには、すべてのログをコンソールに出力する単純なロガーを実装します。

2.1. ロガーの作成

作成する必要のあるメインクラスはLoggerです。 このクラスは、 System.Logger インターフェイスと、少なくとも次の4つのメソッドを実装する必要があります。

  • getName():ロガーの名前を返します。 名前でロガーを作成するためにJDKによって使用されます
  • isLoggable():ロガーが有効になっているレベルを示します
  • log(): アプリケーションが使用している基本システム (この場合はコンソール) にログを出力するメソッドです。 実装する2つのlog()メソッドがあり、それぞれが異なるパラメーターを受け取ります

実装がどのようになるか見てみましょう。

public class ConsoleLogger implements System.Logger {

    @Override
    public String getName() {
        return "ConsoleLogger";
    }

    @Override
    public boolean isLoggable(Level level) {
        return true;
    }

    @Override
    public void log(Level level, ResourceBundle bundle, String msg, Throwable thrown) {
        System.out.printf("ConsoleLogger [%s]: %s - %s%n", level, msg, thrown);
    }

    @Override
    public void log(Level level, ResourceBundle bundle, String format, Object... params) {
        System.out.printf("ConsoleLogger [%s]: %s%n", level, 
          MessageFormat.format(format, params));
    }
}

ConsoleLogger クラスは、前述の4つのメソッドをオーバーライドします。 getName()メソッドは String、を返しますが、 isLoggable()メソッドはすべての場合にtrueを返します。 最後に、コンソールに出力する2つの log()メソッドがあります。

2.2. LoggerFinderの作成

ロガーを作成したら、ConsoleLoggerのインスタンスを作成するLoggerFinderを実装する必要があります。

そのためには、抽象クラス System.LoggerFinder を拡張し、 getLogger()メソッドを実装する必要があります。

public class CustomLoggerFinder extends System.LoggerFinder {

    @Override
    public System.Logger getLogger(String name, Module module) {
        return new ConsoleLogger();
    }
}

この場合、常に ConsoleLogger を返します。

最後に、LoggerFinderをサービスとして登録して、JDKで検出できるようにする必要があります。 実装を提供しない場合、SimpleConsoleLogger がデフォルトで使用されます。

JDKが実装をロードするために使用するメカニズムは、ServiceLoaderです。 詳細については、このチュートリアルを参照してください。

Java 9 を使用しているので、クラスをモジュールにパッケージ化し、サービスを module-info.java ファイルに登録します。

module com.baeldung.logging {
    provides java.lang.System.LoggerFinder
      with com.baeldung.logging.CustomLoggerFinder;
    exports com.baeldung.logging;
}

Javaモジュールの詳細については、この他のチュートリアルを確認してください。

2.3. 例のテスト

この例をテストするために、アプリケーションとして機能する別のモジュールを作成しましょう。 これには、サービス実装を使用するMainクラスのみが含まれます。

このクラスは、 System.getLogger()メソッドを呼び出すことにより、ConsoleLoggerのインスタンスを取得します。

public class MainApp {

    private static System.Logger LOGGER = System.getLogger("MainApp");

    public static void main(String[] args) {
        LOGGER.log(Level.ERROR, "error test");
        LOGGER.log(Level.INFO, "info test");
    }
}

内部的には、JDKは CustomLoggerFinder 実装を取得し、ConsoleLogger。のインスタンスを作成します。

その後、このモジュールの module-info ファイルを作成しましょう。

module com.baeldung.logging.app {
}

この時点で、プロジェクト構造は次のようになります。

├── src
│   ├── modules
│   │   ├── com.baeldung.logging
│   │   │   ├── com
│   │   │   │   └── baeldung
│   │   │   │       └── logging
│   │   │   │           ├── ConsoleLogger.java
│   │   │   │           └── CustomLoggerFinder.java
│   │   │   └── module-info.java
│   │   ├── com.baeldung.logging.app
│   │   │   ├── com
│   │   │   │   └── baeldung
│   │   │   │       └── logging
│   │   │   │           └── app
│   │   │   │               └── MainApp.java
│   │   │   └── module-info.java
└──

最後に、2 つのモジュールをコンパイルし、mods ディレクトリに配置します。

javac --module-path mods -d mods/com.baeldung.logging \
  src/modules/com.baeldung.logging/module-info.java \
  src/modules/com.baeldung.logging/com/baeldung/logging/*.java

javac --module-path mods -d mods/com.baeldung.logging.app \
  src/modules/com.baeldung.logging.app/module-info.java \
  src/modules/com.baeldung.logging.app/com/baeldung/logging/app/*.java

最後に、app モジュールの Main クラスを実行しましょう。

java --module-path mods \
  -m com.baeldung.logging.app/com.baeldung.logging.app.MainApp

コンソール出力を見ると、ログがConsoleLoggerを使用して印刷されていることがわかります。

ConsoleLogger [ERROR]: error test
ConsoleLogger [INFO]: info test

3. 外部ロギングフレームワークの追加

Java 9 でのログ API の最も有用な使用法の 1 つは、アプリケーションがJDK は、アプリケーションが使用しているのと同じロギング フレームワーク にログを記録します。これが、このセクションで行うことです。

SLF4J をロギング ファサードとして使用し、Logback をロギング フレームワークとして使用する新しいモジュールを作成します。

前のセクションで基本について説明したので、ここで外部ロギング フレームワークを追加する方法に焦点を当てることができます。

3.1. SLF4Jを使用したカスタム実装

まず、インスタンスごとに新しい SLF4J ロガーを作成する別の Logger を実装します。

public class Slf4jLogger implements System.Logger {

    private final String name;
    private final Logger logger;

    public Slf4jLogger(String name) {
        this.name = name;
        logger = LoggerFactory.getLogger(name);
    }

    @Override
    public String getName() {
        return name;
    }
    
    //...
}

このロガーorg.slf4j.Loggerであることに注意してください。

メソッドの rest、 については、SLF4J ロガー インスタンス の実装に依存します。 したがって、SLF4Jロガーが有効になっている場合、ロガーが有効になります。

@Override
public boolean isLoggable(Level level) {
    switch (level) {
        case OFF:
            return false;
        case TRACE:
            return logger.isTraceEnabled();
        case DEBUG:
            return logger.isDebugEnabled();
        case INFO:
            return logger.isInfoEnabled();
        case WARNING:
            return logger.isWarnEnabled();
        case ERROR:
            return logger.isErrorEnabled();
        case ALL:
        default:
            return true;
    }
}

また、logメソッドは、使用されるログレベルに応じて、適切なSLF4Jロガーメソッドを呼び出します。

@Override
public void log(Level level, ResourceBundle bundle, String msg, Throwable thrown) {
    if (!isLoggable(level)) {
        return;
    }

    switch (level) {
        case TRACE:
            logger.trace(msg, thrown);
            break;
        case DEBUG:
            logger.debug(msg, thrown);
            break;
        case INFO:
            logger.info(msg, thrown);
            break;
        case WARNING:
            logger.warn(msg, thrown);
            break;
        case ERROR:
            logger.error(msg, thrown);
            break;
        case ALL:
        default:
            logger.info(msg, thrown);
    }
}

@Override
public void log(Level level, ResourceBundle bundle, String format, Object... params) {
    if (!isLoggable(level)) {
        return;
    }
    String message = MessageFormat.format(format, params);

    switch (level) {
        case TRACE:
            logger.trace(message);
            break;
        // ...
        // same as the previous switch
    }
}

最後に、Slf4jLogger を使用する新しい LoggerFinder を作成しましょう。

public class Slf4jLoggerFinder extends System.LoggerFinder {
    @Override
    public System.Logger getLogger(String name, Module module) {
        return new Slf4jLogger(name);
    }
}

3.2. モジュール構成

すべてのクラスを実装したら、サービスをモジュールに登録し、SLF4J モジュールの依存関係を追加しましょう。

module com.baeldung.logging.slf4j {
    requires org.slf4j;
    provides java.lang.System.LoggerFinder
      with com.baeldung.logging.slf4j.Slf4jLoggerFinder;
    exports com.baeldung.logging.slf4j;
}

このモジュールの構造は次のとおりです。

├── src
│   ├── modules
│   │   ├── com.baeldung.logging.slf4j
│   │   │   ├── com
│   │   │   │   └── baeldung
│   │   │   │       └── logging
│   │   │   │           └── slf4j
│   │   │   │               ├── Slf4jLoggerFinder.java
│   │   │   │               └── Slf4jLogger.java
│   │   │   └── module-info.java
└──

これで、前のセクションで行ったように、このモジュールをmodsディレクトリにコンパイルできます。

このモジュールをコンパイルするには、slf4j-apijarをmodsディレクトリに配置する必要があることに注意してください。 また、モジュール化されたバージョンのライブラリを使用することを忘れないでください。 最新バージョンはで見つけることができます Maven Central

3.3. ログバックの追加

これでほぼ完了ですが、Logback の依存関係と構成を追加する必要があります。 これを行うには、logback-classicおよびlogback-corejarをmodsディレクトリに配置します。

以前と同様に、ライブラリのモジュール化されたバージョンを使用していることを確認する必要があります。 繰り返しになりますが、最新バージョンは MavenCentralにあります。

最後に、Logback 構成ファイルを作成して mods ディレクトリに配置します。

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>
                %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} -- %msg%n
            </pattern>
        </encoder>
    </appender>

    <root>
        <appender-ref ref="STDOUT"/>
    </root>

</configuration>

3.4. アプリケーションの実行

この時点で、SLF4Jモジュールを使用してappを実行できます。

この場合、ログバック構成ファイルも指定する必要があります。

java --module-path mods \
  -Dlogback.configurationFile=mods/logback.xml \
  -m com.baeldung.logging.app/com.baeldung.logging.app.MainApp

最後に、出力を確認すると、ログバック構成を使用してログが印刷されていることがわかります。

2018-08-25 14:02:40 [main] ERROR MainApp -- error test
2018-08-25 14:02:40 [main] INFO  MainApp -- info test

4. 結論

この記事では、新しい Platform Logging API を使用して Java 9 でカスタム ロガーを作成する方法を示しました。 また、この新しい API の最も有用な使用例の 1 つである、外部ロギング フレームワークを使用した例を実装しました。

いつものように、例の完全なソースコードは、GitHubから入手できます。