LombokでToString.IncludeとExclude、callSuperで便利にログ出力する
小ネタ。JavaにはLombokという便利なライブラリがあります。その便利なライブラリの中にあるToString、その中でもIncludeとExclude, callSuperを駆使すると便利だったので、ぜひ覚えてください。
この記事では、ToStringのInclude, Exclude, callSuperの3つを紹介します。
環境
- Java
- 15
- lombok
- 1.18.20
ユースケース
アプリケーション起動時に、どういう設定ファイルの値を読み込んでいるかをログに出力して確認したい。
※ アプリケーション起動時に処理させたい時にはPostConstructを使用すると良いです。PostConstructの紹介記事
書くこと
- ToStirngの機能
- Include
- Exclude
- callSuper
書かないこと
- ToStringのその他の機能
普段私が使っておらずメリットがわからないので、特に紹介しません。ある程度Lombokも歴史があるので、他の方が纏めてくださっている記事はあるはずです。
今回使用するファイル
他システムに連携するための設定を抽象クラスExternalPropertiesにもち、抽象クラスを継承したFacebookPropertiesとTwitterPropertiesを検証に使用する。
@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)
ソースコード
- cucumber-sample/ExternalProperties.java at af6e87fe6d3dabfd24b199479c5a8906e0fd4797 · hirotoKirimaru/cucumber-sample · GitHub
- cucumber-sample/FacebookProperties.java at af6e87fe6d3dabfd24b199479c5a8906e0fd4797 · hirotoKirimaru/cucumber-sample · GitHub
- cucumber-sample/TwitterProperties.java at af6e87fe6d3dabfd24b199479c5a8906e0fd4797 · hirotoKirimaru/cucumber-sample · GitHub
- cucumber-sample/FacebookPropertiesTests.java at 69ba18e4cb8713357b4068f2a0cb4cc20e8d5364 · hirotoKirimaru/cucumber-sample · GitHub
終わりに
正直、Lombokが今後使われるかどうかが分かりません。Lombokはバージョンアップのたびに開発環境の不具合が起きやすいですし、その割にはソースコード的には劇的な変化はないですからね。
Java 16からrecordsという便利な仕組みができたので、Lombokを使用しないようにする、という動きは加速するかと思われます。
個人的にはBuilderクラス等を生成できるので、できればLombokはずっとサポートして欲しいのですが…。
今回学んだことが2021年以降も活かせると嬉しいです。
この記事がお役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。
類似記事
- 【Java】lombokの便利な使い方(Builder編) - きり丸の技術日記
- 【Java】lombokのデフォルトのBuilderに不満があったので、解消方法を調べた(デフォルト値/Validation/再びBuilder) - きり丸の技術日記
- SpringBootでpropertiesやymlの設定ファイルが読み込めることのテストを書く【Java】 - きり丸の技術日記
- Javaで起動後DBの値をキャッシュに持つ等をPostConstructで処理させる(SpringBoot) - きり丸の技術日記
