Skip to content
Published on

Spring Boot 設定ファイル構造とフォルダ構造完全ガイド:application.ymlマスター

Authors

目次

  1. プロジェクト標準フォルダ構造
  2. レイヤードアーキテクチャvsドメイン中心構造
  3. application.yml階層構造
  4. 外部設定の優先順位
  5. @ConfigurationPropertiesの活用
  6. マルチモジュールプロジェクト構造
  7. Kubernetes ConfigMap/Secret連携
  8. クイズ

1. プロジェクト標準フォルダ構造

Spring BootプロジェクトはMaven/Gradleの標準ディレクトリレイアウトに従います。一貫した構造はチームの協調作業と保守性を大幅に向上させます。

my-project/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/example/app/
│   │   │       ├── AppApplication.java
│   │   │       ├── config/
│   │   │       │   ├── SecurityConfig.java
│   │   │       │   ├── WebMvcConfig.java
│   │   │       │   └── SwaggerConfig.java
│   │   │       ├── controller/
│   │   │       │   ├── UserController.java
│   │   │       │   └── ProductController.java
│   │   │       ├── service/
│   │   │       │   ├── UserService.java
│   │   │       │   └── UserServiceImpl.java
│   │   │       ├── repository/
│   │   │       │   └── UserRepository.java
│   │   │       ├── domain/
│   │   │       │   ├── User.java
│   │   │       │   └── dto/
│   │   │       │       ├── UserRequest.java
│   │   │       │       └── UserResponse.java
│   │   │       ├── exception/
│   │   │       │   ├── GlobalExceptionHandler.java
│   │   │       │   └── BusinessException.java
│   │   │       ├── security/
│   │   │       │   ├── JwtTokenProvider.java
│   │   │       │   └── JwtAuthFilter.java
│   │   │       └── util/
│   │   │           └── DateUtils.java
│   │   └── resources/
│   │       ├── application.yml
│   │       ├── application-dev.yml
│   │       ├── application-staging.yml
│   │       ├── application-prod.yml
│   │       ├── db/
│   │       │   └── migration/
│   │       │       ├── V1__create_users.sql
│   │       │       └── V2__add_user_index.sql
│   │       ├── static/
│   │       │   ├── css/
│   │       │   └── js/
│   │       └── templates/
│   │           └── email/
│   │               └── welcome.html
└── test/
    ├── java/
    │   └── com/example/app/
    └── resources/
        ├── application-test.yml
        └── data.sql

パッケージ別の役割

パッケージ役割含まれるクラス
configSpring設定クラス群SecurityConfig, WebMvcConfig
controllerHTTPリクエスト処理(プレゼンテーション層)@RestControllerクラス
serviceビジネスロジック(ビジネス層)@Serviceクラス
repositoryデータアクセス(データ層)@Repository, JpaRepository
domainドメインモデル@Entity, DTO, VO
exception例外処理@ControllerAdvice, カスタム例外
securityセキュリティコンポーネントFilter, Provider, Handler
util共通ユーティリティ静的ヘルパーメソッド

2. レイヤードアーキテクチャvsドメイン中心構造

従来のレイヤード構造(機能別パッケージ)

com/example/app/
├── controller/
│   ├── UserController.java
│   ├── OrderController.java
│   └── ProductController.java
├── service/
│   ├── UserService.java
│   ├── OrderService.java
│   └── ProductService.java
└── repository/
    ├── UserRepository.java
    ├── OrderRepository.java
    └── ProductRepository.java

メリット:レイヤー別にファイルを見つけやすい デメリット:ドメイン単位の変更時に複数のパッケージを同時に修正する必要がある

ドメイン中心構造(ドメイン別パッケージ)

com/example/app/
├── user/
│   ├── UserController.java
│   ├── UserService.java
│   ├── UserRepository.java
│   ├── User.java
│   └── UserDto.java
├── order/
│   ├── OrderController.java
│   ├── OrderService.java
│   └── Order.java
└── product/
    ├── ProductController.java
    └── Product.java

メリット:ドメイン別の凝集度が高く、独立デプロイに有利 デメリット:同一レイヤーのファイルを一度に確認しにくい

ヘキサゴナルアーキテクチャのフォルダ構造

com/example/app/
└── user/
    ├── application/
    │   ├── port/
    │   │   ├── in/
    │   │   │   └── CreateUserUseCase.java
    │   │   └── out/
    │   │       └── UserRepository.java
    │   └── service/
    │       └── CreateUserService.java
    ├── domain/
    │   └── User.java
    └── adapter/
        ├── in/
        │   └── web/
        │       └── UserController.java
        └── out/
            └── persistence/
                └── UserJpaRepository.java

ヘキサゴナルアーキテクチャは外部依存(DB、メッセージブローカーなど)をインターフェースで隔離し、テスト容易性と交換可能性を高めます。


3. application.yml階層構造

基本構造とProfile分離

Spring Boot 2.4以降、単一ファイル内で---区切りを使用して複数のプロファイルを定義できます。

# application.yml - 共通設定
spring:
  application:
    name: my-service
  jackson:
    default-property-inclusion: non_null
    time-zone: Asia/Tokyo

logging:
  level:
    root: INFO
    com.example: DEBUG

management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics

---
# devプロファイル
spring:
  config:
    activate:
      on-profile: dev
  datasource:
    url: jdbc:postgresql://localhost:5432/devdb
    username: devuser
    password: devpass
  jpa:
    hibernate:
      ddl-auto: create-drop
    show-sql: true

logging:
  level:
    org.hibernate.SQL: DEBUG

---
# stagingプロファイル
spring:
  config:
    activate:
      on-profile: staging
  datasource:
    url: jdbc:postgresql://staging-db:5432/stagingdb
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}
  jpa:
    hibernate:
      ddl-auto: validate

---
# prodプロファイル
spring:
  config:
    activate:
      on-profile: prod
  datasource:
    url: jdbc:postgresql://prod-db:5432/proddb
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}
  jpa:
    hibernate:
      ddl-auto: validate
    show-sql: false

logging:
  level:
    root: WARN
    com.example: INFO

別ファイルへのProfile分離(大規模プロジェクト向け推奨)

resources/
├── application.yml          # 共通設定
├── application-dev.yml      # 開発環境
├── application-staging.yml  # ステージング環境
└── application-prod.yml     # 本番環境

プロファイルの有効化方法:

# コマンドラインで有効化
java -jar app.jar --spring.profiles.active=prod

# 環境変数で有効化
export SPRING_PROFILES_ACTIVE=prod

4. 外部設定の優先順位

Spring Bootは多くのソースから設定を読み込みます。優先順位が高いものが低いものを上書きします。

優先順位(高いものが低いものを上書き)

  1. コマンドライン引数(--server.port=9090
  2. SPRING_APPLICATION_JSON環境変数(インラインJSON)
  3. ServletConfig初期化パラメーター
  4. ServletContext初期化パラメーター
  5. JNDI属性(java:comp/env/
  6. Javaシステムプロパティ(System.getProperties()
  7. OS環境変数
  8. ランダム値プロパティソース(random.*
  9. プロファイル別外部アプリケーションファイル(JAR外部のapplication-dev.yml
  10. 外部アプリケーションファイル(JAR外部のapplication.yml
  11. プロファイル別内部アプリケーションファイル(JAR内部のapplication-dev.yml
  12. 内部アプリケーションファイル(JAR内部のapplication.yml
  13. @PropertySourceアノテーション
  14. デフォルト値(SpringApplication.setDefaultProperties

環境変数による設定のオーバーライド

# プロパティ名のドット(.)はアンダースコア(_)に変換し大文字にする
export SERVER_PORT=9090
export SPRING_DATASOURCE_URL=jdbc:postgresql://prod-db:5432/mydb
export SPRING_DATASOURCE_USERNAME=produser

コマンドライン引数の例

java -jar app.jar \
  --server.port=9090 \
  --spring.profiles.active=prod \
  --spring.datasource.url=jdbc:postgresql://prod-db:5432/mydb

5. @ConfigurationPropertiesの活用

@ConfigurationPropertiesを使うと、関連する設定を型安全なクラスにバインドして管理できます。

application.yml設定

app:
  api-key: my-secret-key
  timeout: 30s
  allowed-hosts:
    - api.example.com
    - admin.example.com
  retry:
    max-attempts: 3
    delay: 1s
  mail:
    host: smtp.example.com
    port: 587
    from: no-reply@example.com

@ConfigurationPropertiesクラス

@ConfigurationProperties(prefix = "app")
@Validated
@Getter
@Setter
public class AppProperties {

    @NotNull
    private String apiKey;

    private Duration timeout = Duration.ofSeconds(30);

    private List<String> allowedHosts = new ArrayList<>();

    private Retry retry = new Retry();

    private Mail mail = new Mail();

    @Getter
    @Setter
    public static class Retry {
        private int maxAttempts = 3;
        private Duration delay = Duration.ofSeconds(1);
    }

    @Getter
    @Setter
    public static class Mail {
        private String host;
        private int port = 587;
        private String from;
    }
}

Beanの登録

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

または、クラスに直接@Componentを追加:

@Component
@ConfigurationProperties(prefix = "app")
@Validated
public class AppProperties { ... }

IDEオートコンプリートのサポート(メタデータ生成)

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

この依存関係を追加するとコンパイル時にMETA-INF/spring-configuration-metadata.jsonが生成され、IDEでapplication.ymlのオートコンプリートが有効になります。


6. マルチモジュールプロジェクト構造

大規模プロジェクトでは、単一モジュールよりもマルチモジュール構造がコードの再利用と境界の分離に優れています。

Mavenマルチモジュール構造

my-project/                     # 親POM
├── pom.xml                     # 親POM
├── my-api/                     # REST APIモジュール
│   ├── pom.xml
│   └── src/main/java/
│       └── com/example/api/
├── my-domain/                  # ドメイン/ビジネスロジックモジュール
│   ├── pom.xml
│   └── src/main/java/
│       └── com/example/domain/
├── my-infrastructure/          # DB、外部API連携モジュール
│   ├── pom.xml
│   └── src/main/java/
│       └── com/example/infra/
└── my-common/                  # 共通ユーティリティモジュール
    ├── pom.xml
    └── src/main/java/
        └── com/example/common/

親pom.xmlの例

<project>
    <groupId>com.example</groupId>
    <artifactId>my-project</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>

    <modules>
        <module>my-common</module>
        <module>my-domain</module>
        <module>my-infrastructure</module>
        <module>my-api</module>
    </modules>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.0</version>
    </parent>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.example</groupId>
                <artifactId>my-common</artifactId>
                <version>${project.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

モジュール間の依存関係管理

my-api → my-domain → my-common
my-api → my-infrastructure → my-domain

循環依存が発生するとコンパイルエラーになります。共通インターフェースを独立したモジュールに抽出して循環を防ぎます。


7. Kubernetes ConfigMap/Secret連携

ConfigMapによる設定注入(環境変数方式)

# kubernetes/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-app-config
data:
  SPRING_PROFILES_ACTIVE: 'prod'
  SERVER_PORT: '8080'
  SPRING_DATASOURCE_URL: 'jdbc:postgresql://db-service:5432/mydb'
# kubernetes/deployment.yaml
spec:
  containers:
    - name: my-app
      envFrom:
        - configMapRef:
            name: my-app-config
        - secretRef:
            name: my-app-secret

Secretによる機密情報の注入

# Secretの作成
kubectl create secret generic my-app-secret \
  --from-literal=SPRING_DATASOURCE_USERNAME=produser \
  --from-literal=SPRING_DATASOURCE_PASSWORD=secretpass \
  --from-literal=JWT_SECRET=myJwtSecretKey

ボリュームマウント方式(ファイルで注入)

ConfigMapをファイルとしてマウントすると、application.yml全体を外部で管理できます。

# kubernetes/deployment.yaml
spec:
  volumes:
    - name: config-volume
      configMap:
        name: my-app-config-files
  containers:
    - name: my-app
      volumeMounts:
        - name: config-volume
          mountPath: /app/config
      env:
        - name: SPRING_CONFIG_LOCATION
          value: 'classpath:/,file:/app/config/'

spring-cloud-kubernetes連携

Spring Cloud Kubernetesを使用すると、ConfigMap変更時にアプリケーションを再起動することなく設定を動的にリロードできます。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-kubernetes-client-config</artifactId>
</dependency>
spring:
  cloud:
    kubernetes:
      config:
        enabled: true
        name: my-app-config
        namespace: default
      reload:
        enabled: true
        mode: event
        period: 15000

8. クイズ

Q1. Spring BootでJAR外部の設定がJAR内部の設定より優先順位が高い理由は?

答え: 本番環境でアプリケーションを再ビルドすることなく設定を変更できるようにするためです。

解説: Spring Bootの外部設定優先順位体系は12-Factor Appの原則に従っています。JAR外部のapplication.yml、環境変数、コマンドライン引数がJAR内部の設定より高い優先順位を持ちます。これにより、同じJARファイルを開発・ステージング・本番環境にそのままデプロイし、設定のみを環境ごとに異なる形で注入することができます。

Q2. @ConfigurationPropertiesと@Validatedを一緒に使う理由は?

答え: アプリケーション起動時に設定値の妥当性を検証し、無効な設定によるランタイムエラーを事前に防ぐためです。

解説: @ValidatedとJSR-303 Bean Validationアノテーション(@NotNull@Min@Maxなど)を組み合わせると、Spring Bootアプリケーションの起動時に設定値が有効かどうかを検証します。必須設定の欠如や値の範囲外の場合、即座にBindValidationExceptionが発生し、迅速なフィードバックを提供します。

Q3. マルチモジュールプロジェクトで循環依存を防ぐ方法は?

答え: 共通インターフェースや共有ドメインモデルを独立した共通モジュール(common/sharedモジュール)に分離し、依存関係の方向を単方向に保ちます。

解説: モジュールAがモジュールBに依存し、モジュールBがモジュールAに依存する循環依存が発生するとコンパイルが不可能になります。両モジュールが共通して必要なインターフェースやDTOを別のcommonモジュールに分離すると、AとBが共にcommonに依存する単方向の構造を作ることができます。

Q4. Kubernetesでアプリケーション設定を再デプロイなしに動的にリロードする方法は?

答え: spring-cloud-starter-kubernetes-client-configを使用し、spring.cloud.kubernetes.reload.enabled=trueに設定します。

解説: Spring Cloud Kubernetesは2つのリロードモードを提供します。eventモードはKubernetes APIイベントを検知してConfigMapの変更に即座に反応し、pollingモードは定期的にConfigMapを確認します。@RefreshScopeアノテーションが付いたBeanはConfigMap変更時に自動的に再初期化されます。

Q5. application.ymlでspring.config.activate.on-profileの役割は?

答え: 特定のプロファイルが有効な場合にのみ、その設定ブロックが適用されるよう指定します。

解説: Spring Boot 2.4から、単一のapplication.ymlファイルで---区切りを使って複数のドキュメントブロックに分割できます。各ブロックにspring.config.activate.on-profileを指定すると、指定したプロファイルが有効な場合にのみそのブロックの設定が適用されます。以前のspring.profiles構文は非推奨であり、spring.config.activate.on-profileの使用が推奨されます。