ApplicationModules
이 포함되어 있다.var modules = ApplicationModules.of(Application::class)
modules
에는 코드베이스에서 파생된 애플리케이션 모듈의 배열의 인메모리 표현이 들어있다.modules
를 순회하며 출력하면 아래처럼 구조를 볼 수 있다.## example.inventory ##
> Logical name: inventory
> Base package: example.inventory
> Spring beans:
+ ….InventoryManagement
o ….SomeInternalComponent
## example.order ##
> Logical name: order
> Base package: example.order
> Spring beans:
+ ….OrderManagement
+ ….internal.SomeInternalComponent
ApplicationModules.of(
Application::class,
JavaClass.Predicates.resideInAPackage("com.example.db")
).verify()
main package
는 메인 애플리케이션 클래스가 상주하는 곳이다.
@SpringBootApplication
어노테이션이 존재하는 클래스가 있는 곳main package
바로 밑의 sub-package
는 application module package
로 간주된다.
sub-package
하위에 속하지 않으면 단순 패키지로 간주되며 의존성 주입 대상이 아니게 된다.application module package
에 하위 패키지에 위치하는 타입은 다른 모듈에서 참조하려면 public
일 필요가 있다. Example
└─ src/main/java
├─ example
| └─ Application.java
├─ example.inventory
| ├─ InventoryManagement.java
| └─ SomethingInventoryInternal.java
├─ example.order
| └─ OrderManagement.java
└─ example.order.internal
└─ SomethingOrderInternal.java
order
패키지는 API 패키지로, 다른 모듈에서 참조할 수 있도록 내부 타입은 public
일 것이다.order.internal
패키지는 하위 패키지인 점은 같지만 다른 모듈에서 참조해선 안 된다.
OrderManagement
가 SomethingOrderInternal
을 의존한다면 SomethingOrderInternal
은 public
이어야 하고 Java 컴파일러는 다른 모듈이 order.internal
내부를 참조하는 것을 막아주지 못한다.@ApplicaitonModule
어노테이션을 package-info.java
타입에 선언하면 된다.@org.springframework.modulith.ApplicationModule(
type = Type.OPEN
)
package example.inventory
@ApplicationModule
애노테이션을 사용하여 허용되는 종속성을 선언하도록 선택할 수 있다.package example.inventory
@ApplicationModule(allowedDependencies = "order")
class ModuleMetadata {}
inventory
모듈 내 코드는 order
모듈의 코드만 참조할 수 있다.@NamedInterface
애노테이션을 package-info.java 파일에 선언@PackageInfo
애노테이션을 타입에 명시적으로 선언 Example
└─ src/main/java
├─ example
| └─ Application.java
├─ …
├─ example.order
| └─ OrderManagement.java
├─ example.order.spi
| ├— package-info.java
| └─ SomeSpiInterface.java
└─ example.order.internal
└─ SomethingOrderInternal.java
// example.order.spi 내부의 package-info.java 파일
package example.order.spi
import org.springframework.modulith.PackageInfo
import org.springframework.modulith.NamedInterface
@PackageInfo
@NamedInterface("spi")
class ModuleMetadata {}
SomeSpiInterface
를 참조 가능inventory
모듈에서 이를 사용해야 한다면 위에서 선언한 named interface를 아래와 같이 참조할 수 있다.@org.springframework.modulith.ApplicationModule(
allowedDependencies = "order :: spi"
)
package example.inventory
spi
를 ::
을 통해 연결하는 것에 유의하라
inventory
모듈은 SomeSpiInterface
및 order.spi
하위에 있는 코드를 의존할 수 있다.order
코드는 반대로 inventory
를 의존할 수 없다.@ApplicationModule
또는 jMolecules @Module
애노테이션을 통해 명시적으로 애노테이션이 있는 패키지만 고려하도록 활성화할 수 있다.spring.modulith.detection-strategy=explicitly-annotated
ApplicationModuleDetectionStrategy
의 구현체를 제공하여 모듈 탐지 전략을 커스텀할 수도 있다.spring.modulith.detection-strategy=example.CustomApplicationModuleDetectionStrategy
package example
class CustomApplicationModuleDetectionStrategy : ApplicationModuleDetectionStrategy {
override fun getModuleBasePackages(basePackage: JavaPackage): Stream<JavaPackage> {
// Your module detection goes here
}
}
@Modulithic
애노테이션이 있는 스프링부트 애플리케이션 클래스의 핵심 관심사를 구성할 수 있도록 스프링 모듈리스는 제공한다.package example
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.modulith.Modulithic
@Modulithic
@SpringBootApplication
class DemoApplication
fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
}