1概要

簡単に言うと、Spring Bootの自動設定は、クラスパスに存在する依存関係に基づいてSpringアプリケーションを自動的に設定する方法を表します。

これにより、自動構成クラスに含まれる特定のBeanを定義する必要がなくなるため、開発を迅速かつ容易に行うことができます。

次のセクションでは、

カスタムSpring Bootの自動設定の作成

を見ていきます。


2 Mavenの依存関係

必要な依存関係から始めましょう。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>2.0.1.RELEASE</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.11</version>
</dependency>


spring-boot-starter-data-jpa

の最新バージョンhttps://search.maven.org/classic/#search%7Cga%7C1%7Ca%3A%22mysql-connector-java%22%20AND%20g%3A%22mysql%22[mysql-connector-java]をダウンロードできますMaven Centralから。


3カスタム自動設定の作成

  • カスタムの自動設定を作成するには、

    @ Configuration

    というアノテーションを付けたクラスを作成して登録する必要があります。


MySQL

データソース用のカスタム設定を作成しましょう。

@Configuration
public class MySQLAutoconfiguration {
   //...
}

次の必須ステップは、標準ファイル

resources/META-INF/spring.factories

のキー

org.springframework.boot.autoconfigure.EnableAutoConfiguration

の下にクラスの名前を追加して、クラスを自動設定候補として登録することです。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.baeldung.autoconfiguration.MySQLAutoconfiguration

自動設定クラスを他の自動設定候補よりも優先させたい場合は、

@ AutoConfigureOrder(Ordered.HIGHEST

PRECEDENCE)__注釈を追加できます。

自動設定は、@ @ Conditional__アノテーションでマークされたクラスとBeanを使用して設計されているため、自動設定またはその特定の部分を置き換えることができます。

  • 自動設定は、自動設定Beanがアプリケーションで定義されていない場合にのみ有効です。 Beanを定義すると、デフォルトのものが上書きされます。


3.1. クラス条件

クラス条件により、

@ ConditionalOnClass

アノテーションを使用して

指定されたクラスが存在する場合、または

@ ConditionalOnMissingClass

アノテーションを使用して

クラスが存在しない場合に、構成Beanが含まれることを指定できます。


MySQLConfiguration

がクラス

DataSource

が存在する場合にのみロードされるように指定しましょう。

@Configuration
@ConditionalOnClass(DataSource.class)
public class MySQLAutoconfiguration {
   //...
}


3.2. 豆の状態

指定されたBeanが存在するかどうかにかかわらず** Beanをインクルードしたい場合は、

@ ConditionalOnBean

および

@ ConditionalOnMissingBean

アノテーションを使用できます。

これを例示するために、構成クラスに

entityManagerFactory

Beanを追加し、

dataSource

というBeanが存在し、

entityManagerFactory

というBeanがまだ定義されていない場合にのみこのBeanを作成するように指定します。

@Bean
@ConditionalOnBean(name = "dataSource")
@ConditionalOnMissingBean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    LocalContainerEntityManagerFactoryBean em
      = new LocalContainerEntityManagerFactoryBean();
    em.setDataSource(dataSource());
    em.setPackagesToScan("com.baeldung.autoconfiguration.example");
    em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
    if (additionalProperties() != null) {
        em.setJpaProperties(additionalProperties());
    }
    return em;
}


JpaTransactionManager

型のBeanがまだ定義されていない場合にのみロードされる

transactionManager

Beanも設定します。

@Bean
@ConditionalOnMissingBean(type = "JpaTransactionManager")
JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory);
    return transactionManager;
}


3.3. 物件条件


@ ConditionalOnProperty

アノテーションは、Spring Environmentプロパティの存在と値に基づいて設定をロードするかどうかを指定するために使用されます。

まず、私たちの設定用のプロパティソースファイルを追加しましょう。それはプロパティがどこから読み込まれるかを決定します:

@PropertySource("classpath:mysql.properties")
public class MySQLAutoconfiguration {
   //...
}


usemysql

というプロパティが存在する場合にのみロードされるように、データベースへの接続を作成するために使用されるメインの

DataSource

Beanを設定できます。

属性

havingValue

を使用して、一致する必要がある

usemysql

プロパティの特定の値を指定できます。


usemysql

プロパティが

local

に設定されている場合は、

myDb

というローカルデータベースに接続するデフォルト値で

dataSource

Beanを定義しましょう。

@Bean
@ConditionalOnProperty(
  name = "usemysql",
  havingValue = "local")
@ConditionalOnMissingBean
public DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();

    dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
    dataSource.setUrl("jdbc:mysql://localhost:3306/myDb?createDatabaseIfNotExist=true");
    dataSource.setUsername("mysqluser");
    dataSource.setPassword("mysqlpass");

    return dataSource;
}


usemysql

プロパティが

customに設定されている場合、

dataSource__ BeanはデータベースURL、ユーザー、およびパスワードのカスタムプロパティ値を使用して設定されます。

@Bean(name = "dataSource")
@ConditionalOnProperty(
  name = "usemysql",
  havingValue = "custom")
@ConditionalOnMissingBean
public DataSource dataSource2() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();

    dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
    dataSource.setUrl(env.getProperty("mysql.url"));
    dataSource.setUsername(env.getProperty("mysql.user") != null
      ? env.getProperty("mysql.user") : "");
    dataSource.setPassword(env.getProperty("mysql.pass") != null
      ? env.getProperty("mysql.pass") : "");

    return dataSource;
}


mysql.properties

ファイルには、

usemysql

プロパティが含まれます。

usemysql=local


MySQLAutoconfiguration

を使用するアプリケーションがデフォルトのプロパティを上書きしたい場合は、

mysql.properties

ファイルの

mysql.url



mysql.user



mysql.pass

プロパティ、および

usemysql = custom

行に異なる値を追加するだけです。


3.4. リソース条件


@ ConditionalOnResource

アノテーションを追加することは、指定されたリソースが存在する場合にのみ設定が読み込まれることを意味します。

リソースファイル

mysql.properties

が存在する場合に限り、

entityManagerFactory

Beanによって使用されるHibernate固有のプロパティを含む

Properties

オブジェクトを返す

additionalProperties()

というメソッドを定義しましょう。

@ConditionalOnResource(
  resources = "classpath:mysql.properties")
@Conditional(HibernateCondition.class)
Properties additionalProperties() {
    Properties hibernateProperties = new Properties();

    hibernateProperties.setProperty("hibernate.hbm2ddl.auto",
      env.getProperty("mysql-hibernate.hbm2ddl.auto"));
    hibernateProperties.setProperty("hibernate.dialect",
      env.getProperty("mysql-hibernate.dialect"));
    hibernateProperties.setProperty("hibernate.show__sql",
      env.getProperty("mysql-hibernate.show__sql") != null
      ? env.getProperty("mysql-hibernate.show__sql") : "false");
    return hibernateProperties;
}

Hibernate固有のプロパティを

mysql.properties

ファイルに追加できます。

mysql-hibernate.dialect=org.hibernate.dialect.MySQLDialect
mysql-hibernate.show__sql=true
mysql-hibernate.hbm2ddl.auto=create-drop


3.5. カスタム条件

Spring Bootで利用可能な条件のいずれも使用したくない場合は、

SpringBootCondition

クラスを拡張して

getMatchOutcome()

メソッドをオーバーライドすることによって** カスタム条件を定義することもできます。


HibernateEntityManager

クラスがクラスパスに存在するかどうかを確認する

additionalProperties()

メソッド用に

HibernateCondition

という条件を作成しましょう。

static class HibernateCondition extends SpringBootCondition {

    private static String[]CLASS__NAMES
      = { "org.hibernate.ejb.HibernateEntityManager",
          "org.hibernate.jpa.HibernateEntityManager" };

    @Override
    public ConditionOutcome getMatchOutcome(ConditionContext context,
      AnnotatedTypeMetadata metadata) {

        ConditionMessage.Builder message
          = ConditionMessage.forCondition("Hibernate");
        return Arrays.stream(CLASS__NAMES)
          .filter(className -> ClassUtils.isPresent(className, context.getClassLoader()))
          .map(className -> ConditionOutcome
            .match(message.found("class")
            .items(Style.NORMAL, className)))
          .findAny()
          .orElseGet(() -> ConditionOutcome
            .noMatch(message.didNotFind("class", "classes")
            .items(Style.NORMAL, Arrays.asList(CLASS__NAMES))));
    }
}

その後、

additionalProperties()

メソッドに条件を追加します。

@Conditional(HibernateCondition.class)
Properties additionalProperties() {
 //...
}


3.6. 適用条件

また、

@ ConditionalOnWebApplication

または

@ ConditionalOnNotWebApplication

アノテーションを追加することで、設定をWebコンテキストの内側/外側でのみロードできるように指定することもできます。


4自動設定のテスト

自動設定をテストするための非常に簡単な例を作成しましょう。 Springデータを使用して

MyUser

というエンティティクラスと

MyUserRepository

インターフェイスを作成します。

@Entity
public class MyUser {
    @Id
    private String email;

   //standard constructor, getters, setters
}

public interface MyUserRepository
  extends JpaRepository<MyUser, String> { }

自動設定を有効にするには、

@ SpringBootApplication

または

@ EnableAutoConfiguration

アノテーションのいずれかを使用できます。

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

次に、

MyUser

エンティティを保存する

JUnit

テストを書きましょう。

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(
  classes = AutoconfigurationApplication.class)
@EnableJpaRepositories(
  basePackages = { "com.baeldung.autoconfiguration.example" })
public class AutoconfigurationTest {

    @Autowired
    private MyUserRepository userRepository;

    @Test
    public void whenSaveUser__thenOk() {
        MyUser user = new MyUser("[email protected]");
        userRepository.save(user);
    }
}


DataSource

設定を定義していないので、アプリケーションは

myDb

という

MySQL

データベースに接続するために作成した自動設定を使用します。

  • 接続文字列に

    createDatabaseIfNotExist = true

    プロパティが含まれているため、データベースが存在する必要はありません。ただし、ユーザー

    mysqluser

    、または存在する場合は

    mysql.user

    プロパティで指定されたユーザーを作成する必要があります。

アプリケーションログを調べて、

MySQL

データソースが使用されていることを確認できます。

web - 2017-04-12 00:01:33,956[main]INFO  o.s.j.d.DriverManagerDataSource - Loaded JDBC driver: com.mysql.cj.jdbc.Driver


5自動設定クラスを無効にする

自動設定をロードから除外する** 場合は、

exclude

または

excludeName

属性を持つ

@ EnableAutoConfiguration

アノテーションを設定クラスに追加できます。

@Configuration
@EnableAutoConfiguration(
  exclude={MySQLAutoconfiguration.class})
public class AutoconfigurationApplication {
   //...
}

特定の自動設定を無効にするもう1つの方法は、

spring.autoconfigure.exclude

プロパティを設定することです。

spring.autoconfigure.exclude=com.baeldung.autoconfiguration.MySQLAutoconfiguration


6. 結論

このチュートリアルでは、カスタムのSpring Boot自動設定を作成する方法を説明しました。例の完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/spring-boot-autoconfiguration[GitHubに載っています]。

JUnitテストは

autoconfiguration

プロファイルを使用して実行できます。

mvn clean install -Pautoconfiguration