目录
Spring Integration概述
企业集成模式
Spring Integration实现了企业集成模式(EIP),提供了一套完整的消息驱动架构:
核心概念:
- 消息通道:消息传输的载体
- 消息端点:消息的生产者和消费者
- 消息转换:消息格式转换
- 消息路由:智能消息分发
- 消息过滤:选择性消息处理
Maven依赖配置
<dependencies>
<!-- Spring Integration Core -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
<version>5.5.18</version>
</dependency>
<!-- Spring Integration HTTP -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-http</artifactId>
<version>5.5.18</version>
</dependency>
<!-- Spring Integration JDBC -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jdbc</artifactId>
<version>5.5.18</version>
</dependency>
<!-- Spring Integration File -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-file</artifactId>
<version>5.5.18</version>
</dependency>
<!-- Spring Integration JMS -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jms</artifactId>
<version>5.5.18</version>
</dependency>
<!-- Spring Integration Email -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-mail</artifactId>
<version>5.5.18</version>
</dependency>
<!-- Spring Integration WebFlux -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-webflux</artifactId>
<version>5.5.18</version>
</dependency>
</dependencies>
消息通道
不同类型的通道
通道配置:
@Configuration
@EnableIntegration
public class IntegrationChannelConfig {
// 点对点通道
@Bean
public MessageChannel orderProcessingChannel() {
return MessageChannels.direct("orderProcessing").get();
}
// 发布订阅通道
@Bean
public MessageChannel notificationChannel() {
return MessageChannels.publishSubscribe("notification").get();
}
// 队列通道(有界队列)
@Bean
public MessageChannel boundedQueueChannel() {
return MessageChannels.queue("boundedQueue", 100).get();
}
// 可执行器通道(异步处理)
@Bean
public MessageChannel asyncProcessingChannel() {
return MessageChannels.executor("asyncProcessing", taskExecutor()).get();
}
// 轮询通道(循环分发)
@Bean
public MessageChannel loadBalancingChannel() {
return MessageChannels.publishSubscribe("loadBalancing")
.applySequence(true)
.get();
}
// 优先队列通道
@Bean
public MessageChannel priorityChannel() {
return MessageChannels.priority("priorityChannel",
OrderPriority.comparator()).get();
}
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("Integration-");
executor.initialize();
return executor;
}
}
// 订单优先级比较器
public class OrderPriorityComparator implements Comparator<Message<?>> {
@Override
public int compare(Message<?> o1, Message<?> o2) {
OrderPriority p1 = (OrderPriority) o1.getHeaders().get("priority");
OrderPriority p2 = (OrderPriority) o2.getHeaders().get("priority");
if (p1 == null) p1 = OrderPriority.NORMAL;
if (p2 == null) p2 = OrderPriority.NORMAL;
return p1.ordinal() - p2.ordinal();
}
}
通道拦截器
通道拦截器实现:
@Component
public class OrderChannelInterceptor implements ChannelInterceptor {
private static final Logger logger = LoggerFactory.getLogger(OrderChannelInterceptor.class);
@Autowired
private MetricsRegistry metricsRegistry;
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
logger.info("消息发送前拦截: 通道={}, 消息ID={}",
channel.toString(),
message.getHeaders().get("id"));
// 验证消息格式
validateMessage(message);
// 记录发送指标
metricsRegistry.incrementCounter("messages.sent",
"channel", channel.toString());
// 设置消息追踪信息
addTracingHeaders(message);
return message;
}
@Override
public void postSend(Message<?> message, MessageChannel channel, boolean sent) {
if (sent) {
logger.info("消息发送成功: 通道={}", channel.toString());
metricsRegistry.incrementCounter("messages.sent.success",
"channel", channel.toString());
} else {
logger.warn("消息发送失败: 通道={}", channel.toString());
metricsRegistry.incrementCounter("messages.sent.failure",
"channel", channel.toString());
}
}
@Override
public Message<?> postReceive(Message<?> message, MessageChannel channel) {
logger.info("消息接收后拦截: 通道={}, 消息ID={}",
channel.toString(),
message.getHeaders().get("id"));
// 记录接收指标
metricsRegistry.incrementCounter("messages.received",
"channel", channel.toString());
// 处理延时统计
Long createdTime = (Long) message.getHeaders().get("createdTime");
if (createdTime != null) {
long latency = System.currentTimeMillis() - createdTime;
metricsRegistry.recordTimer("message.latency", latency,
TimeUnit.MILLISECONDS);
}
return message;
}
@Override
public boolean preReceive(MessageChannel channel) {
logger.debug("消息接收前拦截: 通道={}", channel.toString());
return true;
}
private void validateMessage(Message<?> message) {
if (message.getPayload() == null) {
throw new IllegalStateException("消息负载不能为空");
}
MessageHeaders headers = message.getHeaders();
if (!headers.containsKey("id")) {
throw new IllegalStateException("消息必须包含ID头部信息");
}
}
private void addTracingHeaders(Message<?> message) {
// 添加分布式追踪头部信息
String traceId = UUID.randomUUID().toString();
String spanId = UUID.randomUUID().toString();
((MessageHeaders) message.getHeaders()).put("traceId", traceId);
((MessageHeaders) message.getHeaders()).put("spanId", spanId);
((MessageHeaders) message.getHeaders()).put("createdTime", System.currentTimeMillis());
}
}
消息转换器
内置转换器
消息转换配置:
@Configuration
public class MessageConverterConfig {
@Bean
public ObjectToMapConverter objectToMapConverter() {
return new ObjectToMapConverter();
}
@Bean
public MapToObjectConverter<Order> mapToOrderConverter() {
return new MapToOrderConverter();
}
@Bean
public JsonToObjectTransformer jsonToOrderTransformer() {
ObjectMapper objectMapper = createObjectMapper();
return new JsonToObjectTransformer(objectMapper, Order.class);
}
@Bean
public ObjectToJsonTransformer objectToJsonTransformer() {
ObjectMapper objectMapper = createObjectMapper();
return new ObjectToJsonTransformer(objectMapper);
}
@Bean
public XmlToJsonTransformer xmlToJsonTransformer() {
return new XmlToJsonTransformer();
}
@Bean
public FlatFileTransformer flatFileTransformer() {
LineAggregator<Order> lineAggregator = new DelimitedLineAggregator<Order>() {
{
setDelimiter("|");
setFieldExtractor(new BeanWrapperFieldExtractor<Order>() {
{
setNames(new String[]{"id", "customerName", "amount"});
}
});
}
};
return new FlatFileTransformer(flatFileItemReader(), lineAggregator);
}
@Bean
public FlatFileItemReader<Order> flatFileItemReader() {
FlatFileItemReader<Order> reader = new FlatFileItemReader<>();
reader.setResource(new ClassPathResource("orders.txt"));
reader.setLineMapper(new DefaultLineMapper<Order>() {
{
setLineTokenizer(new DelimitedLineTokenizer("|") {
{
setNames(new String[]{"id", "customerName", "amount"});
}
});
setFieldSetMapper(new BeanWrapperFieldSetMapper<Order>() {
{
setTargetType(Order.class);
}
});
}
});
return reader;
}
private ObjectMapper createObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
return mapper;
}
}
// 自定义转换器
@Component
public class OrderToOrderDtoConverter implements Converter<Order, OrderDto> {
@Override
public OrderDto convert(Order source) {
OrderDto dto = new OrderDto();
dto.setId(source.getId());
dto.setOrderNumber(source.getOrderNumber());
dto.setCustomerName(String.format("%s %s",
source.getCustomer().getFirstName(),
source.getCustomer().getLastName()));
dto.setTotalAmount(source.getTotalAmount());
dto.setStatus(source.getStatus().name());
dto.setCreatedDate(source.getCreatedDate());
// 计算订单优先级
dto.setPriority(calculatePriority(source));
// 添加扩展信息
dto.setMetadata(extractMetadata(source));
return dto;
}
private OrderPriority calculatePriority(Order order) {
if (order.getTotalAmount().compareTo(new BigDecimal("1000")) > 0) {
return OrderPriority.HIGH;
} else if (order.getCustomer().getCustomerTier() == CustomerTier.PREMIUM) {
return OrderPriority.HIGH;
} else if (order.getItems().size() > 10) {
return OrderPriority.MEDIUM;
} else {
return OrderPriority.NORMAL;
}
}
private Map<String, Object> extractMetadata(Order order) {
Map<String, Object> metadata = new HashMap<>();
metadata.put("itemCount", order.getItems().size());
metadata.put("paymentMethod", order.getPaymentMethod());
metadata.put("hasDiscount", order.getDiscountAmount().compareTo(BigDecimal.ZERO) > 0);
metadata.put("isExpress", order.isExpressDelivery());
return metadata;
}
}
消息路由器
智能路由
消息路由配置:
@Configuration
public class MessageRouterConfig {
@Bean
public MessageChannel orderRouterChannel() {
return MessageChannels.direct("orderRouter").get();
}
// 普通路由器
@Bean
@ServiceActivator(inputChannel = "orderRouterChannel")
public Router orderRouter() {
ExpressionEvaluatingRouter router = new ExpressionEvaluatingRouter(
"payload.status", OrderProcessingChannel.class);
router.setDefaultOutputChannelName("defaultOrderChannel");
router.setChannelMapping("PENDING", "pendingOrderChannel");
router.setChannelMapping("PROCESSING", "processingOrderChannel");
router.setChannelMapping("COMPLETED", "completedOrderChannel");
router.setChannelMapping("CANCELLED", "cancelledOrderChannel");
return router;
}
// 头部分离路由器
@Bean
@ServiceActivator(inputChannel = "splitterChannel")
public HeaderValueRouter headerValueRouter() {
HeaderValueRouter router = new HeaderValueRouter("productType");
router.setChannelMapping("ELECTRONICS", "electronicsChannel");
router.setChannelMapping("CLOTHING", "clothingChannel");
router.setChannelMapping("BOOKS", "booksChannel");
router.setChannelMapping("HOME", "homeChannel");
router.setDefaultOutputChannelName("generalChannel");
return router;
}
// 自定义路由器
@Bean
@ServiceActivator(inputChannel = "orderRoutingChannel")
public Router customOrderRouter() {
return new AbstractRouter() {
@Override
protected Collection<MessageChannel> determineTargetChannels(Message<?> message) {
Order order = (Order) message.getPayload();
Collection<MessageChannel> channels = new ArrayList<>();
// 基于订单金额路由
if (order.getTotalAmount().compareTo(new BigDecimal("10000")) > 0) {
channels.add(getTargetChannel("vipOrderChannel"));
} else if (order.getTotalAmount().compareTo(new BigDecimal("1000")) > 0) {
channels.add(getTargetChannel("premiumOrderChannel"));
} else {
channels.add(getTargetChannel("standardOrderChannel"));
}
// 基于地理位置路由
if ("International".equals(order.getShippingAddress().getCountry())) {
channels.add(getTargetChannel("internationalOrderChannel"));
}
// 基于商品类型路由
Set<String> productCategories = order.getItems().stream()
.map(item -> item.getProduct().getCategory().getName())
.collect(Collectors.toSet());
if (productCategories.contains("Electronics")) {
channels.add(getTargetChannel("electronicsOrderChannel"));
}
if (productCategories.contains("Books")) {
channels.add(getTargetChannel("bookOrderChannel"));
}
return channels;
}
};
}
// 负载均衡路由器
@Bean
@ServiceActivator(inputChannel = "loadBalancerChannel")
public LoadBalancingStrategy loadBalancingStrategy() {
return new RoundRobinLoadBalancingStrategy();
}
// 异常路由器
@Bean
@ServiceActivator(inputChannel = "errorRecoveryChannel")
public Router errorRecoveryRouter() {
ExpressionEvaluatingRouter router = new ExpressionEvaluatingRouter(
"headers['EXCEPTION']", RetryableErrorChannel.class);
router.setChannelMapping("java.lang.IllegalArgumentException", "validationErrorChannel");
router.setChannelMapping("java.sql.SQLException", "databaseErrorChannel");
router.setChannelMapping("java.net.SocketTimeoutException", "timeoutErrorChannel");
router.setDefaultOutputChannelName("genericErrorChannel");
return router;
}
private MessageChannel getTargetChannel(String channelName) {
return ApplicationContextHolder.getApplicationContext()
.getBean(channelName, MessageChannel.class);
}
}
条件路由
条件表达式路由:
@Component
public class ConditionalRouter extends AbstractRouter {
@Override
protected Collection<MessageChannel> determineTargetChannels(Message<?> message) {
MessageHeaders headers = message.getHeaders();
Collection<MessageChannel> channels = new ArrayList<>();
// 工作时间和非工作时间分离
LocalDateTime now = LocalDateTime.now();
DayOfWeek dayOfWeek = now.getDayOfWeek();
int hour = now.getHour();
boolean isBusinessHour = dayOfWeek != DayOfWeek.SATURDAY &&
dayOfWeek != DayOfWeek.SUNDAY &&
hour >= 9 && hour <= 18;
if (isBusinessHour) {
channels.add(getChannel("businessHourChannel"));
} else {
channels.add(getChannel("afterHoursChannel"));
}
// 紧急订单特殊处理
String priority = (String) headers.get("priority");
if ("URGENT".equals(priority)) {
channels.add(getChannel("urgentProcessingChannel"));
}
// VIP客户特殊处理
boolean isVipCustomer = (boolean) headers.getOrDefault("isVip", false);
if (isVipCustomer) {
channels.add(getChannel("vipCustomerChannel"));
}
return channels;
}
}
AutoConfiguration机制
自动配置原理
Spring Boot自动配置核心机制:
@Configuration
@ConditionalOnClass
@EnableConfigurationProperties
@AutoConfigureAfter
@AutoConfigureBefore
public class CustomAutoConfiguration {
// 自动配置Bean
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "custom.service", name = "enabled", havingValue = "true", matchIfMissing = true)
public CustomService customService(CustomProperties properties) {
return new CustomServiceImpl(properties);
}
// 条件化创建的Bean
@Bean
@ConditionalOnProperty(prefix = "custom", name = "metrics.enabled", havingValue = "true")
public MeterRegistry customizeMeterRegistry() {
return new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
}
// 依赖注入的Bean
@Bean
public CustomController customController(CustomService customService,
CustomMetricsService metricsService) {
return new CustomController(customService, metricsService);
}
}
自定义自动配置
完整自动配置类:
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(CustomProperties.class)
@ConditionalOnClass(CustomService.class)
@ConditionalOnProperty(prefix = "custom", name = "enabled", matchIfMissing = true)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class CustomAutoConfiguration {
private final CustomProperties properties;
public CustomAutoConfiguration(CustomProperties properties) {
this.properties = properties;
}
@Bean
@ConditionalOnMissingBean(CustomService.class)
public CustomService customService() {
log.info("自动配置CustomService,配置属性: {}", properties);
return new CustomServiceImpl(properties);
}
@Bean
@ConditionalOnClass(TaskExecutor.class)
@ConditionalOnMissingBean(name = "customTaskExecutor")
public TaskExecutor customTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(properties.getExecutor().getCorePoolSize());
executor.setMaxPoolSize(properties.getExecutor().getMaxPoolSize());
executor.setQueueCapacity(properties.getExecutor().getQueueCapacity());
executor.setThreadNamePrefix("custom-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
log.info("自动配置自定义任务执行器: core={}, max={}, queue={}",
properties.getExecutor().getCorePoolSize(),
properties.getExecutor().getMaxPoolSize(),
properties.getExecutor().getQueueCapacity();
return executor;
}
@Bean
@ConditionalOnMissingBean(CustomHealthIndicator.class)
@ConditionalOnProperty(prefix = "custom", name = "health.enabled", matchIfMissing = true)
public CustomHealthIndicator customHealthIndicator(CustomService customService) {
return new CustomHealthIndicator(customService, properties.getHealth());
}
@Bean
@ConditionalOnMissingBean(CustomActuatorEndpoint.class)
@ConditionalOnProperty(prefix = "management.custom", name = "enabled", matchIfMissing = true)
public CustomActuatorEndpoint customActuatorEndpoint(CustomService customService) {
return new CustomActuatorEndpoint(customService);
}
@Bean
@ConditionalOnClass(HttpMessageConverters.class)
@ConditionalOnMissingBean(name = "customMessageConverter")
public HttpMessageConverter<?> customMessageConverter() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
return new MappingJackson2HttpMessageConverter(objectMapper);
}
@Bean
@ConditionalOnMissingBean(CustomMetricsCollector.class)
@ConditionalOnEnabledMetricsEndpoint
public CustomMetricsCollector customMetricsCollector(MeterRegistry meterRegistry) {
return new CustomMetricsCollector(meterRegistry);
}
// 配置后处理器
@Bean
public BeanFactoryCustomizer beanFactoryCustomizer() {
return beanFactory -> {
log.info("Custom bean factory customization applied");
// 添加自定义后处理器
beanFactory.addBeanPostProcessor(new CustomBeanPostProcessor());
// 注册自定义作用域
beanFactory.registerScope("custom", new CustomScope());
};
}
}
// 配置属性类
@ConfigurationProperties(prefix = "custom")
@Validated
public class CustomProperties {
/**
* 是否启用自定义服务
*/
private boolean enabled = true;
/**
* 服务名称
*/
@NotBlank(message = "服务名称不能为空")
private String serviceName = "CustomService";
/**
* 重试配置
*/
private Retry retry = new Retry();
/**
* 缓存配置
*/
private Cache cache = new Cache();
/**
* 健康检查配置
*/
private Health health = new Health();
/**
* 执行器配置
*/
private Executor executor = new Executor();
@Data
public static class Retry {
private int maxAttempts = 3;
private Duration initialDelay = Duration.ofSeconds(1);
private Duration maxDelay = Duration.ofSeconds(30);
private double multiplier = 2.0;
}
@Data
public static class Cache {
private boolean enabled = true;
private Duration ttl = Duration.ofMinutes(10);
private int maxSize = 1000;
}
@Data
public static class Health {
private boolean enabled = true;
private Duration timeout = Duration.ofSeconds(5);
private String[] criticalChecks = {};
}
@Data
public static class Executor {
private int corePoolSize = Runtime.getRuntime().availableProcessors();
private int maxPoolSize = Runtime.getRuntime().availableProcessors() * 2;
private int queueCapacity = 100;
}
}
自定义Starter开发
Spring Boot Starter结构
Starter项目结构:
custom-spring-boot-starter/
├── pom.xml
├── src/main/
│ ├── java/com/example/custom/
│ │ ├── CustomAutoConfiguration.java
│ │ ├── CustomProperties.java
│ │ ├── CustomService.java
│ │ ├── CustomServiceImpl.java
│ │ └── CustomHealthIndicator.java
│ └── resources/
│ ├── META-INF/
│ │ └── spring.factories
│ └── application.yml
└── README.md
Maven配置:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelNumber>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>Custom Spring Boot Starter</name>
<description>自定义Spring Boot Starter模块</description>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-boot.version>2.7.5</spring-boot.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Spring Boot Configuration Processor -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<scope>provided</scope>
</dependency>
<!-- Spring Boot Boot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- Micrometer Core -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
Spring.factories配置
spring.factories文件:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.custom.config.CustomAutoConfiguration,\
com.example.custom.config.CustomSecurityAutoConfiguration,\
com.example.custom.config.CustomMetricsAutoConfiguration,\
com.example.custom.config.CustomCacheAutoConfiguration
# Auto Configuration Import Selectors
org.springframework.boot.autoconfigure.AutoConfigurationImportSelector=\
com.example.custom.selector.CustomConfigurationImportSelector
# Configuration Properties
org.springframework.boot.env.PropertySourceLoader=\
com.example.custom.properties.CustomPropertySourceLoader
# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
com.example.custom.failure.CustomFailureAnalyzer
# Bean Information Contributors
org.springframework.boot.autoconfigure.processor.ConfigurerBeanInformationContributor=\
com.example.custom.info.CustomBeanInformationContributor
Starter使用示例
在项目中使用Starter:
<dependency>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
application.yml配置:
custom:
enabled: true
service-name: "MyCustomService"
retry:
max-attempts: 5
initial-delay: PT2S
max-delay: PT1M
multiplier: 1.5
cache:
enabled: true
ttl: PT15M
max-size: 2000
health:
enabled: true
timeout: PT10S
critical-checks: ["database", "external-api"]
executor:
core-pool-size: 4
max-pool-size: 8
queue-capacity: 50
配置属性绑定
类型安全配置
复杂配置属性绑定:
@ConfigurationProperties(prefix = "database.master")
@Validated
public class MasterDatabaseProperties {
@NotBlank(message = "Master数据库URL不能为空")
private String url;
@NotBlank(message = "Master数据库用户名不能为空")
private String username;
@NotBlank(message = "Master数据库密码不能为空")
private String password;
@Min(value = 5, message = "连接池最小大小不能小于5")
@Max(value = 100, message = "连接池最小大小不能超过100")
private int minPoolSize = 5;
@Min(value = 10, message = "连接池最大大小不能小于10")
@Max(value = 200, message = "连接池最大大小不能超过200")
private int maxPoolSize = 50;
@Min(value = 30000, message = "连接超时时间不能少于30秒")
private Duration connectionTimeout = Duration.ofSeconds(30);
@NotNull
private Pool pool = new Pool();
@NotNull
private Cluster cluster = new Cluster();
@Data
@Validated
public static class Pool {
@Min(value = 1)
private Duration maxLifetime = Duration.ofMinutes(30);
@Min(value = 1000)
private Duration idleTimeout = Duration.ofMinutes(10);
@Min(value = 0)
private Duration leakDetectionThreshold = Duration.ofMinutes(5);
}
@Data
@Validated
public static class Cluster {
private boolean enabled = false;
@NotBlank
private String replicaHosts = "";
@Min(value = 1)
private int replicaPort = 3306;
@Min(value = 1)
private Duration failoverTimeout = Duration.ofSeconds(30);
@Min(value = 0)
private Duration heartbeatInterval = Duration.ofSeconds(10);
}
/**
* 动态计算连接池配置
*/
@PostConstruct
public void validateConfiguration() {
if (minPoolSize >= maxPoolSize) {
throw new IllegalStateException("最小连接池大小不能大于等于最大连接池大小");
}
if (connectionTimeout.compareTo(Duration.ofSeconds(60)) > 0) {
log.warn("连接超时时间过长,可能影响性能");
}
log.info("Master数据库配置加载完成: url={}, poolSize=[{}, {}]",
url, minPoolSize, maxPoolSize);
}
}
嵌套配置绑定
多层嵌套配置:
@ConfigurationProperties(prefix = "application")
@EnableConfigurationProperties({
ApplicationConfig.class,
DatabaseConfig.class,
CacheConfig.class,
SecurityConfig.class
})
public class ApplicationConfig {
@NotNull
private Info info;
@NotNull
private Profiles profiles;
@NotNull
private Features features;
@Data
public static class Info {
@NotBlank
private String name;
@NotBlank
private String version;
private String description;
private Build build;
@Data
public static class Build {
private String artifact;
private String group;
private String version;
private LocalDateTime time;
}
}
@Data
public static class Profiles {
private String active;
private boolean includeDefault = true;
private Map<String, ProfileConfig> environments = new HashMap<>();
@Data
public static class ProfileConfig {
private boolean enabled;
private String url;
private String username;
private String password;
private Map<String, Object> properties = new HashMap<>();
}
}
@Data
public static class Features {
private boolean enableMetrics = true;
private boolean enableTracing = true;
private boolean enableLogging = true;
private boolean enableSecurity = true;
private boolean enableCaching = false;
private boolean enableAsync = false;
private Map<String, Boolean> endpoints = new HashMap<>();
public boolean isEndpointEnabled(String endpoint) {
return endpoints.getOrDefault(endpoint, endpoint.startsWith("health"));
}
}
@PostConstruct
public void initializeFeatures() {
// 根据环境动态调整特性
String activeProfile = profiles.getActive();
if ("prod".equals(activeProfile)) {
features.setEnableLogging(false); // 生产环境关闭详细日志
features.setEnableTracing(false); // 生产环境关闭追踪
} else if ("dev".equals(activeProfile)) {
features.setEnableMetrics(false); // 开发环境关闭指标收集
}
log.info("应用配置初始化完成: name={}, version={}, activeProfile={}",
info.getName(), info.getVersion(), activeProfile);
}
}
条件化装配
条件注解使用
高级条件化配置:
@Configuration
@ConditionalOnClass({DataSourceAuthenticationProvider.class})
public class ConditionalConfiguration {
@Configuration
@ConditionalOnProperty(prefix = "custom.auth", name = "provider", havingValue = "database")
@EnableConfigurationProperties(DatabaseAuthProperties.class)
public static class DatabaseAuthConfiguration {
@Bean
@ConditionalOnMissingBean
public DataSourceAuthenticationProvider databaseAuthProvider(
DataSourceAuthenticationTokenRepository repository,
PasswordEncoder passwordEncoder) {
return new DataSourceAuthenticationProvider(repository, passwordEncoder);
}
@Bean
@ConditionalOnMissingBean
public DataSourceAuthenticationTokenRepository authTokenRepository(
DataSource dataSource) {
return new DataSourceAuthenticationTokenRepository(dataSource);
}
}
@Configuration
@ConditionalOnProperty(prefix = "custom.auth", name = "provider", havingValue = "ldap")
@ConditionalOnClass({LdapAuthenticationProvider.class})
public static class LdapAuthConfiguration {
@Bean
@ConditionalOnMissingBean
public LdapAuthenticationProvider ldapAuthProvider(LdapProperties ldapProperties) {
return new LdapAuthenticationProvider(
ldapProperties.getUrl(),
ldapProperties.getUserDnPattern(),
ldapProperties.getGroupSearchBase()
);
}
}
@Configuration
@ConditionalOnProperty(prefix = "custom.auth", name = "provider", havingValue = "oauth")
@ConditionalOnClass({OAuthAuthenticationProvider.class})
public static class OAuthAuthConfiguration {
@Bean
@ConditionalOnMissingBean
public OAuthAuthenticationProvider oauthAuthProvider(OAuthProperties oauthProperties) {
return OAuthAuthenticationProvider.builder()
.clientId(oauthProperties.getClientId())
.clientSecret(oauthProperties.getClientSecret())
.authorizationEndpoint(oauthProperties.getAuthorizationEndpoint())
.tokenEndpoint(oauthProperties.getTokenEndpoint())
.build();
}
}
}
// 自定义条件
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({OnFeatureEnabledCondition.class})
public @interface ConditionalOnFeatureEnabled {
String value();
}
@Component
public class OnFeatureEnabledCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
AnnotationAttributes attributes = AnnotationAttributes.fromMap(
metadata.getAnnotationAttributes(ConditionalOnFeatureEnabled.class.getName()));
String featureName = attributes.getString("value");
Environment env = context.getEnvironment();
boolean enabled = env.getProperty("features." + featureName, Boolean.class, false);
return enabled;
}
}
// 使用自定义条件
@Configuration
@ConditionalOnFeatureEnabled("advanced-caching")
public class AdvancedCacheConfiguration {
@Bean
@ConditionalOnMissingBean
public AdvancedCacheManager advancedCacheManager(
@Qualifier("cacheManager") CacheManager defaultCacheManager) {
return new AdvancedCacheManager(defaultCacheManager);
}
@Bean
@ConditionalOnMissingBean
public CacheMetricsCollector cacheMetricsCollector(
AdvancedCacheManager cacheManager,
MeterRegistry meterRegistry) {
return new CacheMetricsCollector(cacheManager, meterRegistry);
}
}
总结
Spring集成框架与AutoConfiguration为企业级应用提供了灵活、可扩展的配置和集成解决方案:
核心技术要点
- 消息驱动架构 - Spring Integration的通道、路由、转换机制
- 智能路由 - 基于条件、优先级、负载均衡的消息分发
- 自动配置 - Spring Boot AutoConfiguration机制的深入理解
- 自定义Starter - 可复用组件的打包和分发
- 条件化装配 - 基于环境和条件的动态Bean创建
- 配置属性绑定 - 类型安全的外部配置管理
企业级应用价值
- 架构灵活性:消息驱动实现松耦合的组件通信
- 配置标准化:统一的外部配置管理和属性绑定
- 组件复用:自定义Starter提供开箱即用的功能模块
- 环境适应性:条件化配置满足不同环境的需求
最佳实践建议
- 条件装配:合理使用条件注解控制Bean的创建
- 配置验证:使用@Validated确保配置的正确性
- 启动优化:避免不必要的依赖和复杂的Bean创建逻辑
- 文档完整:为自定义Starter提供完整的文档和示例
- 版本兼容:保证Starter向后兼容性
核心竞争优势
- 开发效率:自动配置减少样板代码,提高开发效率
- 系统可靠性:条件化装配避免不必要的组件加载
- 维护便利性:统一的配置管理简化系统维护
- 扩展能力:灵活的Starter机制支持功能模块的快速集成
通过Spring集成框架和AutoConfiguration机制,小伙伴们可以构建高度自动化、可配置、可扩展的企业级Spring应用!

被折叠的 条评论
为什么被折叠?



