web-dev-qa-db-ja.com

ランタイムコンストラクター引数を持つSpring Bean

Spring Java configuration実行時に渡されるコンストラクタ引数を使用して、Spring Beanを作成します。次のJava config。BeanがありますfixedLengthReportコンストラクターでいくつかの引数が必要です。

@Configuration
public class AppConfig {

    @Autowrire
    Dao dao;

    @Bean
    @Scope(value = "prototype")
    **//SourceSystem can change at runtime**
    public FixedLengthReport fixedLengthReport(String sourceSystem) {
         return new TdctFixedLengthReport(sourceSystem, dao);
    }
}

しかし、Beanが見つからないためsourceSystemを配線できなかったというエラーが表示されます。ランタイムコンストラクター引数を使用してBeanを作成するにはどうすればよいですか?

Spring 4.2を使用しています

23
suraj bahl

BeanFactoryと共にプロトタイプBeanを使用できます。

_@Configuration
public class AppConfig {

   @Autowired
   Dao dao;

   @Bean
   @Scope(value = "prototype")
   public FixedLengthReport fixedLengthReport(String sourceSystem) {
       return new TdctFixedLengthReport(sourceSystem, dao);
   }
}
_

@Scope(value = "prototype")は、Springが起動時にBeanをすぐにインスタンス化せず、要求に応じて後でインスタンス化することを意味します。ここで、プロトタイプBeanのインスタンスをカスタマイズするには、次のことを行う必要があります。

_@Controller
public class ExampleController{

   @Autowired
   private BeanFactory beanFactory;

   @RequestMapping("/")
   public String exampleMethod(){
      TdctFixedLengthReport report = 
         beanFactory.getBean(TdctFixedLengthReport.class, "sourceSystem");
   }
}
_

Beanは起動時にインスタンス化できないため、Beanを直接Autowireしないでください。そうしないと、SpringはBean自体をインスタンス化しようとします。この使用法ではエラーが発生します。

_@Controller
public class ExampleController{

   //next declaration will cause ERROR
   @Autowired
   private TdctFixedLengthReport report;

}
_
41
Ken Bekov

コードは問題なく見えます。パラメータ付きのプロトタイプを取得するには、BeanFactory#getBean(String name、Object ... args)メソッドを使用します。

Spring Java Config:ランタイム引数でプロトタイプスコープの@Beanをどのように作成しますか? BeanFactory#getBean(String name、Object ... args)を見てくださいあなたが探しているものであること。

あなたのIDEA(私の場合はIntelliJ IDEAバージョン15))がエラーを与え、それがランタイム/コンパイル時エラー

IntelliJでは、Springインスペクションの設定を変更できます。

  • ファイル->設定に移動します。
  • 検索ボックスに検査を入力します。
  • Spring Core-> Code-> Autowire for Bean Classesに移動します。
  • 「エラー」から「弱い警告」に変更します
2
Haim Raman

これは、Spring 4.3で導入されたSpringのObjectProvider<>クラスで実現できます。詳細については、Springの ドキュメント を参照してください。

要点は、提供されるオブジェクトのBeanファクトリメソッドを定義し、ObjectProvider<>をコンシューマに挿入し、提供されるオブジェクトの新しいインスタンスを作成することです。

public class Pair
{
    private String left;
    private String right;

    public Pair(String left, String right)
    {
        this.left = left;
        this.right = right;
    }

    public String getLeft()
    {
        return left;
    }

    public String getRight()
    {
        return right;
    }
}

@Configuration
public class MyConfig
{
    @Bean
    @Scope(BeanDefinition.SCOPE_PROTOTYPE)
    public Pair pair(String left, String right)
    {
        return new Pair(left, right);
    }
}

@Component
public class MyConsumer
{
    private ObjectProvider<Pair> pairProvider;

    @Autowired
    public MyConsumer(ObjectProvider<Pair> pairProvider)
    {
        this.pairProvider = pairProvider;
    }

    public void doSomethingWithPairs()
    {
        Pair pairOne = pairProvider.getObject("a", "b");
        Pair pairTwo = pairProvider.getObject("z", "x");
    }
}

注:実際にObjectProvider<>インターフェイスを実装するわけではありません。 Springは自動的にそれを行います。 Beanファクトリメソッドを定義するだけです。

0
HairOfTheDog