小ネタ。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) - きり丸の技術日記