Spring @Configurationクラスを理解する


108

Spring @Autowiredの使い方理解するという質問に続いて、スプリングワイヤリングの他のオプションである@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代わりにどのように使用できますか?コード自体に影響はありますか?

回答:


151

へのXMLの移行 @Configuration

@Configurationいくつかの手順でxmlをに移行することが可能です。

  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 {
      ...  
    }

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

    @Import(OtherConfiguration.class)
    @Configuration
    public class MyApplicationContext {
      ...
    }
  4. 他のXMLまたは@Configurationクラスをインポートした後@Configuration、次のようにクラスにプライベートメンバーを宣言することにより、コンテキストで宣言したBeanを使用できます。

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

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

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

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

    これはSpEL式でも使用できます。

  6. SpringがそのようなクラスをBeanコンテナーとして扱うことができるようにするには、このタグをコンテキストに配置して、メインxmlでこれをマークする必要があります。

    <context:annotation-config/>

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

    <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が宣言されたメソッドを気にしません。


2
考えられる欠点の1つは、構成が失われることです。開発中の一部の機能を模倣するクラスがあり、それをUAT環境の別のクラスと交換したいとします。XMLを使用する場合、構成を変更し、アプリケーションを実行/再起動できるようにするだけです。これらの新しいクラス構成では、クラスを再コンパイルする必要があります。
ホセ

5
@JoseChavez-それは、私がすでに数回聞いた素晴らしい議論です。そして、jar / warの外でXMLを使用するアプリやシステムが見つからないという統計的調査を試みました。それの実際的な意味は、jarを解凍してXMLを変更する(これを行う人を見つけることができなかった)か、jarを再構築する(これまで話したすべての人が言ったことです) 。つまり、結論としては、かなりの議論になる可能性があるため、実際には重要ではありません。
2014

6
それが@Profileアノテーションと "$ {env.value}"構文の目的です。@Profile( "someName")を使用すると、プロファイル全体がアクティブな場合にのみ使用できるように構成全体にタグを付けることができます。application.properties(または.yml)ファイルで、spring.profiles.active = someName、default ...を設定できます。環境変数に基づいて動的に設定するには、$ {SOME_ENV_VAR}構文をspringの値として使用します。 active.profilesを実行し、環境変数を設定します。-春は現在、Javaの設定使用することをお勧めしますdocs.spring.io/spring-boot/docs/current/reference/htmlsingle/...
ジャックViers

設定ファイルでメソッドとして各Beanを定義する以外の選択肢は何ですか?
Asif Mushtaq 2018

@AsifMushtaq-自動スキャン機能を使用すると、@Component @Serviceアノテーションが含まれている各クラスまたは他のそのようなアノテーションが自動的にBeanになります(ただし、この質問の焦点では​​ありませんでした)
Avi
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.