web-dev-qa-db-ja.com

Springの実装時にApplicationContext.getBean()を使用しないようにする方法IOC

私は春を始めたばかりですIOCコンセプト。インターネットで見つかるほとんどの例では、コードを使用してオブジェクトを取得することがよくあります。

_ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Hello hello = (Hello) appContext.getBean("hello"); 
_

これらの質問からの参照として、stackoverflowの 1 および 2 です。私はそれを推測しました、悪い習慣だと考えられているコードでappContext.getBean( "hello")を使う必要はありません。また、もうお勧めしません。ここで訂正してください。私の推論が間違っている場合。

それを考慮して、プロジェクトに応じて変更を加えました。これが私のapplicationContext.xmlです

_<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean id="utilClassRef" class="org.hd.derbyops.DUtils" lazy-init="false" />
<bean id="appContext" class="org.hd.derbyops.ContextProvider" lazy-init="false">
   <property name="utils" ref="utilClassRef" />
</bean>
</beans>
_

私のcontextProviderクラスコード

_public class ContextProvider implements ApplicationContextAware {

    private static ApplicationContext ctx;

    /**
     * Objects as properties
     */
    private static DUtils utils;

    public void setApplicationContext(ApplicationContext appContext)
            throws BeansException {
        ctx = appContext;

    }

    public static ApplicationContext getApplicationContext() {
        return ctx;
    }

    public static DUtils getUtils() {
        return utils;
    }

    public void setUtils(DUtils dUtilsRef) {
        utils = dUtilsRef;
    }

}
_

たとえば、org.hd.derbyops.DUtilsに依存するクラスAを考えます。次のコード行を使用しています

_ContextProvider.getUtils();
_

クラスAでDUtilsオブジェクトを取得し、コード内のApplicationContext.getBean()の使用を回避するため。

10個のクラスがあり、クラスAがそれらすべてに依存していて、ApplicationContext.getBean()を使用せずにオブジェクトを作成してアクセスするとします。その場合も、上記と同様に、ContextProviderクラスのプロパティを作成し、その後にそのプロパティのセッターおよびゲッターを作成することを考えています。ここで、_get<PropertyName>_は静的です。そのため、オブジェクトが必要なときはどこでも、次のように使用できます。

_ContextProvider.get<PropertyName>;
_

これが私の簡単な質問です。まず、私のアプローチは正しいですか?それが正しければ、起動時にすべてのBeanをロードすることは、パフォーマンスキラーではないでしょうか。 getBeanを少なくとも2回以上呼び出さずに、アプリケーションでそれをどのように実行しますか?

Webアプリケーションを設計し、コードでApplicationContext.getBean()を使用せずにSpring IOCを実装する場合は、どうしますか

注:上記のタグ付けされた他の質問を参照して

ApplicationContext.getBean()の呼び出しは、制御の反転ではありません!

12
srk

簡単な答えは、はい、いいえ、いいえ、いいえです。最後に、おそらく春MVCをオンラインで検索します。

それで、あなたのアプローチ。はい、あなたはそれのほとんどを正しく持っています。ただし、すべてに対して静的メソッドを使用することは非常に悪い習慣と見なされています。そして、あなたはする必要はありません。 Springは、通常のpojoを簡単に作成することができ、Springはそれらをシングルトンとして使用し、それらを相互に注入するという考えに基づいています(オブジェクトをその場で作成することもできますが、ここでは一般的なケースを取り上げます)。静的クラスとメソッドを使用する場合:

  • 単体テスト用にそれらをモックすることはできません(JUnitを正しく使用していますか?)
  • 継承では使用できません
  • 静的イニシャライザは、例外を緩和する優れた方法です
  • などなど

だから、注射にはそうです、そして静的なものにはいいえ。

次に、パフォーマンス。春を使用するのはかなり遅いというのはあなたの言う通りですが、起動時にすべての注入を行うと、それは一度だけ起こります。 Springは、データをやり取りするシングルトンクラスが多数存在する可能性が高いサーバー側アプリケーション向けです。したがって、DBからデータを取得するクラス、それを処理するクラス、表示するクラスがあり、それらを相互に接続するためにSpringが使用されます。

コマンドラインアプリのように、繰り返し起動するアプリケーションでSpringを使用している場合は、Springを間違った種類のアプリケーションに使用しており、おそらくビルダーなどを使用する必要があります。 Springは、頻繁に再起動されない大規模エンタープライズアプリ向けです。

最後に、起動時にクラスのすべての依存関係をクラスに注入するだけで、すべてのクラスでこれを実行する場合は、getBeanを行う必要はまったくありません。また、init-methodおよびdestroy-method Beanの属性は、Springが依存関係の注入を終了するとプロセスを起動できることを意味します。必要なのはコンテキストをロードすることだけであり、アプリは存在するようになります。

Webプロジェクトに関しては、Spring MVCは基本的に制御パターンの全体的な反転を取り、それをWebアプリケーションに適用します。 Springのものはコンテナーによってロードされ、Bean名以外のものを使用せずに応答するURLを定義できます。そして、ほとんどのコードはpojoとしてとどまることができます。非常に複雑なものがある場合は、春のWebフローを確認することをお勧めしますが、それを試す前に、春のfooが非常に強力であることを確認することをお勧めします。

9
Jimadilo

実際にApplicationContextgetBean()を呼び出さずに最初のインスタンスを取得する私の例を次に示します。

public class Test{
  // Declare private static variable so that we can access it in main()
  private static Triangle triangle;

  // Use constructor injection to set the triangle
  public Test(Triangle triangle) {
      Test.triangle = triangle;
  }

  public static void main(String[] args) {
      // Specify the context file containing the bean definitions
      // Spring automatically creates instances of all the beans defined
      // in this XML file. This process is performed before you actually make
      // a getBean("beanName") call.
      ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");

      // Use instance methods of triangle 
      Test.triangle.draw();
  }
} 

別の方法を使用できます。

spring.xml(Bean構成XMLファイル)

<bean class="com.example.Test" init-method="myMethod">
    <constructor-args ref="triangle"/>
</bean>

あなたのメインクラスのために

public class Test {
  private final Triangle triangle;

  public Test (Triangle triangle) {
     this.triangle = triangle;
  }

  public static void main (String[] args) {
     ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
  }

  // Called by Spring immediately after the Triangle Bean has been created and
  // all the properties for the bean have been set. This method name must match
  // the one specified with destroy-method attribute in spring.xml
  public void myMethod () {
     triangle.draw();
  }
}
1
rIshab1988