ロンボク島での春のコンストラクター注入
1. 序章
Lombokは、ボイラープレートコードを克服する非常に便利なライブラリです。 まだ慣れていない場合は、前のチュートリアル– ProjectLombokの概要を参照することを強くお勧めします。
この記事では、Springのコンストラクターベースの依存性注入と組み合わせた場合の使いやすさを示します。
2. コンストラクターベースの依存性注入
constructorベースの依存性注入を使用してSpringの依存性を配線する良い方法。 このアプローチでは、コンポーネントの依存関係をコンストラクターに明示的に渡す必要があります。
フィールドベースの依存性注入とは対照的に、次のような多くの利点もあります。
- テスト固有の構成コンポーネントを作成する必要はありません–依存関係はコンストラクターに明示的に注入されます
- 一貫性のある設計–必要なすべての依存関係が強調され、コンストラクターの定義によって管理されます
- シンプルな単体テスト–SpringFrameworkのオーバーヘッドを削減
- 最終的なキーワードを使用する自由を取り戻しました
ただし、コンストラクターを作成する必要があるため、コンストラクターを使用すると、コードベースが大幅に大きくなります。 GreetingServiceとFarewellService:の2つの例を考えてみましょう。
@Component
public class GreetingService {
@Autowired
private Translator translator;
public String produce() {
return translator.translate("hello");
}
}
@Component
public class FarewellService {
private final Translator translator;
public FarewellService(Translator translator) {
this.translator = translator;
}
public String produce() {
return translator.translate("bye");
}
}
基本的に、両方のコンポーネントは同じことを行います。タスク固有の単語を使用して、構成可能なTranslaterを呼び出します。
ただし、2番目のバリエーションは、コンストラクターのボイラープレートがコードに実際に値をもたらさないため、はるかに難読化されています。
最新のSpringリリースでは、コンストラクターに@Autowiredアノテーションを付ける必要はありません。
3. Lombokによるコンストラクターインジェクション
Lombok を使用すると、すべてのクラスのフィールド( @AllArgsConstructor を使用)またはすべての最終的なクラスのフィールド(
前の2つに類似した3番目のコンポーネントを作成しましょう。
@Component
@RequiredArgsConstructor
public class ThankingService {
private final Translator translator;
public String produce() {
return translator.translate("thank you");
}
}
上記のアノテーションにより、Lombokはコンストラクターを生成します。
@Component
public class ThankingService {
private final Translator translator;
public String thank() {
return translator.translate("thank you");
}
/* Generated by Lombok */
public ThankingService(Translator translator) {
this.translator = translator;
}
}
4. 複数のコンストラクター
コンポーネントにコンストラクターが1つしかない限り、コンストラクターに注釈を付ける必要はありません。Springは、新しいオブジェクトをインスタンス化するための適切なコンストラクターとして明確に選択できます。 さらにある場合は、IoCコンテナで使用されるものにも注釈を付ける必要があります。
ApologizeServiceの例を考えてみましょう。
@Component
@RequiredArgsConstructor
public class ApologizeService {
private final Translator translator;
private final String message;
@Autowired
public ApologizeService(Translator translator) {
this(translator, "sorry");
}
public String produce() {
return translator.translate(message);
}
}
上記のコンポーネントは、オプションで message フィールドを使用して構成できます。このフィールドは、コンポーネントの作成後に変更できません(したがって、セッターがありません)。 したがって、2つのコンストラクターを提供する必要がありました。1つは完全な構成で、もう1つはmessageの暗黙のデフォルト値です。
コンストラクターの1つに@Autowired 、 @Inject 、または @Resource のいずれかで注釈が付けられていない限り、Springはエラーをスローします。
Failed to instantiate [...]: No default constructor found;
Lombok- で生成されたコンストラクターに注釈を付ける場合は、@AllArgsConstructorのonConstructorパラメーターを使用して注釈を渡す必要があります。
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ApologizeService {
// ...
}
onConstructor パラメーターは、生成されたコンストラクターに配置される注釈の配列(またはこの特定の例のような単一の注釈)を受け入れます。 下位互換性の問題のために、二重アンダースコアのイディオムが導入されました。 ドキュメントによると:
奇妙な構文の理由は、この機能をjavac7コンパイラで機能させるためです。 the
@__
typeは、注釈タイプへの注釈参照です__
(二重下線)これは実際には存在しません。 これにより、アノテーションプロセッサが後で作成する可能性があるため、エラーが原因でjavac7がコンパイルプロセスの中止を遅らせることになります。__
タイプ。
5. 概要
このチュートリアルでは、ボイラープレートコードの増加という観点から、コンストラクターベースのDIよりもフィールドベースのDIを優先する必要がないことを示しました。
Lombokのおかげで、実行時にパフォーマンスに影響を与えることなく、一般的なコード生成を自動化することができ、1行の注釈を使用することで長くてわかりにくいコードを省略できます。
チュートリアルで使用されるコードは、GitHubでから入手できます。