diff --git a/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextCommonAutoConfiguration.kt b/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextCommonAutoConfiguration.kt new file mode 100644 index 0000000..ff54641 --- /dev/null +++ b/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextCommonAutoConfiguration.kt @@ -0,0 +1,69 @@ +package com.gewuyou.forgeboot.context.autoconfigure + +import com.fasterxml.jackson.databind.ObjectMapper +import com.gewuyou.forgeboot.context.api.ContextFieldContributor +import com.gewuyou.forgeboot.context.api.FieldRegistry +import com.gewuyou.forgeboot.context.impl.ContextHolder +import com.gewuyou.forgeboot.context.impl.DefaultFieldRegistry +import com.gewuyou.forgeboot.core.serialization.serializer.ValueSerializer +import com.gewuyou.forgeboot.core.serialization.serializer.impl.serializer.JacksonValueSerializer +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +/** + * Context Common 自动配置 + * + * 该配置类定义了上下文模块的基础 Bean,包括序列化器、上下文持有者、字段注册表以及多种处理器。 + * 所有 Bean 均使用 @ConditionalOnMissingBean 注解以确保仅在容器中没有其他同类型 Bean 时才创建。 + * + * @since 2025-06-24 22:09:55 + * @author gewuyou + */ +@Configuration(proxyBeanMethods = false) +class ContextCommonAutoConfiguration { + + /** + * 创建 ValueSerializer Bean,用于在缺少其他实现时提供默认的值序列化器。 + * + * 该方法定义了一个 JacksonValueSerializer 实例作为默认的 ValueSerializer 实现, + * 负责使用 Jackson 库对上下文字段值进行序列化和反序列化操作。 + * + * @param objectMapper 提供 JSON 序列化支持的 ObjectMapper 实例 + * @return 构建完成的 ValueSerializer 实例 + */ + @Bean + @ConditionalOnMissingBean + fun valueSerializer(objectMapper: ObjectMapper): ValueSerializer { + return JacksonValueSerializer(objectMapper) + } + + /** + * 创建 ContextHolder Bean,用于在缺少其他实现时提供默认的上下文持有者。 + * + * 该方法定义了一个 ContextHolder 实例作为默认的上下文管理器, + * 负责存储、传递和清理当前线程的上下文字段数据。 + * + * @param valueSerializer 提供值序列化支持的 ValueSerializer 实例 + * @return 构建完成的 ContextHolder 实例 + */ + @Bean + @ConditionalOnMissingBean + fun contextHolder(valueSerializer: ValueSerializer): ContextHolder { + return ContextHolder(valueSerializer) + } + + + /** + * 创建 FieldRegistry Bean,用于注册上下文中所有字段定义。 + * + * FieldRegistry 是上下文字段的核心注册中心,聚合所有 ContextFieldContributor 提供的字段定义。 + * + * @param contributors 提供字段定义的贡献者列表 + * @return 构建完成的 FieldRegistry 实例 + */ + @Bean + @ConditionalOnMissingBean + fun fieldRegistry(contributors: List): FieldRegistry = + DefaultFieldRegistry(contributors.flatMap { it.fields() }.toSet()) +} \ No newline at end of file diff --git a/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextFeignAutoConfiguration.kt b/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextFeignAutoConfiguration.kt new file mode 100644 index 0000000..cdc357e --- /dev/null +++ b/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextFeignAutoConfiguration.kt @@ -0,0 +1,44 @@ +package com.gewuyou.forgeboot.context.autoconfigure + +import com.gewuyou.forgeboot.context.api.FieldRegistry +import com.gewuyou.forgeboot.context.impl.ContextHolder +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +/** + * 上下文Feign自动配置类 + * + * 该配置类用于在Spring Boot应用中自动装配与上下文传播相关的Feign拦截器。 + * 当Feign库存在时,该配置会创建一个请求拦截器,用于在Feign调用过程中传播上下文字段。 + * + * @since 2025-06-24 22:17:46 + * @author gewuyou + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnClass(name = ["feign.RequestInterceptor"]) +class ContextFeignAutoConfiguration { + /** + * 创建 Feign 请求拦截器 Bean。 + * + * 该拦截器会在每次 Feign 请求发起前执行,将当前上下文中的字段值写入 HTTP 请求头, + * 以支持跨服务调用的上下文传播。 + * + * @param registry 字段注册表,用于获取需要传播的字段定义 + * @param contextHolder 上下文持有者,用于获取当前线程的上下文快照 + * @return 构建完成的 feign.RequestInterceptor 实例 + */ + @Bean + @ConditionalOnMissingBean + fun feignInterceptor(registry: FieldRegistry, contextHolder: ContextHolder) = + feign.RequestInterceptor { tpl -> + // 获取当前上下文快照 + val ctx = contextHolder.snapshot() + // 遍历所有已注册的字段定义 + registry.all().forEach { def -> + // 如果当前字段有值,则将其添加到 HTTP 请求头中 + ctx[def.key]?.let { tpl.header(def.header, it) } + } + } +} \ No newline at end of file diff --git a/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextProcessorAutoConfiguration.kt b/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextProcessorAutoConfiguration.kt new file mode 100644 index 0000000..4800785 --- /dev/null +++ b/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextProcessorAutoConfiguration.kt @@ -0,0 +1,59 @@ +package com.gewuyou.forgeboot.context.autoconfigure + +import com.gewuyou.forgeboot.context.api.FieldRegistry +import com.gewuyou.forgeboot.context.impl.processor.GeneratorProcessor +import com.gewuyou.forgeboot.context.impl.processor.HeaderProcessor +import com.gewuyou.forgeboot.context.impl.processor.MdcProcessor +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +/** + * 上下文处理器自动配置 + * + * 该配置类定义了多个上下文处理相关的 Bean,用于支持线程上下文字段的提取、生成和日志集成。 + * + * @since 2025-06-24 22:12:58 + * @author gewuyou + */ +@Configuration(proxyBeanMethods = false) +class ContextProcessorAutoConfiguration { + + /** + * 创建 HeaderProcessor Bean,用于处理请求头中的上下文字段。 + * + * HeaderProcessor 负责从请求头中提取上下文字段并注入到当前线程上下文中。 + * + * @param reg 字段注册表,用于获取需要处理的上下文字段定义 + * @return 构建完成的 HeaderProcessor 实例 + */ + @Bean("headerProcessor") + fun headerProcessor(reg: FieldRegistry): HeaderProcessor { + return HeaderProcessor(reg) + } + + /** + * 创建 GeneratorProcessor Bean,用于生成上下文字段值。 + * + * GeneratorProcessor 根据字段定义生成默认值(如 traceId、spanId 等),适用于首次进入系统的情况。 + * + * @param reg 字段注册表,用于获取需要生成值的上下文字段定义 + * @return 构建完成的 GeneratorProcessor 实例 + */ + @Bean("generatorProcessor") + fun generatorProcessor(reg: FieldRegistry): GeneratorProcessor { + return GeneratorProcessor(reg) + } + + /** + * 创建 MdcProcessor Bean,用于将上下文字段写入 MDC(Mapped Diagnostic Context)。 + * + * MdcProcessor 使得日志框架(如 Logback)可以访问当前上下文字段,便于日志追踪。 + * + * @param reg 字段注册表,用于获取需要写入 MDC 的上下文字段定义 + * @return 构建完成的 MdcProcessor 实例 + */ + @Bean("mdcProcessor") + fun mdcProcessor(reg: FieldRegistry): MdcProcessor { + return MdcProcessor(reg) + } +} \ No newline at end of file diff --git a/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextReactorAutoConfiguration.kt b/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextReactorAutoConfiguration.kt new file mode 100644 index 0000000..847e401 --- /dev/null +++ b/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextReactorAutoConfiguration.kt @@ -0,0 +1,33 @@ +package com.gewuyou.forgeboot.context.autoconfigure + +import com.gewuyou.forgeboot.context.api.FieldRegistry +import com.gewuyou.forgeboot.context.impl.processor.ReactorProcessor +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +/** + * Context Reactor 自动配置 + * + * 该配置类用于在 Spring Boot 环境中自动装配 ReactorProcessor Bean。 + * 只有在 classpath 中存在 reactor.util.context.Context 类时才会生效。 + * + * @since 2025-06-24 22:14:18 + * @author gewuyou + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnClass(name = ["reactor.util.context.Context"]) +class ContextReactorAutoConfiguration { + + /** + * 创建并配置 ReactorProcessor Bean + * + * 该方法定义了一个名为 "reactorProcessor" 的 Spring Bean, + * 用于在 Reactor 响应式流的上下文中传播和管理自定义上下文字段。 + * + * @param reg FieldRegistry 实例,用于注册和管理上下文字段 + * @return 配置完成的 ReactorProcessor 实例 + */ + @Bean("reactorProcessor") + fun reactorProcessor(reg: FieldRegistry) = ReactorProcessor(reg) +} \ No newline at end of file diff --git a/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextServletAutoConfiguration.kt b/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextServletAutoConfiguration.kt new file mode 100644 index 0000000..9dd60ef --- /dev/null +++ b/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextServletAutoConfiguration.kt @@ -0,0 +1,45 @@ +package com.gewuyou.forgeboot.context.autoconfigure + +import com.gewuyou.forgeboot.context.api.ContextProcessor +import com.gewuyou.forgeboot.context.impl.ContextHolder +import com.gewuyou.forgeboot.context.impl.filter.ContextServletFilter +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.core.Ordered +import org.springframework.core.annotation.Order + +/** + * 上下文 Servlet 自动配置类 + * + * 该配置类用于在基于 Servlet 的 Web 应用中自动装配上下文传播相关的组件。 + * 主要功能包括: + * - 在满足 Servlet 环境条件时启用配置 + * - 注册 ContextServletFilter Bean 以支持请求链中的上下文一致性维护 + * + * @since 2025-06-24 22:15:23 + * @author gewuyou + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnProperty(name = ["spring.main.web-application-type"], havingValue = "servlet", matchIfMissing = true) +@ConditionalOnClass(name = ["jakarta.servlet.Filter"]) +class ContextServletAutoConfiguration { + + /** + * 构建并注册 ContextServletFilter 实例 + * + * 此方法创建一个用于同步阻塞的 Servlet 请求链中的上下文传播过滤器。 + * 只有在容器中尚未存在相同类型的 Bean 时才会注册。 + * + * @param chain 处理器链,包含多个 ContextProcessor 实例 + * @param contextHolder 上下文持有者,用于存储和传递上下文数据 + * @return 构建完成的 ContextServletFilter 实例 + */ + @Bean + @ConditionalOnMissingBean + @Order(Ordered.HIGHEST_PRECEDENCE + 10) + fun contextServletFilter(chain: List, contextHolder: ContextHolder) = + ContextServletFilter(chain, contextHolder) +} \ No newline at end of file diff --git a/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextTaskDecoratorAutoConfiguration.kt b/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextTaskDecoratorAutoConfiguration.kt new file mode 100644 index 0000000..826b8a6 --- /dev/null +++ b/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextTaskDecoratorAutoConfiguration.kt @@ -0,0 +1,50 @@ +package com.gewuyou.forgeboot.context.autoconfigure + +import com.gewuyou.forgeboot.context.api.ContextProcessor +import com.gewuyou.forgeboot.context.impl.ContextHolder +import org.springframework.context.annotation.Bean +import org.springframework.core.task.TaskDecorator +import kotlin.collections.forEach + +/** + * Context Task Decorator 自动配置 + * + * 用于自动装配一个 TaskDecorator Bean,确保异步任务执行时能够继承和保持上下文一致性。 + * 通过注入处理器链和上下文持有者,实现上下文的捕获、传递和清理。 + * + * @since 2025-06-24 22:18:51 + * @author gewuyou + */ +class ContextTaskDecoratorAutoConfiguration { + /** + * 创建 TaskDecorator Bean,用于在异步执行中保持上下文一致性。 + * + * 通过装饰线程池任务,确保异步任务继承调用线程的上下文状态。 + * 此方法会注入所有可用的 ContextProcessor 来处理上下文注入逻辑。 + * + * @param processors 所有处理器列表,用于上下文注入操作 + * @param contextHolder 上下文持有者,用于获取和存储当前线程的上下文快照 + * @return 构建完成的 TaskDecorator 实例,用于装饰异步任务 + */ + @Bean + fun contextTaskDecorator(processors: List, contextHolder: ContextHolder) = + TaskDecorator { delegate -> + // 捕获当前线程的上下文快照,用于传递给异步任务 + val snap = contextHolder.snapshot() + Runnable { + try { + // 将快照内容重新放入当前线程的上下文持有者中 + snap.forEach(contextHolder::put) + // 调用每个处理器的 inject 方法,将上下文数据注入到目标对象中 + processors.forEach { it.inject(Unit, snap.toMutableMap()) } + // 执行被装饰的任务 + delegate.run() + } finally { + // 清理当前线程的上下文注入数据,避免内存泄漏 + processors.forEach { it.inject(Unit, mutableMapOf()) } + // 清空上下文持有者的全部数据 + contextHolder.clear() + } + } + } +} \ No newline at end of file diff --git a/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextWebClientAutoConfiguration.kt b/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextWebClientAutoConfiguration.kt new file mode 100644 index 0000000..ee989b6 --- /dev/null +++ b/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextWebClientAutoConfiguration.kt @@ -0,0 +1,47 @@ +package com.gewuyou.forgeboot.context.autoconfigure + +import com.gewuyou.forgeboot.context.api.FieldRegistry +import com.gewuyou.forgeboot.context.impl.ContextHolder +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass +import org.springframework.boot.web.reactive.function.client.WebClientCustomizer +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.web.reactive.function.client.ClientRequest + +/** + * Context Web Client 自动配置 + * + * 配置 WebClient 请求行为,自动将上下文字段注入到 HTTP 请求头中。 + * 适用于 Spring Boot 的 WebClient 请求定制场景。 + * + * @since 2025-06-24 22:20:10 + * @author gewuyou + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnClass(name = ["org.springframework.web.reactive.function.client.WebClient"]) +class ContextWebClientAutoConfiguration { + /** + * 注册 WebClientCustomizer,用于定制 WebClient 的请求行为。 + * + * 在每次请求发出前,将当前上下文字段写入 HTTP 请求头。 + * + * @param contextHolder 上下文持有者,用于获取当前线程的上下文快照 + * @param registry 字段注册器,用于获取需传递的上下文字段定义 + * @return 构建完成的 WebClientCustomizer 实例 + */ + @Bean + fun contextWebClientCustomizer(contextHolder: ContextHolder, registry: FieldRegistry) = + WebClientCustomizer { builder -> + // 添加过滤器,在请求发出前处理上下文注入逻辑 + builder.filter { req, next -> + val ctx = contextHolder.snapshot() // 获取当前上下文快照 + val mutated = ClientRequest.from(req).apply { + // 遍历所有注册字段定义,将上下文中的值注入到请求头中 + registry.all().forEach { def -> + ctx[def.key]?.let { value -> header(def.header, value) } + } + }.build() + next.exchange(mutated) // 执行修改后的请求 + } + } +} \ No newline at end of file diff --git a/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextWebFluxAutoConfiguration.kt b/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextWebFluxAutoConfiguration.kt new file mode 100644 index 0000000..ff8f01f --- /dev/null +++ b/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ContextWebFluxAutoConfiguration.kt @@ -0,0 +1,49 @@ +package com.gewuyou.forgeboot.context.autoconfigure + +import com.gewuyou.forgeboot.context.api.ContextProcessor +import com.gewuyou.forgeboot.context.impl.ContextHolder +import com.gewuyou.forgeboot.context.impl.filter.ContextWebFilter +import com.gewuyou.forgeboot.context.impl.processor.ReactorProcessor +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.core.Ordered +import org.springframework.core.annotation.Order + +/** + * Context Web Flux 自动配置 + * + * 该配置类用于在 Spring WebFlux 环境下自动装配上下文传播相关的组件。 + * 主要功能是注册 ContextWebFilter Bean,以确保请求链中上下文字段的一致性维护。 + * + * @since 2025-06-24 22:16:19 + * @author gewuyou + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnProperty(name = ["spring.main.web-application-type"], havingValue = "reactive") +@ConditionalOnClass(name = ["org.springframework.web.server.WebFilter"]) +class ContextWebFluxAutoConfiguration { + /** + * 注册 ContextWebFilter Bean,用于在 WebFlux 请求链中传播上下文字段。 + * + * 该过滤器利用 ReactorProcessor 在 WebFlux 的过滤器链中维护上下文一致性。 + * 参数 chain 提供了一组 ContextProcessor 实例,用于处理不同类型的上下文逻辑; + * reactorProcessor 是一个关键组件,负责实际的上下文传播和反应式流集成; + * contextHolder 存储了当前线程或请求的上下文数据,确保其在整个请求生命周期中可用。 + * + * @param chain 处理器链,包含多个 ContextProcessor 实例 + * @param reactorProcessor ReactorProcessor 实例,用于反应式上下文传播 + * @param contextHolder 上下文持有者,用于存储和获取当前上下文 + * @return 构建完成的 ContextWebFilter 实例 + */ + @Bean + @ConditionalOnMissingBean + @Order(Ordered.HIGHEST_PRECEDENCE + 10) + fun contextWebFilter( + chain: List, + reactorProcessor: ReactorProcessor, + contextHolder: ContextHolder + ) = ContextWebFilter(chain, reactorProcessor, contextHolder) +} \ No newline at end of file diff --git a/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ForgeContextAutoConfiguration.kt b/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ForgeContextAutoConfiguration.kt deleted file mode 100644 index e9fa1b1..0000000 --- a/forgeboot-context/forgeboot-context-autoconfigure/src/main/kotlin/com/gewuyou/forgeboot/context/autoconfigure/ForgeContextAutoConfiguration.kt +++ /dev/null @@ -1,295 +0,0 @@ -package com.gewuyou.forgeboot.context.autoconfigure - - -import com.fasterxml.jackson.databind.ObjectMapper -import com.gewuyou.forgeboot.context.api.ContextFieldContributor -import com.gewuyou.forgeboot.context.api.ContextProcessor -import com.gewuyou.forgeboot.context.api.FieldRegistry -import com.gewuyou.forgeboot.context.impl.ContextHolder -import com.gewuyou.forgeboot.context.impl.DefaultFieldRegistry -import com.gewuyou.forgeboot.context.impl.filter.ContextServletFilter -import com.gewuyou.forgeboot.context.impl.filter.ContextWebFilter -import com.gewuyou.forgeboot.context.impl.processor.GeneratorProcessor -import com.gewuyou.forgeboot.context.impl.processor.HeaderProcessor -import com.gewuyou.forgeboot.context.impl.processor.MdcProcessor -import com.gewuyou.forgeboot.context.impl.processor.ReactorProcessor -import com.gewuyou.forgeboot.core.serialization.serializer.ValueSerializer -import com.gewuyou.forgeboot.core.serialization.serializer.impl.serializer.JacksonValueSerializer -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty -import org.springframework.boot.web.reactive.function.client.WebClientCustomizer -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.core.task.TaskDecorator -import org.springframework.web.reactive.function.client.ClientRequest - -/** - * 配置类,用于自动配置上下文相关的 Bean。 - * - * 该配置类根据不同的运行时依赖和配置条件,定义了一系列的 Bean, - * 实现了上下文字段在不同场景下的传播与管理机制。 - * - * @since 2025-06-04 11:48:01 - * @author gewuyou - */ -@Configuration -class ForgeContextAutoConfiguration { - - /** - * 创建 ValueSerializer Bean,用于在缺少其他实现时提供默认的值序列化器。 - * - * 该方法定义了一个 JacksonValueSerializer 实例作为默认的 ValueSerializer 实现, - * 负责使用 Jackson 库对上下文字段值进行序列化和反序列化操作。 - * - * @param objectMapper 提供 JSON 序列化支持的 ObjectMapper 实例 - * @return 构建完成的 ValueSerializer 实例 - */ - @Bean - @ConditionalOnMissingBean - fun valueSerializer(objectMapper: ObjectMapper): ValueSerializer { - return JacksonValueSerializer(objectMapper) - } - - /** - * 创建 ContextHolder Bean,用于在缺少其他实现时提供默认的上下文持有者。 - * - * 该方法定义了一个 ContextHolder 实例作为默认的上下文管理器, - * 负责存储、传递和清理当前线程的上下文字段数据。 - * - * @param valueSerializer 提供值序列化支持的 ValueSerializer 实例 - * @return 构建完成的 ContextHolder 实例 - */ - @Bean - @ConditionalOnMissingBean - fun contextHolder(valueSerializer: ValueSerializer): ContextHolder { - return ContextHolder(valueSerializer) - } - /* ─────────────────────────────────────────────────────────────── - 0️⃣ 通用 Bean:不依赖 Web / Feign / Reactor 等外部包 - ─────────────────────────────────────────────────────────────── */ - - /** - * 创建 FieldRegistry Bean,用于注册上下文中所有字段定义。 - * - * FieldRegistry 是上下文字段的核心注册中心,聚合所有 ContextFieldContributor 提供的字段定义。 - * - * @param contributors 提供字段定义的贡献者列表 - * @return 构建完成的 FieldRegistry 实例 - */ - @Bean - @ConditionalOnMissingBean - fun fieldRegistry(contributors: List): FieldRegistry = - DefaultFieldRegistry(contributors.flatMap { it.fields() }.toSet()) - - /** - * 创建 HeaderProcessor Bean,用于处理请求头中的上下文字段。 - * - * HeaderProcessor 负责从请求头中提取上下文字段并注入到当前线程上下文中。 - * - * @param reg 字段注册表 - * @return 构建完成的 HeaderProcessor 实例 - */ - @Bean("headerProcessor") - fun headerProcessor(reg: FieldRegistry) = HeaderProcessor(reg) - - /** - * 创建 GeneratorProcessor Bean,用于生成上下文字段值。 - * - * GeneratorProcessor 根据字段定义生成默认值(如 traceId、spanId 等),适用于首次进入系统的情况。 - * - * @param reg 字段注册表 - * @return 构建完成的 GeneratorProcessor 实例 - */ - @Bean("generatorProcessor") - fun generatorProcessor(reg: FieldRegistry) = GeneratorProcessor(reg) - - /** - * 创建 MdcProcessor Bean,用于将上下文字段写入 MDC(Mapped Diagnostic Context)。 - * - * MdcProcessor 使得日志框架(如 Logback)可以访问当前上下文字段,便于日志追踪。 - * - * @param reg 字段注册表 - * @return 构建完成的 MdcProcessor 实例 - */ - @Bean("mdcProcessor") - fun mdcProcessor(reg: FieldRegistry) = MdcProcessor(reg) - - /* ─────────────────────────────────────────────────────────────── - 1️⃣ Reactor 支持(只有 classpath 有 Reactor 时才激活) - ─────────────────────────────────────────────────────────────── */ - - /** - * 配置类,提供对 Reactor 上下文传播的支持。 - */ - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(name = ["reactor.util.context.Context"]) - class ReactorSupport { - - /** - * 创建 ReactorProcessor Bean,用于在 Reactor 上下文中传播上下文字段。 - * - * ReactorProcessor 适配了 Reactor 的 Context 接口,确保上下文字段在响应式流中正确传递。 - * - * @param reg 字段注册表 - * @return 构建完成的 ReactorProcessor 实例 - */ - @Bean("reactorProcessor") - fun reactorProcessor(reg: FieldRegistry) = ReactorProcessor(reg) - } - - /* ─────────────────────────────────────────────────────────────── - 2️⃣ WebFlux 过滤器(依赖 WebFlux + Reactor) - ─────────────────────────────────────────────────────────────── */ - - /** - * 配置类,注册 WebFlux 环境下的上下文传播过滤器。 - */ - @Configuration(proxyBeanMethods = false) - @ConditionalOnProperty(name = ["spring.main.web-application-type"], havingValue = "reactive") - @ConditionalOnClass(name = ["org.springframework.web.server.WebFilter"]) - class WebFluxPart { - - /** - * 注册 ContextWebFilter Bean,用于在 WebFlux 请求链中传播上下文字段。 - * - * 该过滤器利用 ReactorProcessor 在 WebFlux 的过滤器链中维护上下文一致性。 - * - * @param chain 处理器链 - * @param reactorProcessor ReactorProcessor 实例 - * @return 构建完成的 ContextWebFilter 实例 - */ - @Bean - @ConditionalOnMissingBean - fun contextWebFilter( - chain: List, - reactorProcessor: ReactorProcessor, - contextHolder: ContextHolder - ) = ContextWebFilter(chain, reactorProcessor,contextHolder) - } - - /* ─────────────────────────────────────────────────────────────── - 3️⃣ Servlet 过滤器(依赖 Servlet API) - ─────────────────────────────────────────────────────────────── */ - - /** - * 配置类,注册 Servlet 环境下的上下文传播过滤器。 - */ - @Configuration(proxyBeanMethods = false) - @ConditionalOnProperty(name = ["spring.main.web-application-type"], havingValue = "servlet", matchIfMissing = true) - @ConditionalOnClass(name = ["jakarta.servlet.Filter"]) - class ServletPart { - - /** - * 注册 ContextServletFilter Bean,用于在 Servlet 请求链中传播上下文字段。 - * - * 该过滤器负责在同步阻塞的 Servlet 请求链中维护上下文一致性。 - * - * @param chain 处理器链 - * @return 构建完成的 ContextServletFilter 实例 - */ - @Bean - @ConditionalOnMissingBean - fun contextServletFilter(chain: List,contextHolder: ContextHolder) = - ContextServletFilter(chain,contextHolder) - } - - /* ─────────────────────────────────────────────────────────────── - 4️⃣ Feign 请求拦截器(依赖 OpenFeign) - ─────────────────────────────────────────────────────────────── */ - - /** - * 配置类,注册 Feign 客户端的请求拦截器。 - */ - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(name = ["feign.RequestInterceptor"]) - class FeignPart { - - /** - * 注册 Feign 请求拦截器,用于在 Feign 调用中传播上下文字段。 - * - * 拦截器会在每次 Feign 请求发起前,将当前上下文字段写入 HTTP 请求头。 - * - * @param registry 字段注册表 - * @param contextHolder 上下文持有者 - * @return 构建完成的 feign.RequestInterceptor 实例 - */ - @Bean - @ConditionalOnMissingBean - fun feignInterceptor(registry: FieldRegistry,contextHolder: ContextHolder) = - feign.RequestInterceptor { tpl -> - val ctx = contextHolder.snapshot() - registry.all().forEach { def -> - ctx[def.key]?.let { tpl.header(def.header, it) } - } - } - } - - /* ─────────────────────────────────────────────────────────────── - 5️⃣ 线程池 TaskDecorator(纯 Spring,安全通用) - ─────────────────────────────────────────────────────────────── */ - - /** - * 配置类,注册异步执行上下文保持支持。 - */ - @Configuration(proxyBeanMethods = false) - class TaskDecoratorPart { - - /** - * 创建 TaskDecorator Bean,用于在异步执行中保持上下文一致性。 - * - * 通过装饰线程池任务,确保异步任务继承调用线程的上下文状态。 - * - * @param processors 所有处理器列表 - * @param contextHolder 上下文持有者 - * @return 构建完成的 TaskDecorator 实例 - */ - @Bean - fun contextTaskDecorator(processors: List,contextHolder: ContextHolder) = - TaskDecorator { delegate -> - val snap = contextHolder.snapshot() - Runnable { - try { - snap.forEach(contextHolder::put) - processors.forEach { it.inject(Unit, snap.toMutableMap()) } - delegate.run() - } finally { - processors.forEach { it.inject(Unit, mutableMapOf()) } - contextHolder.clear() - } - } - } - } - - /* ─────────────────────────────────────────────────────────────── - 6️⃣ WebClient 过滤器 - ─────────────────────────────────────────────────────────────── */ - - /** - * 配置类,注册 WebClient 自定义器以支持上下文传播。 - */ - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(name = ["org.springframework.web.reactive.function.client.WebClient"]) - class WebClientPart(private val registry: FieldRegistry) { - - /** - * 注册 WebClientCustomizer,用于定制 WebClient 的请求行为。 - * - * 在每次请求发出前,将当前上下文字段写入 HTTP 请求头。 - *@param contextHolder 上下文持有者 - * @return 构建完成的 WebClientCustomizer 实例 - */ - @Bean - fun contextWebClientCustomizer(contextHolder: ContextHolder) = WebClientCustomizer { builder -> - builder.filter { req, next -> - val ctx = contextHolder.snapshot() - val mutated = ClientRequest.from(req).apply { - registry.all().forEach { def -> - ctx[def.key]?.let { value -> header(def.header, value) } - } - }.build() - next.exchange(mutated) - } - } - } -} \ No newline at end of file diff --git a/forgeboot-context/forgeboot-context-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/forgeboot-context/forgeboot-context-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 0ebbb8f..dddd0ed 100644 --- a/forgeboot-context/forgeboot-context-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/forgeboot-context/forgeboot-context-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1 +1,8 @@ -com.gewuyou.forgeboot.context.autoconfigure.ForgeContextAutoConfiguration +com.gewuyou.forgeboot.context.autoconfigure.ContextCommonAutoConfiguration +com.gewuyou.forgeboot.context.autoconfigure.ContextProcessorAutoConfiguration +com.gewuyou.forgeboot.context.autoconfigure.ContextReactorAutoConfiguration +com.gewuyou.forgeboot.context.autoconfigure.ContextServletAutoConfiguration +com.gewuyou.forgeboot.context.autoconfigure.ContextWebFluxAutoConfiguration +com.gewuyou.forgeboot.context.autoconfigure.ContextFeignAutoConfiguration +com.gewuyou.forgeboot.context.autoconfigure.ContextTaskDecoratorAutoConfiguration +com.gewuyou.forgeboot.context.autoconfigure.ContextWebClientAutoConfiguration