Spring Bootでカスタム自動設定を作成する
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
。