依存性注入がパブリックメソッドを使用するのはなぜですか?私が間違っている場合は訂正してください。ただし、反射を使用して実装を変更することは可能です。
5 に答える
DI自体は目標ではありません。DIの目的は、継承よりも合成を優先することで緩い結合を可能にすることです。これは、目的のためにパブリックAPIを公開する場合にのみ可能です。
パブリックAPIがないと、コンポーネントを新しい方法で再構成することはできません。
ColinDが出した答えを詳しく説明するために(Javaをプログラミングする1年まで、パッケージプライベートクラスについてさえ知りませんでした)。DIフレームワークで開発されたアプリを使用すると、インターフェースを公開し、おそらくいくつかの抽象クラスと列挙型を作成すると思います。
package org.my.service;
public interface Service {
public void process();
}
次に、具体的な実装はパッケージプライベート(パブリックキーワードなし)になります
package org.my.service;
class RealService {
public void process() {/*do something*/}
}
これにより、情報隠蔽の概念が適用され、実装の詳細がパブリックAPIに漏れることがなくなります。また、そのパッケージの外部でクラスを使用できないことも意味します(試行すると、コンパイル時エラーが発生します。どこでも「新規」にすることはできません)。
繰り返しますが、ColinDが言ったように、単体テストはorg.my.serviceにあるため、単体テストを行うことができます。
それはかなり包括的な声明であり、真実ではありません。私の好みは、依存性注入にパッケージプライベートコンストラクター(またはパッケージプライベートクラスのパブリックコンストラクター)を使用することです。これにより、クラスをインスタンス化して自分で(リフレクションやインジェクターなしで)注入できるためです。同じパッケージのテストクラスでテストします。
セキュリティポリシーにより、リフレクションAPIを介しても、保護されたメソッド、パッケージプライベートメソッド、またはプライベートメソッドを呼び出すことができない場合があることに注意してください。DIフレームワークがすべての環境で機能する場合、パブリックメソッドにのみ依存できます。
DIフレームワークには、依存性を注入する多くの方法があります
- コンストラクターインジェクション
- セッターインジェクション
- イニシャライザインジェクション
- フィールドインジェクション
最初の3つを使用すると、修飾子public
を使用して、クラスがDIフレームワークの外部で使用されている場合でも、依存関係を手動で設定できます。
ただし、4番目のオプションが広く使用されています。依存関係を手動で設定する必要がある最も一般的なシナリオは、単体テストです。たとえば、その春には、を提供しますReflectionTestUtils
。これにより、1行でフィールドに注入できますが、これは多かれ少なかれ問題ありません。