本記事は、Spring Boot 2.7.3について書いてあります。
Spring Bootとは
Spring Bootはフレームワークでなく、Spring Frameworkを利用してアプリケーションを作りやすくしている仕組みのこと。 Spring Boot単体では何も作ることはできないので、Spring WebやSpring Dataなどのフレームワークを利用する。(Spring BootではStarterを利用することがほとんど)
Spring Bootと非Spring Bootの大きな違いは、Starterという依存関係便利パックが提供されている&デフォルトの設定(必要そうなクラスのBean登録)がされていること。
Starters
アプリケーションを作るときにあったら必要であろう依存関係を含んだ便利パック。例えば、SpringとJPAを利用してアプリケーションを作りたいとなったら、spring-boot-starter-data-jpa
を依存関係に追加すればよい。
Starterを利用すると後述するauto-configurationの仕組みが提供されており、単にライブラリを依存関係に追加するよりも設定項目が減り、楽にアプリケーション開発が行える。
※ 公式のスターターはspring-boot-starter-*
という名前になっており多くのIDEでそれに適した設定が入っているため、サードパーティのスターターは頭にspring-boot
という名前をつけてはいけない。
Starterの例
- Spring Boot application starters
- Spring Bootでアプリケーションを作るために利用
spring-boot-starter-data-jpa
、spring-boot-starter-web
など
- Spring Boot production starters
- production readyな機能を提供する
spring-boot-starter-actuator
- Spring Boot technical starters
- デフォルトで利用されているライブラリ等を置き換えたり除外したりするときに利用
spring-boot-starter-logging
やspring-boot-starter-tomcat
など
コーディング
Spring Bootアプリケーションにおけるエントリーポイントは@SpringBootApplication
で、これをメインクラスに付与する。
なお、@SpringBootApplication
はパッケージ最上位に置くのがよい。
一般的なメインクラス。
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
設定クラス
Spring Bootの設定にはJavaベースの設定を推奨している。XMLを利用することもできる。
Auto-configuration
Spring Boot auto-configurationは、プロジェクトに追加されている依存関係に基づいて、Spring アプリケーションに自動的に設定を行う仕組みのことである。
@EnableAutoConfiguration
または@SpringBootApplication
を付与すると、auto-configurationを有効にすることができる。
デフォルトで全AutoConfigurationが適用されるが、以下のように書くとauto-configurationから除外することができる。
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) public class Application { }
@SpringBootApplicationについて
@SpringBootApplication
は、@SpringBootConfiguration
、@EnableAutoConfiguration
、@ComponentScan
を含み持つアノーテーションでこれらと同じ機能を提供する。ちなみに、複数の機能を持つアノテーションのことを複合アノテーションと呼ぶ。
@EnableAutoConfiguration
- 先に説明したauto-configurationを有効にする
@ComponentScan
- これが付与されたクラスの配下にあるクラスの
@Component
系のアノテーション(@RestController
、@Service
など)が付与されているクラスをBean登録する。 - これはSpring Bootのアノテーションでなく、Spring Frameworkのアノテーション
- これが付与されたクラスの配下にあるクラスの
@SpringBootConfiguration
- このクラス自身をBean登録する。
@Configuration
とほぼ同じ機能ではあるが、インテグレーションテストを書く際に役立つ。
Auto configuration
AutoConfigurationのクラスに@AutoConfiguration
を付与するとBean登録される。
auto-configurationを適用させるクラスはMETA-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
(Spring Boot 2.7より前はMETA-INF/spring.factoriesだった)に列挙されている。
AutoConfigurationImportSelector#getCandidateConfigurationsを参照。
Condition Annotations
auto-configurationクラスに書いてある@Conditonal
に従ってBean登録が行われる。
@Conditional
の仲間には次のものがある。
Class Condition
クラスパスに指定したクラスがあるかないか。@ConditionalOnClass
、@ConditionalOnMissingClass
。
JacksonAutoConfiguration.javaだと、ObjectMapper.javaがクラスパスに存在したらauto-configurationが適用される。
@AutoConfiguration @ConditionalOnClass(ObjectMapper.class) public class JacksonAutoConfiguration {
Bean Conditions
指定したBeanがあるかないか。@ConditionalOnBean
、@ConditionalOnMissingBean
。
RestTemplateAutoConfiguration#restTemplateBuilderConfigurerだと、RestTemplateBuilderConfigurerがBean登録されてなかったらこのメソッドでRestTemplateBuilderConfigurerのBean登録が行われる。
@Bean @Lazy @ConditionalOnMissingBean public RestTemplateBuilderConfigurer restTemplateBuilderConfigurer(
Property Conditions
application.ymlや起動オプションなどで指定するSpring 環境プロパティによってBean登録が行われる。
JacksonHttpMessageConvertersConfiguration.MappingJackson2HttpMessageConverterConfiguration.javaだと、spring.mvc.converters.preferred-json-mapper=jackson
のときBean登録が行われる
@Configuration(proxyBeanMethods = false) @ConditionalOnClass(ObjectMapper.class) @ConditionalOnBean(ObjectMapper.class) @ConditionalOnProperty(name = HttpMessageConvertersAutoConfiguration.PREFERRED_MAPPER_PROPERTY, havingValue = "jackson", matchIfMissing = true) static class MappingJackson2HttpMessageConverterConfiguration {
Resource Conditions
指定したリソースが存在したらBean登録する。@ConditionalOnResource
。
このようにresourcesにパスを指定する。(ProjectInfoAutoConfiguration#buildProperties)
@ConditionalOnResource(resources = "${spring.info.build.location:classpath:META-INF/build-info.properties}")
Web Application Conditions
Webアプリケーションかどうか。@ConditonalOnWebApplication
、@ConditionalOnNotWebAplication
。
その他、クラウドプラットフォームかどうかで判定する@ConditionalOnCloudPlatform
などもある。CloudPlatform.javaに定義されている、CloudFoundry、Heroku、SAP、Kubernetes、Azure App Serviceが対象。
SpEL Expression Conditions
@ConditionalOnExpression
はSpEL(SPring Expression Language)で書かれたプロパティに応じてBean登録する。
Spring Boot が起動するまでにやっていること
@EnableAutoConfiguraion(@SpringBootApplication)
が行っていることから、Spring Bootの特徴であるAutoConfigureの仕組みを説明する。
1. DIコンテナ(ApplicationContext)の作成
ApplicationContextは、BeanFactoryを継承したアプリケーションの設定を提供する主要なインターフェース。メイン機能の1つにDIコンテナがある。
2. spring.factories、AutoConfiguration.imports読込
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
にauto-configureするクラス(@AutoConfigure
をつけたクラス)を列挙する。
以前はspring.factoriesに書いていたが、このファイルはauto-configureを利用するために必要なクラスを書くようになった(ぽい)
これらに書かれたクラスを読み込む。
3. Bean登録するAutoConfigurationクラスをソート
定義された順序で、Bean登録するAutoConfigurationクラスをソートする。AutoConfigurationSorter#getInPriorityOrder
で行う。
- アルファベット順
@Order
の順@AutoConfigureBefore
と@AutoConfigureAfter
の順@AutoConfigureBefore
は指定したクラスの前@AutoConfigureAfter
は指定したクラスの後
4. Bean登録
ConfigurationClassParser#processGroupImportsでDIコンテナにBean登録を行う
application.properties(yml)について
application.propterties(yml)は、設定値を書くファイル。 Spring Bootが提供している設定値の一覧はここに書いてある。
このファイルに書いても確実に設定されるわけではなく、@ConfigurationProperties
が付与されたクラスに値がバインドされるだけである。
設定が行われる条件は、次の2つが満たされていることです。
- バインドされる@ConfigurationPropertiesのクラスがBean登録されていること
- そのAutoConfigurationが有効となっていこと
大抵、@AutoConfiguration
を付与したクラスに@EnableConfigurationProperties
も付与されている。つまり、AutoConfigurationが有効になっていればapplication.properties(yml)に書いた設定は適用される。
これはDataSourceAutoConfiguration.javaの例である。
@AutoConfiguration(before = SqlInitializationAutoConfiguration.class) @ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class }) @ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory") @EnableConfigurationProperties(DataSourceProperties.class) @Import(DataSourcePoolMetadataProvidersConfiguration.class) public class DataSourceAutoConfiguration {
Banner
Bannerとは、Spring Bootを起動すると見るこれのことで地味に変更がされ続けている。
歴史
バージョン | 内容 |
---|---|
1.0.x | Bannerを表示するかどうかの設定のみ |
1.1.x | Text Bannerを表示できるようになる |
1.2.x | Banner変数が登場 |
1.3.x | Text Bannerが色付け可能に |
1.4.x | Image Bannerを表示可能に |
2.0.x | アニメーションgifをサポート |
2.2.x | ASCII バナーは256色利用可能に |
カスタマイズ
バナーのカスタマイズ方法は3通りで、デフォルトバナーは3で実現しているおり、SpringBootBanner.javaが実装。
- resources/banner.[ gif | jpg | png ]を置く
- resources/banner.txtを置く
- org.springframework.boot.Bannerインターフェースを実装する
優先順位
SpringApplicationBannerPrinter#getBannerで表示すバナーを決定している。
- Image BannerとText Bannerを探す
- 1がなかったら自作のBannerクラス
- 1も2もなかったらDefault Banner
Image Banner と Text Bannerは一緒に表示可能。
Bannerインターフェース実装してみた
public class StoresBanner implements Banner { private static final String[] BANNER = { " ______ _________ ___ _______ ________ ______ \\n" + ".' ____ \\\\ | _ _ | .' `. |_ __ \\\\ |_ __ | .' ____ \\\\ \\n" + "| (___ \\\\_| |_/ | | \\\\_| / .-. \\\\ | |__) | | |_ \\\\_| | (___ \\\\_| \\n" + " _.____`. | | | | | | | __ / | _| _ _.____`. \\n" + "| \\\\____) | _| |_ \\\\ `-' / _| | \\\\ \\\\_ _| |__/ | | \\\\____) | \\n" + " \\\\______.' |_____| `.___.' |____| |___| |________| \\\\______.' \\n" }; @Override public void printBanner(Environment environment, Class<?> sourceClass, PrintStream printStream) { for (String line : BANNER) { printStream.println(line); } } }
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication app = new SpringApplication(Application11.class); app.setBanner(new StoresBanner()); app.run(args); } }
※ バナーが好きだと思われる人が作ったOnline Spring Boot Banner Generatorというサイトがある。