きり丸の技術日記

技術検証したり、資格等をここに残していきます。

LombokでToString.IncludeとExclude、callSuperで便利にログ出力する

小ネタ。JavaにはLombokという便利なライブラリがあります。その便利なライブラリの中にあるToString、その中でもIncludeExclude, callSuperを駆使すると便利だったので、ぜひ覚えてください。

この記事では、ToStringInclude, Exclude, callSuperの3つを紹介します。

環境

  • Java
    • 15
  • lombok
    • 1.18.20

ユースケース

アプリケーション起動時に、どういう設定ファイルの値を読み込んでいるかをログに出力して確認したい。

※ アプリケーション起動時に処理させたい時にはPostConstructを使用すると良いです。PostConstructの紹介記事

書くこと

  • ToStirngの機能
    • Include
    • Exclude
    • callSuper

書かないこと

  • ToStringのその他の機能

普段私が使っておらずメリットがわからないので、特に紹介しません。ある程度Lombokも歴史があるので、他の方が纏めてくださっている記事はあるはずです。

今回使用するファイル

他システムに連携するための設定を抽象クラスExternalPropertiesにもち、抽象クラスを継承したFacebookPropertiesTwitterPropertiesを検証に使用する。

@Getter
@Setter
@Slf4j
@ToString
public abstract class ExternalProperties {
  private String host;
  private String protocol;
  private String port;
  private String endpoint;
  private String timeout;

  @ToString.Exclude // ログに出さない
  private String basicUser;
  @ToString.Exclude // ログに出さない
  private String basicPassword;

  @ToString.Include(name = "rootUrl") // デフォルトはメソッド名になる
  public URI getUri() {
    return URI.create(protocol + "://" + host + ":" + port + "/" + endpoint);
  }

  @PostConstruct
  public void display() {
    log.info(this.toString());
  }
}

@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = "external.facebook")
@ToString(callSuper = true)
public class FacebookProperties extends ExternalProperties {
}

@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = "external.twitter")
@ToString(callSuper = true)
public class TwitterProperties extends ExternalProperties {
}

ToStringについて

クラスに@ToStringと付与することで、toString()の結果がハッシュ値ではなくインスタンスの所有する変数を出力するようになります。基本的にはToStringを単体で使用することは少なく、@Valueもしくは@Data@ToStringを包括しているので意識せずに使用していると思われます。

付与していないログ:

FacebookProperties(super=kirimaru.config.FacebookProperties$$EnhancerBySpringCGLIB$$f12ea043@8dfe921)

付与しているログ:

FacebookProperties(super=ExternalProperties(host=localhost, protocol=http, port=10080, endpoint=facebook, timeout=3, rootUrl=http://localhost:10080/facebook))

なお、普段の業務では出てきませんが、競技プログラミング等で循環参照しているデータをデバッグしようとしてログに出力すると、StackOverflowErrorが発生します。注意しましょう。

Include

@ToString.Includeを付与することで、メソッドの結果をtoString()で出力できるようになります。例えば、URIを構築する材料のhostやport等を持った設定ファイルがあったときに、hostがxxx, portがxxxという情報ではなく、そこから構築されるURLを表示したい、といったユースケースで有効活用することができます。

@ToString.Include(name = "rootUrl")
public URI getUri() {
  return URI.create(protocol + "://" + host + ":" + port + "/" + endpoint);
}
FacebookProperties(super=ExternalProperties(host=localhost, protocol=http, port=10080, endpoint=facebook, timeout=3, rootUrl=http://localhost:10080/facebook))

ToString.Includeはrank, nameの変数を所持しています。

  • rank
    • ToStringでの表示順を設定します。デフォルトでは0で、最も後ろに表示されます。この値を100等に設定すると、先頭に表示することもできます。
  • name
    • その名の通り、表示する名前を設定します。デフォルトだとメソッド名が表示されます。

昔はこの設定をofで設定できていたようです。今でもできますが、近いうちにDeperecatedになることがJavaDocに記載されており、ToString.Includeと一緒に扱おうとするとエラーとなります。

java: The old-style 'exclude/of' parameter cannot be used together with the new-style @Include / @Exclude annotations.

Exclude

@ToString.Excludeを変数付与することで、toStringで出力しなくなります。例えば、BASIC認証のID/PASS等は出力したくない、というときに使用できます。

@ToString.Exclude // ログに出さない
private String basicUser;
@ToString.Exclude // ログに出さない
private String basicPassword;

ofと同様に、昔はこの設定をexcludeで設定できていたようです。今でもできますが、近いうちにDeperecatedになることがJavaDocに記載されており、ToString.Excludeと一緒に扱おうとするとエラーとなります。

java: The old-style 'exclude/of' parameter cannot be used together with the new-style @Include / @Exclude annotations.

callSuper

デフォルトではfalseになっています。この設定を使用することで、継承元のToStringの結果を含めることができます。

継承しているファイルでtoString()を使用したい場合は、この設定を含めないと出力元のファイルが何かが分からずに苦労することになります。

callSuper=trueを付与している場合:

TwitterProperties(super=ExternalProperties(host=localhost, protocol=http, port=80, endpoint=twitter, timeout=3, rootUrl=http://localhost:80/twitter))
FacebookProperties(super=ExternalProperties(host=localhost, protocol=http, port=10080, endpoint=facebook, timeout=3, rootUrl=http://localhost:10080/facebook))

callSuper=falseを付与している場合:

ExternalProperties(host=localhost, protocol=http, port=80, endpoint=twitter, timeout=3, rootUrl=http://localhost:80/twitter)
ExternalProperties(host=localhost, protocol=http, port=10080, endpoint=facebook, timeout=3, rootUrl=http://localhost:10080/facebook)

ソースコード

終わりに

正直、Lombokが今後使われるかどうかが分かりません。Lombokはバージョンアップのたびに開発環境の不具合が起きやすいですし、その割にはソースコード的には劇的な変化はないですからね。

Java 16からrecordsという便利な仕組みができたので、Lombokを使用しないようにする、という動きは加速するかと思われます。

個人的にはBuilderクラス等を生成できるので、できればLombokはずっとサポートして欲しいのですが…。

今回学んだことが2021年以降も活かせると嬉しいです。


この記事がお役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。

類似記事

f:id:nainaistar:20210607002313p:plain