サーチ…


特定のタイプのすべてのBeanを自動配線する

同じインターフェースを複数実装している場合、Springはそのすべてをコレクションオブジェクトにオートワイヤリングできます。バリデータパターン1を使用した例を使用します

フークラス:

public class Foo {
     private String name;
     private String emailAddress;
     private String errorMessage;
     /** Getters & Setters omitted **/
}

インタフェース:

public interface FooValidator {
    public Foo validate(Foo foo);
}

名前バリデータクラス:

@Component(value="FooNameValidator")
public class FooNameValidator implements FooValidator {
    @Override
    public Foo validate(Foo foo) {
        //Validation logic goes here.
    }
}

電子メールバリデータークラス:

@Component(value="FooEmailValidator")
public class FooEmailValidator implements FooValidator {
    @Override
    public Foo validate(Foo foo) {
        //Different validation logic goes here.
    }
}

これらのバリデータを個別にまたはクラスにまとめてautowireできるようになりました。

インタフェース:

public interface FooService {
    public void handleFoo(Foo foo);
}

クラス:

@Service
public class FooServiceImpl implements FooService {
    /** Autowire all classes implementing FooValidator interface**/
    @Autowired
    private List<FooValidator> allValidators;

    @Override
    public void handleFoo(Foo foo) {
       /**You can use all instances from the list**/
       for(FooValidator validator : allValidators) {
           foo = validator.validate(foo);               
       }
    }   
}

Spring IoCコンテナに複数のインタフェースを実装していて、 @Qualifierアノテーションで@Qualifierを使用したいのかを指定していない場合、Springは開始しようとすると例外をスローします。なぜなら、どのインスタンスを使用するかはわかりません。

1:これは簡単な検証を行う正​​しい方法ではありません。これは自動配線に関する簡単な例です。 Springがどのようにアノテーションを使用してバリデーションを行うかを、より容易に検証する方法を考えたい場合。

Beanの宣言

Beanを宣言するために、単にと方法を注釈@Bean注釈または持つクラスに注釈を付ける@Componentアノテーション(注釈@Service@Repository@Controller同様に使用することができます)。

JavaConfigがこのようなメソッドに遭遇すると、そのメソッドを実行し、戻り値をBeanFactory内のBeanとして登録します。デフォルトでは、Bean名はメソッド名の名前になります。

Beanは、次の3つの方法のいずれかを使用して作成できます。

  1. Javaベースの設定を使用する :設定ファイルで@beanアノテーションを使用してBeanを宣言する必要があります

    @Configuration
    public class AppConfig {
        @Bean
        public TransferService transferService() {
            return new TransferServiceImpl();
        }
    }
    
  2. XMLベースの設定を使用する :XMLベースの設定では、アプリケーション設定XMLでdeclare beanを作成する必要があります。

     <beans>
         <bean name="transferService" class="com.acme.TransferServiceImpl"/>
     </beans>
    
  3. アノテーション駆動型コンポーネント :アノテーション駆動型コンポーネントでは、Beanとして宣言したいクラスに@Componentアノテーションを追加する必要があります。

     @Component("transferService")
     public class TransferServiceImpl implements TransferService {
         ...
     }
    

transferServiceという名前の3つのBeanはすべて、 BeanFactoryまたはApplicationContext使用できApplicationContext

基本アノテーションオートワイヤリング

インタフェース:

public interface FooService {
    public int doSomething();
}

クラス:

@Service
public class FooServiceImpl implements FooService {
    @Override
    public int doSomething() {
        //Do some stuff here
        return 0;
    }
}

クラスは、このクラスをautowireできるようにSpringのためのインタフェースを実装する必要があることに注意してください。 Springが読み込み時間を使用してスタンドアロンクラスをオートワイヤリングする方法がありますが、この例では範囲外です。

@Autowiredアノテーションを使用してSpring IoCコンテナによってインスタンス化されたどのクラスでも、このBeanにアクセスできます。

使用法:

@Autowired([required=true])

@Autowiredアノテーションは、最初にタイプ別にオートワイヤリングを試み、あいまいな場合にはBean名に戻ります。

この注釈は、いくつかの異なる方法で適用できます。

コンストラクタインジェクション:

public class BarClass() {
    private FooService fooService         

    @Autowired
    public BarClass(FooService fooService) {
        this.fooService = fooService;
    }
}

フィールドインジェクション:

public class BarClass() {
    @Autowired
    private FooService fooService;
}

セッター注入:

public class BarClass() {
    private FooService fooService;

    @Autowired
    public void setFooService(FooService fooService) {
        this.fooService = fooService;
    }
}

動的Beanのインスタンス化のためのFactoryBeanの使用

注入するBeanを動的に決定するために、 FactoryBeanを使用できます。これらは、factoryメソッドパターンを実装するクラスであり、コンテナのBeanのインスタンスを提供します。それらはSpringによって認識され、Beanが工場から来ることを知らずに、透過的に使用することができます。例えば:

public class ExampleFactoryBean extends AbstractFactoryBean<String> {
    // This method determines the type of the bean for autowiring purposes
    @Override
    public Class<?> getObjectType() {
        return String.class;
    }

    // this factory method produces the actual bean
    @Override
    protected String createInstance() throws Exception {
        // The thing you return can be defined dynamically,
        // that is read from a file, database, network or just
        // simply randomly generated if you wish.
        return "Something from factory";
    }
}

構成:

@Configuration
public class ExampleConfig {
    @Bean
    public FactoryBean<String> fromFactory() {
        return new ExampleFactoryBean();
    }
}

Beanを取得する:

AbstractApplicationContext context = new AnnotationConfigApplicationContext(ExampleConfig.class);
String exampleString = (String) context.getBean("fromFactory");

実際のFactoryBeanを取得するには、Beanの名前の前にアンパサンド接頭辞を使用します。

FactoryBean<String> bean = (FactoryBean<String>) context.getBean("&fromFactory");

prototypeまたはsingletonスコープのみを使用することができます - スコープをprototypeオーバーライドisSingletonメソッドに変更するには、

public class ExampleFactoryBean extends AbstractFactoryBean<String> {
    @Override
    public boolean isSingleton() {
        return false;
    }

    // other methods omitted for readability reasons
}

スコープとは、実際に作成されるインスタンスを指し、ファクトリBean自体ではありません。

プロトタイプスコープのBeanをシングルトンに注入する

コンテナはシングルトンBeanを作成し、その中に共同作業者を1回だけ注入します。これは、シングルトンBeanがプロトタイプスコープのコラボレーターを持つ場合、プロトタイプスコープのBeanはアクセサーを介してアクセスされるたびに注入されるため、望ましい動作ではありません。

この問題の解決策はいくつかあります。

  1. 検索メソッドの注入を使用する
  2. javax.inject.Provider介してプロトタイプスコープのBeanを取得する
  3. org.springframework.beans.factory.ObjectFactoryを介してプロトタイプスコープのBeanを取得する(#2に相当するが、Spring固有のクラスを持つ)
  4. ApplicationContextAwareインタフェースを実装してシングルトンBeanコンテナを認識させる

アプローチ#3と#4は、Springフレームワークと強く結びついているので、一般的には推奨されません。したがって、この例では説明しません。

XML設定による抽象メソッドの注入と抽象メソッド

Javaクラス

public class Window {
}

public abstract class WindowGenerator {

    public Window generateWindow() {
        Window window = createNewWindow(); // new instance for each call
        ... 
    }

    protected abstract Window createNewWindow(); // lookup method
}

XML

<bean id="window" class="somepackage.Window" scope="prototype" lazy-init="true"/>

<bean id="windowGenerator" class="somepackage.WindowGenerator">
    <lookup-method name="createNewWindow" bean="window"/>
</bean>

Javaのコンフィグレーションと@Componentによるメソッドの参照のルックアップ

Javaクラス

public class Window {
}

@Component
public class WindowGenerator {

    public Window generateWindow() {
        Window window = createNewWindow(); // new instance for each call
        ...
    }

    @Lookup
    protected Window createNewWindow() {
        throw new UnsupportedOperationException();
    }
}

Java構成

@Configuration
@ComponentScan("somepackage") // package where WindowGenerator is located
public class MyConfiguration {

    @Bean
    @Lazy
    @Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public Window window() {
        return new Window();
    }
}

Javaの設定による手動検索メソッドの注入

Javaクラス

public class Window {
}

public abstract class WindowGenerator {

    public Window generateWindow() {
        Window window = createNewWindow(); // new instance for each call
        ...
    }

    protected abstract Window createNewWindow(); // lookup method
}

Java構成

@Configuration
public class MyConfiguration {

    @Bean
    @Lazy
    @Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public Window window() {
        return new Window();
    }

    @Bean
    public WindowGenerator windowGenerator(){
        return new WindowGenerator() {
            @Override
            protected Window createNewWindow(){
                return window();
            }
        };
    }
}

経由シングルトンにprotoypeスコープのBeanの注入javax.inject.Provider

Javaクラス

public class Window {
}

public class WindowGenerator {

    private final Provider<Window> windowProvider;

    public WindowGenerator(final Provider<Window> windowProvider) {
        this.windowProvider = windowProvider;
    }

    public Window generateWindow() {
        Window window = windowProvider.get(); // new instance for each call   
        ...
    }
}

XML

<bean id="window" class="somepackage.Window" scope="prototype" lazy-init="true"/>

<bean id="windowGenerator" class="somepackage.WindowGenerator">
    <constructor-arg>
        <bean class="org.springframework.beans.factory.config.ProviderCreatingFactoryBean">
            <property name="targetBeanName" value="window"/>
        </bean>
    </constructor-arg>
</bean>

他のスコープに対しても同じ手法を使用できます(たとえば、リクエストスコープのBeanをシングルトンに注入する場合など)。

@Qualifierで特定のBeanインスタンスを自動配線する

同じインターフェースを複数実装している場合、Springはクラスにオートワイヤリングする必要があるかどうかを知る必要があります。この例では、Validatorパターンを使用します。 1

フークラス:

public class Foo {
     private String name;
     private String emailAddress;
     private String errorMessage;
     /** Getters & Setters omitted **/
}

インタフェース:

public interface FooValidator {
    public Foo validate(Foo foo);
}

名前バリデータクラス:

@Component(value="FooNameValidator")
public class FooNameValidator implements FooValidator {
    @Override
    public Foo validate(Foo foo) {
        //Validation logic goes here.
    }
}

電子メールバリデータークラス:

@Component(value="FooEmailValidator")
public class FooEmailValidator implements FooValidator {
    @Override
    public Foo validate(Foo foo) {
        //Different validation logic goes here.
    }
}

これらのバリデーターをクラスに個別にautowireできるようになりました。

インタフェース:

public interface FooService {
    public void handleFoo(Foo foo);
}

クラス:

@Service
public class FooServiceImpl implements FooService {
    /** Autowire validators individually **/
    @Autowired
    /* 
     * Notice how the String value here matches the value 
     * on the @Component annotation? That's how Spring knows which 
     * instance to autowire.
     */
    @Qualifier("FooNameValidator")
    private FooValidator nameValidator;

    @Autowired
    @Qualifier("FooEmailValidator")
    private FooValidator emailValidator;

    @Override
    public void handleFoo(Foo foo) {
        /**You can use just one instance if you need**/
        foo = nameValidator.validate(foo);
    }   
}

Spring IoCコンテナに複数のインタフェースを実装していて、 @Qualifierアノテーションで@Qualifierを使用したいのかを指定していない場合、Springは開始しようとすると例外をスローします。なぜなら、どのインスタンスを使用するかはわかりません。

1:これは簡単な検証を行う正​​しい方法ではありません。これは自動配線に関する簡単な例です。 Springがどのようにアノテーションを使用してバリデーションを行うかを、より容易に検証する方法を考えたい場合。

ジェネリック型パラメータを使用してクラスの特定のインスタンスをオートワイヤする

ジェネリック型パラメータを持つインタフェースを持っている場合、Springはそれを使って、指定した型パラメータを実装する実装だけを自動配線します。

インタフェース:

public interface GenericValidator<T> {
    public T validate(T object);
}

Fooバリデータークラス:

@Component
public class FooValidator implements GenericValidator<Foo> {
    @Override
    public Foo validate(Foo foo) {
        //Logic here to validate foo objects.
    }
}

バーバリデータークラス:

@Component
public class BarValidator implements GenericValidator<Bar> {
    @Override
    public Bar validate(Bar bar) {
        //Bar validation logic here
    }
}

タイプパラメータを使用してこれらのバリデータを自動配線して、どのインスタンスを自動配線するかを決定できるようになりました。

インタフェース:

public interface FooService {
    public void handleFoo(Foo foo);
}

クラス:

@Service
public class FooServiceImpl implements FooService {
    /** Autowire Foo Validator **/
    @Autowired
    private GenericValidator<Foo> fooValidator;

    @Override
    public void handleFoo(Foo foo) {
        foo = fooValidator.validate(foo);
    }   
}


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow