2017-10-25 14 views
1

Hallo Spring Container LevelのBeanファクトリにある別の実装間で、プログラムで候補を選択する方法を探したいと思います。プログラムでのBean注入の解決

プロファイルと私は単にこの

のようにそれを達成することができ、私持っている以下のプロファイルの「CH」と「IT」は、私はそれで豆プロファイル下がある場合は、デフォルトにフォールバックすることを望みます。

を考えると、これらのクラス:

デフォルト実装

@Component 
public class DefaultMapper { 
    public void doSomething() { 
     System.out.println("Map Default"); 
    } 
} 

スイス実装

@Component 
@Profile("CH") 
public class SwissMapper extends DefaultMapper { 

    @Override 

    public void doSomething() { 

     System.out.println("do something swiss"); 

    } 

} 

イタリアの実装:今

@Component 
@Profile("IT") 
public class ItalianMapper extends DefaultMapper { 
@Override 
    public void doSomething() { 
     System.out.println("do pasta"); 
    } 
} 

私はそれを実行した場合@ActiveProfiles("IT")とするとNoUniqueBeanDefinitionExceptionがスローされます。これは、Defaultがプロファイルされていないので十分であり、コンテナによってそれ以上の注意を払うことなく登録されます。

考察:

私はDefaultMapper@Profile("default")を追加した場合、私は別のデフォルトBeanがONLY CHでプロファイルサブクラスを持っている持ってまで、これは動作します。

別のBeanのデフォルトの実装:

@Component 
@Profile("default") 
public class DefaultParser { 
    public void doSomething() { 
     System.out.println("Parse Default"); 
    } 
} 

その後スイスの実装(NOイタリア語が使用できない、またはより良いデフォルトはイタリアのために収まる言った):

@Component 
@Profile("CH") 
public class SwissParser extends DefaultParser { 
@Override 
public void doSomething() { 
    System.out.println("Ässe Ässe"); 
} 

}

@ActiveProfiles("IT")を実行するとNo BeanDefinitionExceptionがスローされますが、「デフォルト」がActiveProfilesとしてチェーン化されていないため私は実装がありません。ここでのCHプロファイルは、各デフォルトクラスのプロファイリングされた実装があるので動作します。私は専門を持っているそれらのプロファイルを除外@Profile({"default","IT", "<all other profiles which have NOT a specialized implementation"}など、または@Profile("!CH")デフォルトクラスに定義する必要 - :

は 私はせずに、このシナリオをカバーするためのより良い方法をしたいと思いますと言いました。私はここで、iこれを解決したいと思います)次に

; - DefaultMapperに私は@Primaryとしてマークされ、コンテナがすべてでそれを好きではない専門に持っているので、私が思う@Primaryは、soultionではありませんすべての注入されたクラスを決定することができます。Beanの解決があいまいである場合、実装を選択したい(コンテナ内で)プログラム的に決定したいと思います。 i.E nationality.cantidate = CHのapplication.propertiesに設定された値と比較して、@Profile、i.E @Candidate( "CH")と同様にAnnotationが適していると思います。何かのように:私はCDI SPI延長ウィッヒと同様の過去の何かでやった

public class MyExtension extends UnknowSpringType { 
    @Override 
    Object resolveAmbigousDependency(final Context ctx, final Resolution resolution) { 
     final List<Class> clazzes = resolution.getResolvedClasses(); 
     for (final Class clazz : clazzes) { 
      if (clazz.isAnnotationPresent(Candidate.class) && clazz.getAnnotation(Candidate.class).getVaue().equals(candidateApplicationPropertyValue)) { 
      return clazz; 
     } 
     return getDefaultImplementation(clazzes); 
    } 
} 

エレガントであり、また、私はCDIから@Specializesと別の方法でこれをカバーすることができますが、私は上と同じ簡単な方法を見つけることができません春(私はあまり経験がない)、BeanFactory? BeanFactoryPostProcessor

ヘルプ?

答えて

1

すべての特定のパーサーを@Primaryとしてマークすることができます。これは、@Primaryとしてマークされていないデフォルトのパーサーではなく、Springがこれをオートワイヤリングすることを保証します。選択されたプロファイルに特定のパーサーが存在しない場合、@Primary以外のデフォルトコンポーネントにフォールバックします。

参照:https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/Primary.html

@Component 
public class DefaultParser { 
    public void doSomething() { 
     System.out.println("Parse Default"); 
    } 
} 


@Component 
@Primary 
@Profile("CH") 
public class SwissParser extends DefaultParser { 
@Override 
public void doSomething() { 
    System.out.println("Ässe Ässe"); 
} 
+0

のデモがうまくいくように見えますが、このようなものを試してみたところ、動作していなかったのでもう一度試してみます。 ' @Primary @Profile(値= {MigrationProfiles.DEFAULT}) @Target({ElementType.TYPE、ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented公共@interfaceのPrimaryProfiles { @AliasFor(annotation = Profile.class、attribute = "value") String [] value(); } ' – Tama

+0

幸いにも、私は愚かです、私のシナリオではプライマリで私はデフォルトクラスで@Primaryを取ることを忘れていました。私をこの世界に連れてきてくれてありがとう。 – Tama

+0

いいえ、私は助けることができてうれしい – Plog

0

あなたは、複数のプロファイルをアクティブにCHとITとあなたの実装が失敗することができます。

国際化の問題です。

+0

これは例であり、複数の国を実行すると失敗するはずです。 – Tama

関連する問題