1. ホーム
  2. java

[解決済み] Springの@Configurationクラスを理解する

2022-05-17 11:22:59

質問

質問に続く Springの@Autowiredの使い方を理解する 私は、Springの配線のもう一つの選択肢である @Configuration クラスについてです。

このようなspring 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.0.xsd">

  <import resource="another-application-context.xml"/>

  <bean id="someBean" class="stack.overflow.spring.configuration.SomeClassImpl">
    <constructor-arg value="${some.interesting.property}" />
  </bean>

  <bean id="anotherBean" class="stack.overflow.spring.configuration.AnotherClassImpl">
    <constructor-arg ref="someBean"/>
    <constructor-arg ref="beanFromSomewhereElse"/>
  </bean>
</beans>

どのようにすれば @Configuration を使うことができますか?コード自体に何か影響があるのでしょうか?

どのように解決するのですか?

XML を @Configuration

XML を @Configuration を数ステップで実行できます。

  1. を作成します。 @Configuration アノテーションを付けたクラスを作成します。

    @Configuration
    public class MyApplicationContext {
    
    }
    
    
  2. それぞれについて <bean> タグでアノテーションされたメソッドを作成します。 @Bean :

    @Configuration
    public class MyApplicationContext {
    
      @Bean(name = "someBean")
      public SomeClass getSomeClass() {
        return new SomeClassImpl(someInterestingProperty); // We still need to inject someInterestingProperty
      }
    
      @Bean(name = "anotherBean")
      public AnotherClass getAnotherClass() {
        return new AnotherClassImpl(getSomeClass(), beanFromSomewhereElse); // We still need to inject beanFromSomewhereElse
      }
    }
    
    
  3. インポートするために beanFromSomewhereElse をインポートするためには、その定義をインポートする必要があります。これはXMLで定義することができ、ここでは @ImportResource :

    @ImportResource("another-application-context.xml")
    @Configuration
    public class MyApplicationContext {
      ...  
    }
    
    

    ビーンが別の @Configuration クラスで定義されている場合は @Import アノテーションを使用します。

    @Import(OtherConfiguration.class)
    @Configuration
    public class MyApplicationContext {
      ...
    }
    
    
  4. 他のXMLをインポートした後、あるいは @Configuration クラスをインポートした後、プライベートメンバを @Configuration クラスに対して以下のように private member を宣言することで、そのクラスが宣言している Bean を利用することができます。

    @Autowired
    @Qualifier(value = "beanFromSomewhereElse")
    private final StrangeBean beanFromSomewhereElse;
    
    

    あるいは、これに依存するBeanを定義するメソッドのパラメータとして直接使用します。 beanFromSomewhereElse を使って @Qualifier を次のようにします。

    @Bean(name = "anotherBean")
    public AnotherClass getAnotherClass(@Qualifier (value = "beanFromSomewhereElse") final StrangeBean beanFromSomewhereElse) {
      return new AnotherClassImpl(getSomeClass(), beanFromSomewhereElse);
    }
    
    
  5. プロパティのインポートは、他のXMLやXMLからBeanをインポートするのと非常によく似ています。 @Configuration クラスからビーンをインポートするのと非常に似ています。を使う代わりに @Qualifier を使う代わりに @Value を以下のようにプロパティで指定します。

    @Autowired
    @Value("${some.interesting.property}")
    private final String someInterestingProperty;
    
    

    これは SpEL の表現にも使えます。

  6. springがこのようなクラスをBeanコンテナとして扱えるようにするために、メインxmlのコンテキストにこのタグを記述してマークする必要があります。

    <context:annotation-config/>
    
    

    これで @Configuration クラスを、単純なビーンを作るのと全く同じようにインポートできるようになりました。

    <bean class="some.package.MyApplicationContext"/>
    
    

    Spring XMLを完全に回避する方法もありますが、この回答の範囲ではありません。これらのオプションの1つは、私の ブログ記事 を参考にしてください。


この方式を使用するメリットとデメリット

基本的に私は、この方法でBeanを宣言する方がXMLを使うよりもはるかに快適であると感じています。

  1. タイプミス - @Configuration クラスはコンパイルされ、タイポはコンパイルを許可しません。
  2. フェイルファスト(コンパイル時) - Beanの注入を忘れると、XMLのように実行時ではなく、コンパイル時に失敗します。
  3. IDE でのナビゲートが容易 - 依存関係ツリーを理解するために、Bean のコンストラクタ間を移動することができます。
  4. 設定起動時のデバッグを容易にすることができる。

デメリットは私が見る限り多くはないのですが、思い当たる節がいくつかあります。

  1. 不正使用 - コードはXMLより悪用しやすい
  2. XML では、コンパイル時には利用できないが実行時には提供されるクラスに基づいて依存関係を定義することができます。これは @Configuration クラスでは、コンパイル時にそのクラスが利用可能でなければなりません。通常は問題にはなりませんが、場合によってはそうなる可能性もあります。

結論から言うと XML を結合することは全く問題ありません。 @Configuration アノテーション をアプリケーションコンテキストに追加します。SpringはBeanが宣言されたメソッドを気にしません。