私は一般的な Spring に関する質問をしました:自動キャストスプリングビーンズそして、複数の人が、Spring への電話はApplicationContext.getBean()
できるだけ避けるべきだと答えました。それはなぜでしょうか?
Spring で作成するように構成した Bean にアクセスするには、他にどのような方法がありますか?
私は非WebアプリケーションでSpringを使用しており、共有ApplicationContext
オブジェクトにアクセスすることを計画していましたLiorH による説明。
修正
私は以下の回答を受け入れますが、マーティン・ファウラーによる別の見解があります。依存性注入とサービスロケータの使用のメリットについて説明します。(これは本質的にはラップされた を呼び出すことと同じですApplicationContext.getBean()
)。
ファウラー氏は次のように述べている。「サービス ロケータでは、アプリケーション クラスがロケータへのメッセージによって明示的にサービスを求めます。インジェクションでは明示的な要求はなく、サービスはアプリケーション クラス内に表示されます。これが制御の反転です。制御の反転はフレームワークの一般的な機能ですが、代償が伴います。理解しにくい傾向があり、デバッグしようとすると問題を引き起こします。したがって、全体として、必要でない限り、制御の反転は避ける方が好きです。これは悪いことだと言っているのではなく、より単純な代替手段よりも正当化する必要があると考えているだけです。」
ベストアンサー1
他の質問のコメントでも触れましたが、制御の反転の全体的な考え方は、どのクラスも、依存するオブジェクトをどのように取得するかを知らず、気にも留めないことです。これにより、特定の依存関係のどのタイプの実装を使用するかをいつでも簡単に変更できます。また、依存関係のモック実装を提供できるため、クラスのテストも簡単になります。最後に、クラスはよりシンプルになり、コアの役割に重点が置かれるようになります。
呼び出しはApplicationContext.getBean()
制御の反転ではありません。特定の Bean 名に対して構成されている実装を変更することは依然として簡単ですが、クラスは依存関係を提供するために Spring に直接依存するようになり、他の方法では取得できなくなります。テスト クラスで独自のモック実装を作成し、それを自分で渡すことはできません。これは基本的に、依存性注入コンテナーとしての Spring の目的に反します。
どこでも言いたいこと:
MyClass myClass = applicationContext.getBean("myClass");
代わりに、たとえば次のようにメソッドを宣言する必要があります。
public void setMyClass(MyClass myClass) {
this.myClass = myClass;
}
そして、設定では次のようになります。
<bean id="myClass" class="MyClass">...</bean>
<bean id="myOtherClass" class="MyOtherClass">
<property name="myClass" ref="myClass"/>
</bean>
その後、Spring は自動的myClass
に に注入されますmyOtherClass
。
このようにすべてを宣言し、その根底には次のようなものがあります。
<bean id="myApplication" class="MyApplication">
<property name="myCentralClass" ref="myCentralClass"/>
<property name="myOtherCentralClass" ref="myOtherCentralClass"/>
</bean>
MyApplication
は最も中心的なクラスであり、プログラム内の他のすべてのサービスに少なくとも間接的に依存します。main
メソッド内でブートストラップするときに、を呼び出すことはできますapplicationContext.getBean("myApplication")
が、他の場所で呼び出す必要はありませんgetBean()
。