2

次のクラスを検討してください。

public class MyBean {
    private A a;

    @Autowired(required=true)
    public void setA(A a) {
        this.a = a;
    }

    public A getA() {
        return a;
    }
}

たとえば、Spring がインジェクションの候補を 1 つも見つけられない場合など、autowired インジェクションをオーバーライドする必要がある場合があります。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.xsd">

    <bean id="first" class="my.pkg.AImpl"/>
    <bean id="second" class="my.pkg.AImpl"/>
    <bean id="myBeanFirst" class="my.pkg.MyBean">
        <property name="a" ref="first"/>
    </bean>
    <bean id="myBeanSecond" class="my.pkg.MyBean">
        <property name="a" ref="second"/>
    </bean>

</beans>

Java Config で同じことを行う方法はありますか? Spring は myBean メソッドから返された後にプロパティを自動配線しようとし、NoUniqueBeanDefinitionException で失敗するため、次は機能しません (理由は理解しています)。

@Configuration
public class MyConfig {
    @Bean
    public A first() {
        return new AImpl();
    }

    @Bean
    public A second() {
        return new AImpl();
    }

    @Bean
    public MyBean myBeanFirst(A first) {
        MyBean myBean = new MyBean();
        myBean.setA(first);
        return myBean;
    }

    @Bean
    public MyBean myBeanSecond(A second) {
        MyBean myBean = new MyBean();
        myBean.setA(first);
        return myBean;
    }
}

MyBean クラスを変更することは、たとえば、外部ライブラリからのものであるため、常にオプションとは限りません。これは、XML 構成を使用しなければならないケースですか?

ありがとう、アンドレア・ポルチ

更新 2 つのソリューション (名前によるインジェクションと @Primary の使用) に感謝しますが、それらは私のユース ケースを解決しないため、より具体的に説明する必要があると思います。

私のユースケースでは、 MyBean クラスは外部ライブラリから取得されるため、変更はできません。また、MyBean の複数のインスタンスが必要で、それぞれが A インターフェースの異なるインスタンスを注入します。これを反映するために上記のコードを更新しました (xml と Java の両方)。

Java configを使用した解決策はありますか? MyBean への依存関係の自動配線を回避することは可能ですか? (そのクラスの Bean でのみ、コンテキスト内のすべての Bean の自動配線を完全に無効にしないでください)

4

3 に答える 3

3

インジェクションの候補が複数ある場合は、デフォルトの AImpl にする Bean で @Primary を使用して、デフォルトの候補を指定できます。そうすれば、MyBean を変更する必要はありません

于 2014-03-15T08:41:31.767 に答える
3

わかりました。この回答があなたのニーズを満たすと思います。

必要なのは、 classMergedBeanDefinitionPostProcessorのプロパティに正しい値を設定するの実装です。これは、次のクラスで実行できますaMyBean

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.stereotype.Component;


@Component
public class MyBeanPostProcessor implements MergedBeanDefinitionPostProcessor {


    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        if(beanName.equals("myBeanFirst")) {
            beanDefinition.getPropertyValues().add("a", getMyBeanFirstAImpl());
        }
        else if(beanName.equals("myBeanSecond")) {
            beanDefinition.getPropertyValues().add("a", getMyBeanSecondAImpl());
        }
    }

    private Object getMyBeanFirstAImpl() {
        return new AImpl();
    }

    private Object getMyBeanSecondAImpl() {
        return new AImpl();
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

ご覧のとおり、ここの Bean の名前はハードコーディングされていますが、静的な最終文字列に設定することもできます。これは、次のコードの @Bean アノテーションでも使用されます。

@Configuration
public class Configuration {



    @Bean
    public MyBean myBeanFirst() {
        return new MyBean();
    }

    @Bean
    public MyBean myBeanSecond() {
        return new MyBean();
    }

}

次のコードでは、MyBean 作成メソッドで setA が呼び出されないことに気付くでしょう。これは、Spring が Bean ポスト プロセッサを実行するときに、設定した (またはこの場合は設定しなかった) 値に関係なくオーバーライドされるためです。

A のデフォルト値が必要な場合 (たとえば、他の Bean に注入する場合)、前の構成で @Bean の定義に進みます。

于 2014-03-15T17:15:40.340 に答える
0

myBeanFirst を最初に使用する場合は、 を呼び出すだけfirst()です。myBeanSecond についても同様で、2 番目を使用して、second()A を設定するときに呼び出すだけです。

@Configuration
public class MyConfig {
    @Bean
    public A first() {
        return new AImpl();
    }

    @Bean
    public A second() {
        return new AImpl();
    }

    @Bean
    public MyBean myBeanFirst() {
        MyBean myBean = new MyBean();
        myBean.setA(first());
        return myBean;
    }

    @Bean
    public MyBean myBeanSecond() {
        MyBean myBean = new MyBean();
        myBean.setA(second());
        return myBean;
    }
}
于 2014-03-17T15:27:51.480 に答える