2017-05-10 14 views
1

私は知っているので、同様のことを尋ねる多くの質問がありますが、それらを使ってこの状況から抜け出すことはできません。Spring Bootとapplication.ymlを使用してMap <String、Double>を挿入する

私はSpringブートアプリケーションを持っています。

@SpringBootApplication 
@EnableConfigurationProperties 
public class Application implements ApplicationRunner { 
    public static void main(String[] args) { 
     SpringApplication.run(Application .class, args); 
    } 
} 

次に、次のクラスがあります。

@Component 
@ConfigurationProperties(prefix = "somePrefix") 
public class AClass { 
    private final AnotherClass anotherClass; 
    private final Map<String, Double> aMap; 

    @Autowired 
    public AffinityChecks(AnotherClass anotherClass, 
          Map<String, Double> aMap) { 
     this.anotherClass = anotherClass; 
     this.aMap = aMap; 
    } 

    // Omissis 

最後に、次のapplication.yml設定ファイルがあります。

somePrefix: 
    aMap: 
    key1: 0.6 
    key2: 0.2 
    key3: 0.2 

私が欲しいのは、構築プロセス中にタイプAClassのオブジェクトにマップを注入する春です。私が得るエラーは次のとおりです。

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.util.Map<java.lang.String, java.lang.Double>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} 

何が起こっていますか?

ありがとうございます。

+0

"Map aMap"をコンストラクタから削除してください。 https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-complex-type-merge – MrKiller21

+0

"aMap"がSpringによってもう初期化されていないため、コンストラクタからマップする) –

+1

マップにゲッターを追加する必要がある – MrKiller21

答えて

1

スプリングブートは、環境にバインドされている要素のコンストラクタインジェクションをサポートしていません。もちろん、実際の豆を通常の方法で注入することができます。

バインドする各プロパティを通常のJavabeanプロパティ(getter/setterを使用)として定義する必要があります。このルールには1つの例外があります。マップとスカラー以外の値(ネストされたコンテンツ)はゲッターのみ必要です。

具体的には、AnotherClassがbeanであり、FooClassのプロパティがネストされたものです。

@Component 
@ConfigurationProperties(prefix = "somePrefix") 
public class AClass { 
    private final AnotherClass anotherClass; 
    private final Map<String, Double> aMap = new HashMap<>(); 
    private final FooClass foo = new FooClass(); 

    public AClass(AnotherClass anotherClass) { ...} 

    public Map<String, Double> getaMap() { ... } 

    public FooClass getFoo() { ... } 

} 

(ゲッターはプロパティの名前を推測するものであることに注意してください。例では、あなたがFooClassgetXyz()を持っていた場合は、somePrefix.foo.xyzをマップすることができ、上記)。

追加の詳細についてはin the documentationの例があります。

(あなたのコードが間違っているということは、マップがBeanではないので、達成しようとしていたものに対しては@Autowiringが適切な意味ではないということです)。

+0

'AnotherClass' **は** beanです。実際、私はこのケースではコンストラクタインジェクションを使わない方が大好きです:( –

+0

あなたはanotherclasを注入できます。問題ありません。コンストラクタがバインドするものを注入するのをサポートしていません。私は私の答えを更新しました。 –

+0

それはまさに私がやったことです。ありがとう。しかし、最適な解決策は、構成ファイルから読み込まれたすべての値を専用オブジェクト(ビジネスタイプ 'AClass'ではなく)にカプセル化することだと思っています。 –