Auto-configuration
CoApi provides comprehensive Spring Boot auto-configuration that simplifies the setup process while maintaining flexibility for custom configurations. The framework supports two distinct activation paths to accommodate different use cases and development preferences.
Overview
CoApi's auto-configuration system is designed to automatically detect and configure CoApi clients based on classpath scanning and explicit configuration. The system leverages Spring Boot's conditional configuration mechanism to ensure that CoApi components are only registered when needed, providing a seamless integration experience.
The auto-configuration is built around a modular architecture that combines automatic scanning with manual configuration options, allowing developers to choose the approach that best fits their application architecture.
At-a-Glance
| Feature | Auto Configuration | Manual Configuration |
|---|---|---|
| Activation | Spring Boot auto-configuration | @EnableCoApi annotation |
| Scanning | Automatic classpath scanning | Explicit client specification |
| Base Packages | @SpringBootApplication + coapi.base-packages | Annotation attributes |
| Flexibility | High (combines scanning + registered beans) | Medium (explicit control) |
| Setup Complexity | Low (zero configuration) | Low (minimal annotation setup) |
Activation Paths
Auto (Spring Boot) Configuration Path
sequenceDiagram
participant SB as Spring Boot
participant AC as CoApiAutoConfiguration
participant CO as ConditionalOnCoApiEnabled
participant ACR as AutoCoApiRegistrar
participant ABS as AbstractCoApiRegistrar
participant CR as CoApiRegistrar
SB->>AC: AutoConfiguration
AC->>CO: ConditionalOnCoApiEnabled
CO->>AC: Check coapi.enabled=true (default)
AC->>AC: Import AutoCoApiRegistrar
AC->>AC: EnableConfigurationProperties
AC->>AC: return
SB->>AC: Instantiate CoApiAutoConfiguration
AC->>AC: Import AutoCoApiRegistrar
AC->>ABR: getCoApiDefinitions()
ABR->>ACR: AbstractCoApiRegistrar.registerBeanDefinitions()
ACR->>ACR: inferClientMode()
ACR->>ABR: registerHttpExchangeAdapterFactory()
ABR->>ACR: register()
AC->>SB: return AutoCoApiRegistrar
SB->>CR: CoApiRegistrar.register(apiDefinitions)
CR->>CR: Register CoApiDefinition beans
SB->>SB: Complete auto-configurationManual Configuration Path
sequenceDiagram
participant DC as Developer Configuration
participant EC as EnableCoApi
participant ECR as EnableCoApiRegistrar
participant ABS as AbstractCoApiRegistrar
participant CR as CoApiRegistrar
DC->>DC: @EnableCoApi(clents=[...])
DC->>EC: Annotate with explicit clients
EC->>ECR: @Import(EnableCoApiRegistrar)
EC->>ECR: Import EnableCoApiRegistrar
DC->>DC: return
EC->>ECR: getCoApiDefinitions()
ECR->>ECR: Extract clients from @EnableCoApi
ECR->>ECR: Map to CoApiDefinition via toCoApiDefinition()
ECR->>ABR: AbstractCoApiRegistrar.registerBeanDefinitions()
ABR->>ECR: inferClientMode()
ABR->>ECR: registerHttpExchangeAdapterFactory()
ECR->>ABR: register()
EC->>CR: CoApiRegistrar.register(apiDefinitions)
CR->>CR: Register CoApiDefinition beansAuto-Configuration Components
CoApiAutoConfiguration
The main auto-configuration class that orchestrates the entire setup process:
@AutoConfiguration
@ConditionalOnCoApiEnabled
@Import(AutoCoApiRegistrar::class)
@EnableConfigurationProperties(CoApiProperties::class)
class CoApiAutoConfigurationThis class serves as the entry point for automatic configuration and delegates the actual registration to specialized components.
spring-boot-starter/src/main/kotlin/me/ahoo/coapi/spring/boot/starter/CoApiAutoConfiguration.kt:20
ConditionalOnCoApiEnabled
Controls whether CoApi auto-configuration should be enabled:
@ConditionalOnProperty(
value = [ConditionalOnCoApiEnabled.ENABLED_KEY],
matchIfMissing = true,
havingValue = "true",
)
annotation class ConditionalOnCoApiEnabled {
companion object {
const val ENABLED_KEY: String = COAPI_PREFIX + ENABLED_SUFFIX_KEY
}
}The configuration is enabled by default and can be disabled by setting coapi.enabled=false in application properties.
AutoCoApiRegistrar
Handles automatic scanning and registration of CoApi clients:
graph TD
A["AutoCoApiRegistrar"] --> B["getCoApiDefinitions()"]
A --> C["getScanBasePackages()"]
B --> D["Scanned Definitions"]
B --> E["Registered CoApiDefinition Beans"]
C --> F["AutoConfigurationPackages.get()"]
C --> G["coapi.base-packages Property"]
D --> H["ApiClientScanner"]
H --> I["ClassPathScanningCandidateComponentProvider"]
I --> J["AnnotationTypeFilter(CoApi.class)"]
I --> K["Interface Only Filter"]The registrar combines automatically scanned interface definitions with any explicitly registered CoApiDefinition beans.
private fun getScanBasePackages(): Set<String> {
val coApiBasePackages = getCoApiBasePackages()
if (AutoConfigurationPackages.has(appContext).not()) {
return coApiBasePackages
}
return AutoConfigurationPackages.get(appContext).toSet() + coApiBasePackages
}spring-boot-starter/src/main/kotlin/me/ahoo/coapi/spring/boot/starter/AutoCoApiRegistrar.kt:48
EnableCoApiRegistrar
Handles manual configuration through the @EnableCoApi annotation:
@Suppress("UNCHECKED_CAST")
override fun getCoApiDefinitions(importingClassMetadata: AnnotationMetadata): Set<CoApiDefinition> {
val enableCoApi =
importingClassMetadata.getAnnotationAttributes(EnableCoApi::class.java.name) ?: return emptySet()
val clients = enableCoApi[EnableCoApi::clients.name] as Array<Class<*>>
return clients.map { clientType ->
clientType.toCoApiDefinition(env)
}.toSet()
}spring/src/main/kotlin/me/ahoo/coapi/spring/EnableCoApiRegistrar.kt:22
AbstractCoApiRegistrar
Provides the template method pattern for bean registration:
sequenceDiagram
participant ACR as AbstractCoApiRegistrar
participant CM as inferClientMode
participant RH as registerHttpExchangeAdapterFactory
participant CR as CoApiRegistrar
ACR->>ACR: registerBeanDefinitions()
ACR->>CM: inferClientMode()
CM->>ACR: return ClientMode
ACR->>RH: registerHttpExchangeAdapterFactory(clientMode, registry)
RH->>RH: Register SyncHttpExchangeAdapterFactory or ReactiveHttpExchangeAdapterFactory
ACR->>ACR: getCoApiDefinitions(importingClassMetadata)
ACR->>CR: CoApiRegistrar(registry, clientMode)
ACR->>CR: register(apiDefinitions)
CR->>CR: Register CoApiDefinition beansThe abstract class implements the Spring ImportBeanDefinitionRegistrar interface and provides a structured approach to bean registration.
override fun registerBeanDefinitions(importingClassMetadata: AnnotationMetadata, registry: BeanDefinitionRegistry) {
val clientMode = inferClientMode {
env.getProperty(it)
}
registerHttpExchangeAdapterFactory(clientMode, registry)
val coApiRegistrar = CoApiRegistrar(registry, clientMode)
val apiDefinitions = getCoApiDefinitions(importingClassMetadata)
coApiRegistrar.register(apiDefinitions)
}spring/src/main/kotlin/me/ahoo/coapi/spring/AbstractCoApiRegistrar.kt:42
Classpath Scanning Process
The automatic scanning process uses a specialized component scanner that finds interfaces annotated with @CoApi:
class ApiClientScanner(useDefaultFilters: Boolean, environment: Environment) :
ClassPathScanningCandidateComponentProvider(useDefaultFilters, environment) {
init {
addIncludeFilter(AnnotationTypeFilter(CoApi::class.java))
}
override fun isCandidateComponent(beanDefinition: AnnotatedBeanDefinition): Boolean {
return beanDefinition.metadata.isInterface
}
}spring-boot-starter/src/main/kotlin/me/ahoo/coapi/spring/boot/starter/AutoCoApiRegistrar.kt:72
The scanning combines multiple base package sources:
- Spring Boot Auto-configuration packages: Automatically detected from the main application class
- CoApi-specific packages: Configured via
coapi.base-packagesproperty - Supports both single string and array notation:
- Single package:
coapi.base-packages=com.example.clients - Multiple packages:
coapi.base-packages[0]=com.example.clients,coapi.base-packages[1]=com.example.external
- Single package:
Bean Registration Sequence
graph TD
A["Spring Boot Auto-configuration"] --> B["CoApiAutoConfiguration"]
B --> C["AutoCoApiRegistrar"]
C --> D["Conditional Check"]
D --> E{"coapi.enabled=true?"}
E -->|Yes| F["getCoApiDefinitions()"]
E -->|No| G["Skip Configuration"]
F --> H["getScanBasePackages()"]
H --> I["AutoConfigurationPackages.get()"]
H --> J["coapi.base-packages"]
I --> K["Scan CoApi Interfaces"]
J --> K
K --> L["ApiClientScanner.findCandidateComponents()"]
L --> M["Create CoApiDefinition"]
M --> N["CoApiRegistrar.register()"]
N --> O["Register HttpExchangeAdapterFactory"]
O --> P["Register Client Beans"]Configuration Properties
The auto-configuration supports several properties through CoApiProperties:
| Property | Default | Description |
|---|---|---|
coapi.enabled | true | Enable/disable CoApi auto-configuration |
coapi.base-packages | (empty) | Comma-separated list of base packages to scan |
coapi.client-mode | reactive | Client mode: sync or reactive |
Spring Boot Auto-configuration Registration
The auto-configuration is registered in the Spring Boot auto-configuration metadata:
# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
me.ahoo.coapi.spring.boot.starter.CoApiAutoConfigurationThis ensures that Spring Boot automatically discovers and includes the CoApi auto-configuration when the starter dependency is present in the classpath.
References
- Spring Boot Auto-Configuration Documentation
- Spring Boot @Conditional Annotations
- Spring ClassPathScanningCandidateComponentProvider
- Spring ImportBeanDefinitionRegistrar Interface
- CoApi @EnableCoApi Annotation
- [CoApi Client Configuration](.././customization
Related Pages
- [Client Configuration](./customization
- Api Annotation - Using the @CoApi annotation
- Properties Configuration - CoApi properties configuration
- Spring Integration - Advanced Spring integration patterns