春ブート中の多型の構成プロパティ

Cttt:

私は、Springの使用、春に多型の構成プロパティを使用したい@ConfigurationProperties注釈を。

私たちは、次のPOJOクラスがあるとします。

public class Base {
  private String sharedProperty;

  public String getSharedProperty() {
    return sharedProperty;
  }

  public String setSharedProperty(String sharedProperty) {
    this.sharedProperty = sharedProperty;
  }
}

public class Foo extends Base {
  private String fooProperty;

  public String getFooProperty() {
    return fooProperty;
  }

  public String setFooProperty(String sharedProperty) {
    this. fooProperty = fooProperty;
  }
}

public class Bar extends Base {
  private String barProperty;

  public String getSharedProperty() {
    return sharedProperty;
  }

  public String setBarProperty(String barProperty) {
    this.barProperty = barProperty;
  }
}

および構成プロパティクラス、

@Component
@ConfigurationProperties(prefix = "playground")
public class SomeConfigurationProperties {
  private List<Base> mixed;

  public List<Base> getMixed() {
    return mixed;
  }

  public void setMixed(List<Base> mixed) {
    this.mixed = mixed;
  }
}

そして、application.ymlファイル、

playground:
  mixed:
    - shared-property: "shared prop"
      foo-property: "foo prop"
    - shared-property: "shared prop"
      bar-property: "bar prop"

しかし、この構成では、春には、初期化@ConfigurationPropertiesのリストを-annotatedクラスをBase代わりにそれらのサブクラスのオブジェクト。これは、実際には、(セキュリティ上の懸念に)期待される動作です。

行動強制する方法がありSnakeYAMLをサブクラスを使用して、またはカスタム直列化復元プロバイダのいずれかの種類を実装するためには?

aweigold:

それはカスタムPropertySourcesおよび/または実装することは可能ですがConversionServiceを、カスタムのデシリアライゼーションプロバイダは必要ありません。

春は複数のBeanに同じ結合特性を全く問題がありません。あなただけとのApplicationContextと1つのBeanを登録しているので、あなたの実装が機能していない理由は、@Componentベースクラス上の注釈。これはタイプの唯一のシングルトンがあることコンポーネントのスキャナを語っていますBaseのでFooとはBar豆として登録されていない、彼らはにバインドされることはありません。

あなたはこれらの多型を作る見ている唯一の理由はで共有プロパティ名のプレフィックスにある場合SnakeYAMLベースの設定、あなたは実際に多型の関係を導入する必要はありませんし、異なるクラスに共通のフィールド名で共有されるプロパティにバインドすることができます。

、ここで最もまっすぐ進む簡単なもののほんの一部です何をポリモーフィックな方法でしかし求めている実装するための多くの方法があります。

自己豆シングルトンポリモーフィックConfigurationPropertiesを宣言

代わりに適用するの@ConfigurationProperties@Component、基本クラスに注釈を、同じプロパティ名の接頭辞で、具体的なクラスに適用します。各Beanが設定され、その性質上、条件付きではありませんので、これはしかし、それはあなたのニーズに合わせて、私の好ましい方法ではないでしょう。あなたの春の構成プロパティを再ロードすることができます場合によっては、春には、豆のすべてのバインディングを維持します。

注:IntelliJのアイデア2018.3のように、検査プロファイルはエラーとして重複プレフィックスキーを識別するために添加しました。あなたはこれを無視する、または警告を抑制することができます。

私は成功し、次のテスト:

Base.java

package sample;

public class Base {
    private String sharedProperty;

    public String getSharedProperty() {
        return sharedProperty;
    }

    public void setSharedProperty(String sharedProperty) {
        this.sharedProperty = sharedProperty;
    }
}

Foo.java

package sample;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties("playground")
public class Foo extends Base {
    private String fooProperty;

    public String getFooProperty() {
        return fooProperty;
    }

    public void setFooProperty(String fooProperty) {
        this.fooProperty = fooProperty;
    }
}

Bar.java

package sample;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties("playground")
public class Bar extends Base {
    private String barProperty;

    public String getBarProperty() {
        return barProperty;
    }

    public void setBarProperty(String barProperty) {
        this.barProperty = barProperty;
    }
}

application.yml

playground:
  shared-property: "shared prop"
  foo-property: "foo prop"
  bar-property: "bar prop"

SampleAppTest.java

package sample;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.env.Environment;

import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;

@SpringBootTest
public class SampleAppTest {

    @Autowired
    public Environment environment;

    @Test
    public void test(@Autowired Bar bar, @Autowired Foo foo) {
        assertEquals("shared prop", bar.getSharedProperty());
        assertEquals("shared prop", foo.getSharedProperty());
        assertEquals("bar prop", bar.getBarProperty());
        assertEquals("foo prop", foo.getFooProperty());
    }

    @Test
    public void testSuper(@Autowired List<Base> props) {
        assertEquals(2, props.size());
    }
}

性質上の条件付きポリモーフィックConfigurationProperties豆

あなたはそれらの特定のプロパティが欠落している場合は、特定の具体的な実装をインスタンス化することはしたくないかもしれません。さらに、あなたは夫婦たくないかもしれない@ConfigurationProperties@Component注釈各具象クラスに。この実装は、Springを経由してConfigurationProperties豆を構築@Configuration豆。コンフィグレーションBeanは、それらが唯一のプロパティの存在チェックを経て、条件付きで構築されている保証します。この実装はまた、コンクリートタイプのBeanを作成しBase、他のいずれも場合Base豆が条件を満たしていないと共有特性が存在します。前の例と同じユニットテストは、ここで使用され、通過します。

Base.java

package sample;

public class Base {
    private String sharedProperty;

    public String getSharedProperty() {
        return sharedProperty;
    }

    public void setSharedProperty(String sharedProperty) {
        this.sharedProperty = sharedProperty;
    }
}

Foo.java

package sample;

public class Foo extends Base {
    private String fooProperty;

    public String getFooProperty() {
        return fooProperty;
    }

    public void setFooProperty(String fooProperty) {
        this.fooProperty = fooProperty;
    }
}

Bar.java

package sample;

public class Bar extends Base {
    private String barProperty;

    public String getBarProperty() {
        return barProperty;
    }

    public void setBarProperty(String barProperty) {
        this.barProperty = barProperty;
    }
}

SampleConfiguration.java

package sample;

import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SampleConfiguration {

    @Bean
    @ConfigurationProperties("playground")
    @ConditionalOnProperty("playground.foo-property")
    public Foo foo() {
        return new Foo();
    }

    @Bean
    @ConfigurationProperties("playground")
    @ConditionalOnProperty("playground.bar-property")
    public Bar bar() {
        return new Bar();
    }

    @Bean
    @ConfigurationProperties("playground")
    @ConditionalOnProperty("playground.shared-property")
    @ConditionalOnMissingBean(Base.class)
    public Base base() {
        return new Base();
    }
}

application.yml

playground:
  shared-property: "shared prop"
  foo-property: "foo prop"
  bar-property: "bar prop"

SampleAppTest.java

package sample;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.env.Environment;

import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;

@SpringBootTest
public class SampleAppTest {

    @Autowired
    public Environment environment;

    @Test
    public void test(@Autowired Bar bar, @Autowired Foo foo) {
        assertEquals("shared prop", bar.getSharedProperty());
        assertEquals("shared prop", foo.getSharedProperty());
        assertEquals("bar prop", bar.getBarProperty());
        assertEquals("foo prop", foo.getFooProperty());
    }

    @Test
    public void testSuper(@Autowired List<Base> props) {
        assertEquals(2, props.size());
    }
}

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=176299&siteId=1