bus-starter is the Spring Boot startup and feature-assembly layer for Bus. It centralizes configuration discovery,
bus.* property binding, conditional feature activation, default Bean registration, third-party client lifecycle, and
Spring AOT compatibility. Reusable Spring mechanics remain in bus-spring; business algorithms remain in their owning
Bus modules.
The Starter is responsible for:
- Spring Boot configuration discovery;
- default-enabled shared context infrastructure;
- opt-in product feature configuration;
- validated immutable configuration properties;
- conditional Beans and application override points;
- third-party client/service creation and destruction;
- MVC advice, filters, resolvers, and converters selected by configuration;
- feature-specific AOT and Native Image integration.
The Starter is not a replacement for the underlying modules. It must not absorb reusable Spring mechanics from
bus-spring, masking algorithms from bus-sensitive, logging behavior from bus-logger, or domain functionality from
other Bus components.
<dependency>
<groupId>org.miaixz</groupId>
<artifactId>bus-starter</artifactId>
<version>${revision}</version>
</dependency>Add the owning Bus module and required third-party library for each feature selected by the application. Optional libraries are guarded by classpath conditions so their absence does not prevent unrelated Starter infrastructure from loading.
Spring Boot discovers candidates through:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
Early Boot listeners and environment processors are registered through the single Starter-owned
META-INF/spring.factories file. bus-spring supplies their reusable implementations but does not publish a competing
discovery resource.
The root package contains two primary classes:
| Type | Responsibility |
|---|---|
GeniusBuilder |
Authoritative compile-time constants for all bus.* configuration prefixes. |
GeniusStarter |
Registers shared Spring Bean services and application-context-owned runtime context infrastructure. |
The root package therefore remains meaningful and non-empty.
Infrastructure required by multiple features is enabled independently from product features:
| Configuration | Default | Disable property | Responsibility |
|---|---|---|---|
GeniusStarter |
enabled | none | Registers Bean services, environment/provider services, runtime context, and task decorator. |
TaskConfiguration |
enabled when Boot task classes exist | bus.context.task.enabled=false |
Composes ordered task decorators and propagates runtime context. |
WebConfiguration |
enabled for Servlet applications | bus.context.web.enabled=false disables binding only |
Registers the shared RequestContext and conditionally registers context binding for request, async, and error dispatches. |
GeniusStarter contributes replaceable defaults for:
SpringContext;BeanProvider;BeanRegistry;BeanMetadata;EnvironmentResolver;ProviderRegistry;ContextManager;ContextBuilder;SpringBuilder;ContextDecorator.
Each uses a concrete @ConditionalOnMissingBean contract. Applications can replace one service without replacing the
entire infrastructure graph.
TaskConfiguration sorts all TaskDecorator Beans, removes duplicate instances, ensures one ContextDecorator, and
installs a composite decorator on Spring Boot task executors. WebConfiguration always supplies the replaceable
RequestContext Bean in Servlet applications and registers ContextBindingFilter at
Ordered.HIGHEST_PRECEDENCE + 10 for REQUEST, ASYNC, and ERROR dispatches unless binding is disabled.
bus:
context:
task:
enabled: true
web:
enabled: trueBoth switches default to true when their required runtime classes are present.
Product features use one deterministic activation order: an explicit @EnableXxx annotation always enables its feature,
including when bus.<feature>.enabled=false; without the annotation, the feature is enabled only when its
bus.<feature>.enabled property is true. If neither activation source is present, the feature remains disabled.
| Feature | Import annotation | Property | Main responsibility |
|---|---|---|---|
| Auth | @EnableAuth |
bus.auth.enabled |
Authentication service and method resolution. |
| Cache | @EnableCache |
bus.cache.enabled |
Cache provider assembly and AspectJ proxy support. |
| CORS | @EnableCors |
bus.cors.enabled |
Validated Servlet MVC CORS policy. |
| Cortex | @EnableCortex |
bus.cortex.enabled |
Cortex registry and integration assembly. |
| Dubbo | @EnableDubbo |
bus.dubbo.enabled |
Apache Dubbo integration. |
| Elastic | @EnableElastic |
bus.elastic.enabled |
Elasticsearch REST client lifecycle. |
| Fabric | @EnableFabric |
bus.fabric.enabled |
TCP, WebSocket, and DNS service lifecycle. |
| Health | @EnableHealth |
bus.health.enabled |
System health and availability integration. |
| I18n | @EnableI18n |
bus.i18n.enabled |
Message source and Bus i18n adapter. |
| Image | @EnableImage |
bus.image.enabled |
Image and DICOM provider integration. |
| JDBC | @EnableJdbc |
bus.datasource.url or spring.datasource.url |
Validated dynamic data sources and routing. |
| JSON | @EnableJson |
bus.json.enabled |
Application-context JSON provider selection. |
| Limiter | @EnableLimiter |
bus.limiter.enabled |
Limiter scanning and service registration. |
| Mapper | @EnableMapper |
bus.mapper.enabled |
MyBatis mapper scanning, plugins, tenant context, and AOT. |
| Metrics | @EnableMetrics |
bus.metrics.enabled |
Metrics providers and endpoint. |
| Mongo | @EnableMongo |
bus.mongo.enabled |
Mongo client settings customization. |
| Notify | @EnableNotify |
bus.notify.enabled |
Notification registry and service lifecycle. |
| Office | @EnableOffice |
bus.office.enabled |
Document conversion and preview service. |
| Pay | @EnablePay |
bus.pay.enabled |
Payment registry and service. |
| Sensitive | @EnableSensitive |
bus.sensitive.enabled |
Log sanitizer lifecycle and optional MVC body advice. |
| Storage | @EnableStorage |
bus.storage.enabled |
Storage providers, registry, cache, and service. |
| Tempus | @EnableTempus |
bus.tempus.enabled |
Temporal clients, workers, and lifecycle. |
| Tracer | @EnableTracer |
bus.tracer.enabled |
Distributed tracing integration. |
| Validate | @EnableValidate |
bus.validate.enabled |
Method validation and exception advice. |
| Vortex | @EnableVortex |
bus.vortex.enabled |
Reactive routing gateway and asset lifecycle. |
| Wrapper | @EnableWrapper |
bus.wrapper.enabled |
MVC binding, converters, caching, advice, and route prefixes. |
| ZooKeeper | @EnableZookeeper |
bus.zookeeper.enabled |
Apache Curator client lifecycle. |
Each annotation imports the feature configuration directly. The shared @ConditionalOnEnabled rule from
bus-spring accepts that explicit annotation before evaluating bus.<feature>.enabled as the secondary source. Both
activation paths therefore reach the same feature configuration without creating a parallel implementation.
When JSON integration is enabled, JsonConfiguration selects one JsonProvider and JsonBinding installs that exact
provider for JsonKit, cached request-body parsing, and other shared static JSON consumers. Closing the Spring context
removes only the provider owned by that binding. If more than one JSON engine is present, set
bus.json.provider=fastjson, gson, or jackson; AUTO accepts exactly one available engine.
import org.miaixz.bus.starter.annotation.EnableJson;
import org.miaixz.bus.starter.annotation.EnableSensitive;
@SpringBootApplication
@EnableJson
@EnableSensitive
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}bus:
json:
enabled: true
sensitive:
enabled: trueThe annotations make selected integrations explicit in application code. The matching properties activate them.
All feature prefixes come from GeniusBuilder; do not duplicate prefix constants in another module. Configuration
properties validate invalid combinations during binding or Bean creation and defensively copy mutable collections or
arrays where necessary.
Common rules:
- every product feature has an
enabledswitch; - optional dependencies use class conditions;
- application overrides use concrete Bean types or documented Bean names;
- secrets are excluded from diagnostic
toString()output; - timeouts use
Durationwhere supported; - long-running clients and services declare explicit destroy callbacks;
- context-owned global registrations are released when the context closes.
bus:
cors:
enabled: true
path: "/api/**"
allowed-origins:
- "https://console.example.com"
allowed-headers:
- "Authorization"
- "Content-Type"
allowed-methods:
- "GET"
- "POST"
exposed-headers:
- "X-Request-Id"
allow-credentials: true
max-age: 30mWildcard origins cannot be combined with credentials. Arrays are copied defensively. Defaults include GET, POST, PUT, OPTIONS, and DELETE, while the feature itself remains disabled until explicitly enabled.
bus:
sensitive:
enabled: true
debug: falseThe transport-neutral path is always available when enabled:
Sanitizer -> SensitiveBinding -> bus-logger Executor
SensitiveBinding unregisters its sanitizer when the owning application context closes. In Servlet MVC applications,
the nested SensitiveConfiguration.ServletConfiguration additionally contributes request decryption and response
encryption or masking advice. There is no separate SensitiveWebConfiguration.
Encryption keys must come from a protected external configuration source. Diagnostic output masks key material.
bus:
elastic:
enabled: true
hosts: "127.0.0.1:9200"
schema: "http"
connect-timeout: 6s
socket-timeout: 60s
connection-request-timeout: 6s
max-connect-total: 2000
max-connect-per-route: 500Each host must contain a valid port in the range 1..65535. Timeouts and connection limits must be positive, and the
per-route limit cannot exceed the total limit.
bus.fabric.enabled=true or @EnableFabric activates the Fabric parent integration. The explicit annotation has
priority over the property. TCP socket support is enabled by default after the parent is active; WebSocket and DNS
remain child capabilities and require their own enabled=true property. DNS is deliberately imported by
FabricConfiguration, so bus.fabric.dns.enabled=true cannot create a second independent Fabric entry point.
bus:
fabric:
enabled: true
socket:
enabled: true
host: 0.0.0.0
port: 7890
websocket:
enabled: false
dns:
enabled: true
transport: UDP
host: 0.0.0.0
port: 53
cache: true
cache-max-entries: 10000
cache-ttl: 30s
cache-serve-stale-ttl: 5m
cache-prefetch-before-expiry: 5s
max-udp-payload-bytes: 1232
rate-limit-per-second: 0The application must provide one DnsSnapshotProvider; it remains the owner of DNS zones and snapshots. Optional
DnsSnapshotListener, DnsDynamicUpdateSink, DnsTsigKey, and TlsPolicy beans extend lifecycle notifications,
dynamic updates, TSIG validation, and DoT respectively. The Starter owns only the runtime DnsServer bean and closes it
with the Spring context. DNS management, database access, and persistence are outside the Starter.
The Starter assembles JDBC automatically when the pool classes are available. Set bus.datasource.enabled=false to
disable automatic assembly; an explicit @EnableJdbc always has higher priority and still enables JDBC. Datasource
definitions use bus.datasource or spring.datasource, and both use the same root-primary plus multi structure. They
are never merged: a bus.datasource URL selects the complete Bus group and overrides spring.datasource.
bus:
datasource:
name: master
url: jdbc:mysql://127.0.0.1:3306/app
username: app
password: ${APP_DB_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
maximum-pool-size: 20
multi:
- name: archive
url: jdbc:mysql://127.0.0.1:3306/archive
username: app
password: ${ARCHIVE_DB_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
maximum-pool-size: 10JDBC responsibilities are fixed. Reusable DataSourceResolver, DataSourceDefinition, DataSourceMapping,
DataSourceFactory, DynamicDataSource, DataSourceHolder, and AspectjJdbcProxy live in bus-spring under
org.miaixz.bus.spring.jdbc. The Starter package retains only JdbcConfiguration, which assembles Beans, and
JdbcDescriptor, which defines the Bus-before-Spring prefix order and Hikari default. Both prefixes use the same
resolver path. The root name is the default route and every multi entry supplies an additional route. Names must be
nonblank and unique across the complete group. JDBC never references Mapper. When Mapper is enabled, its own
DataSourceListener synchronizes dialect state for initial and runtime route changes. The routing Bean owns every pool
created from these definitions: replacing or removing a route closes the unreferenced pool, and application-context
shutdown closes every remaining pool exactly once.
Service methods select a named datasource with @DataSource. A method annotation overrides its class annotation, and
nested invocations restore the exact parent route on return or failure:
import org.miaixz.bus.spring.jdbc.DataSource;
@Service
public class OrderService {
@DataSource("archive")
@Transactional
public void createOrder() {
// Mapper operations use archive.
}
}Routing must occur before transaction advice obtains a connection. Put @DataSource on the externally invoked service
transaction boundary, or call a routed inner operation through another Spring bean proxy. Self-invocation through
this bypasses AOP, and an already active outer transaction cannot change its acquired connection. Dynamic routing is
not a distributed transaction mechanism. Tenant or routing information must come from trusted runtime context rather
than request-controlled model fields.
Mapper integration covers:
- deterministic mapper classpath scanning;
MapperFactoryBeanand scanner registration;- XML/resource location resolution;
- ordered plugin construction;
- tenant identity from
ContextBuilder; - tenant exception advice;
- AOT Bean factory initialization and runtime hints.
Business code must not overwrite tenant identity through request binding. Custom mapper plugins should use the
documented provider and interceptor extension points instead of modifying the Starter registry after startup.
@EnableMapper scans its declaring package when no package attribute is supplied. Property activation uses
bus.mapper.base-package; when that is also absent, Spring Boot application packages are scanned for explicit
@Mapper interfaces. An unresolved scan scope fails startup instead of silently registering no Mapper. Dialects are
bound to the owning MyBatis Configuration, so two application contexts cannot overwrite each other's route provider.
bus.wrapper.enabled=true activates the aggregate wrapper configuration. Child features remain independently
controlled:
| Capability | Property | Default after Wrapper is enabled |
|---|---|---|
| Request-object binding | bus.wrapper.request-binding.enabled |
true |
| Message converters | bus.wrapper.message-converters.enabled |
true |
| Bounded body cache | bus.wrapper.body-cache.enabled |
false |
| Response advice | bus.wrapper.response-advice.enabled |
false |
| Route prefix | bus.wrapper.route-prefix.enabled |
false |
bus:
wrapper:
enabled: true
request-binding:
enabled: true
message-converters:
enabled: true
type-policy: application
allowed-types:
- com.example.shared.dto.**
- com.example.shared.dto1.**
body-cache:
enabled: false
response-advice:
enabled: false
route-prefix:
enabled: falseMessage converter target-type policies are:
framework: allows Bus framework types, built-in scalar/container types, and explicit rules;application: also discovers Spring Boot application packages and is the default;all: allows every target type and must only be used in trusted environments.
allowed-types accepts exact class names, * for one package segment, and ** for any number of package segments.
The compatibility property auto-type accepts comma-separated rules; auto-type: "**" also explicitly allows every
target type. Prefer allowed-types for new applications.
Request-object binding requires @RequestObject, excludes framework and simple scalar types, and does not allow request
input to replace trusted tenant context. Body caching is bounded; multipart and response diagnostic caching remain
opt-in.
The Starter owns the lifecycle of clients and long-running services it creates:
| Feature | Lifecycle examples |
|---|---|
| Elastic | REST transport/client close. |
| Fabric | TCP and WebSocket service start/stop. |
| Notify, Office, Pay, Storage | Registry/service creation and context cleanup. |
| Tempus | Client, worker factory, workers, and shutdown. |
| Vortex | Router graph, server start/stop, and asset lifecycle. |
| ZooKeeper | Curator client start/close. |
An application-provided replacement Bean owns its own lifecycle unless the replacement contract states otherwise.
Prefer replacing the concrete product contract:
@Bean
StorageService customStorageService(...) {
return new StorageService(...);
}Do not depend on configuration implementation classes from business code. Configuration and property packages are opened
to Spring for framework access but are not exported as general JPMS APIs. Only
org.miaixz.bus.starter.annotation is exported.
| Package group | Content |
|---|---|
| root | Shared startup infrastructure and property-prefix constants. |
annotation |
Public @Enable* annotations. |
context |
Default task and Servlet context propagation. |
| feature packages | One feature's configuration, properties, services, and lifecycle collaborators. |
wrapper.* |
Independently controlled MVC wrapper capabilities. |
There are no internal packages. Feature implementation types stay in their current feature package.
- Product features are opt-in.
- Credentialed CORS rejects wildcard origins.
- Sensitive keys and credentials are not exposed by property diagnostics.
- Request binding does not source authenticated tenant identity from user input.
- Cached bodies have explicit bounds and multipart caching is opt-in.
- Logging sanitization is owned by
bus-sensitive, notbus-logger. - Context state is isolated per application context and restored after asynchronous execution.
- Third-party resources are closed with the owning Spring context.
Spring AOT generates most configuration and Bean reflection hints. Checked-in reachability metadata therefore lists only exact constructors and dynamically accessed members. Entries and nested member lists are sorted A–Z.
The following broad grants are prohibited:
allDeclaredConstructorsandallPublicConstructors;allDeclaredMethodsandallPublicMethods;allDeclaredFieldsandallPublicFields.
The Abarth metadata audit resolves every configured class, constructor, method, field, proxy, and resource against the current runtime model and also enforces ordering.
- Use
XxxConfiguration; removedXxxAutoConfigurationnames must not return. - Use
ContextState,ContextScope, andContextDecoratorfor runtime propagation. - Use
GeniusBuilderfor Starter property prefixes. - Keep reusable mechanics in
bus-springand domain behavior in the owning Bus module. - Do not introduce an
internalpackage under Starter. - Override defaults by Bean type or documented Bean name.
- Keep
AutoConfiguration.imports,spring.factories, module descriptors, and reachability metadata aligned with class renames.
Bus contains and runs no tests. Starter integration, binding, lifecycle, module-path, metadata, AOT, and Native Image tests are maintained in the sibling Abarth repository. Bus builds must skip tests explicitly.