1 介绍

1.1 定义

01.技术概述
    a.基本定义
        Micronaut是一个现代化的、基于JVM的全栈框架,专为构建模块化、易测试的微服务和无服务器应用而设计。它由OCI团队开发,于2018年首次发布,核心特点是采用编译时依赖注入和AOP代理,避免运行时反射带来的性能开销。
    b.技术定位
        a.云原生框架
            Micronaut从设计之初就以云原生为目标,优化了启动时间、内存占用和吞吐量,特别适合容器化部署和函数计算场景。
        b.编译时处理
            通过注解处理器在编译期生成依赖注入和AOP代理代码,消除了运行时反射的性能损耗,实现了快速启动和低内存占用。
        c.多语言支持
            原生支持Java、Kotlin和Groovy三种JVM语言,开发者可以根据项目需求选择合适的编程语言。

02.核心理念
    a.编译优于反射
        a.设计思想
            Micronaut将传统运行时框架在启动时执行的工作前移至编译期,通过注解处理器生成必要的元数据和代理类,避免运行时的类扫描、反射调用和动态代理生成。
        b.性能优势
            ---
            // 传统Spring框架启动过程(运行时反射)
            // 1. 类路径扫描
            // 2. 反射读取注解
            // 3. 动态代理生成
            // 4. Bean实例化
            // 启动时间: 3-5秒,内存占用: 200MB+

            // Micronaut启动过程(编译时处理)
            // 1. 编译期生成依赖注入代码
            // 2. 编译期生成AOP代理类
            // 3. 运行时直接加载生成的类
            // 启动时间: <1秒,内存占用: 20MB+

            import io.micronaut.runtime.Micronaut;

            public class Application {
                public static void main(String[] args) {
                    // Micronaut应用启动,无需类扫描和反射
                    Micronaut.run(Application.class, args);
                }
            }
            ---
    b.响应式优先
        a.响应式编程模型
            Micronaut内置支持响应式编程,HTTP客户端和服务器默认基于Netty实现,支持Reactive Streams、RxJava、Reactor等响应式库。
        b.非阻塞IO
            ---
            // 响应式HTTP客户端示例
            import io.micronaut.http.client.annotation.Client;
            import io.micronaut.http.annotation.Get;
            import io.reactivex.Single;

            @Client("https://api.example.com")
            public interface ExternalApiClient {
                // 返回响应式类型,支持非阻塞调用
                @Get("/users/{id}")
                Single<User> getUser(Long id);
            }
            ---
    c.低内存占用
        a.优化策略
            通过编译时处理、避免反射、减少运行时元数据,Micronaut应用的内存占用远低于传统框架,特别适合容器化和函数计算场景。
        b.内存对比
            ---
            // 内存占用对比(Hello World应用)
            // Spring Boot 2.x:     堆内存 150-200MB
            // Micronaut 3.x:       堆内存 20-30MB
            // Micronaut + GraalVM: RSS内存 15-20MB

            // 容器资源配置示例
            // Docker限制:Micronaut应用可以在64MB内存限制下运行
            docker run -m 64m micronaut-app
            ---

03.技术背景
    a.诞生原因
        a.Spring框架的局限
            Spring框架虽然功能强大,但在微服务和云原生场景下暴露出启动慢、内存占用高、不适合函数计算等问题,这些问题根源于运行时反射机制。
        b.云原生需求
            容器编排、函数计算、边缘计算等新兴场景对框架提出了快速启动、低内存占用、小体积镜像的严格要求。
    b.技术演进
        a.版本历史
            Micronaut 1.0于2018年发布,随后快速迭代,3.x版本(2021年)引入了重大改进,包括更好的GraalVM支持、增强的数据访问能力和完善的云原生集成。
        b.社区生态
            ---
            // Micronaut生态组件
            // - Micronaut Data: 编译时数据访问框架
            // - Micronaut Security: 安全认证框架
            // - Micronaut Kafka: Kafka集成
            // - Micronaut gRPC: gRPC支持
            // - Micronaut AWS: AWS Lambda和服务集成

            // Maven依赖示例
            <dependency>
                <groupId>io.micronaut</groupId>
                <artifactId>micronaut-runtime</artifactId>
                <version>3.8.0</version>
            </dependency>
            ---

1.2 核心概念

01.依赖注入
    a.编译时注入原理
        a.注解处理器机制
            Micronaut使用Java注解处理器(Annotation Processor)在编译期分析代码中的依赖注入注解,生成BeanDefinition类和依赖关系元数据,运行时直接加载这些预生成的类,无需反射扫描。
        b.代码生成过程
            ---
            // 源代码:定义一个服务类
            import jakarta.inject.Singleton;

            @Singleton
            public class UserService {
                private final UserRepository repository;

                public UserService(UserRepository repository) {
                    this.repository = repository;
                }
            }

            // 编译时生成的BeanDefinition类(简化版)
            // $UserService$Definition.java
            public class $UserService$Definition
                extends AbstractInitializableBeanDefinition<UserService> {

                @Override
                protected UserService instantiate(BeanContext context) {
                    // 直接调用构造器,无需反射
                    UserRepository repo = context.getBean(UserRepository.class);
                    return new UserService(repo);
                }
            }
            ---
    b.JSR-330标准支持
        a.标准注解
            Micronaut完全支持JSR-330依赖注入标准,使用jakarta.inject包下的标准注解,如@Inject、@Singleton、@Named等,保证代码的可移植性。
        b.注解对比
            ---
            // JSR-330标准注解
            import jakarta.inject.Inject;
            import jakarta.inject.Singleton;
            import jakarta.inject.Named;

            @Singleton
            public class OrderService {
                @Inject
                @Named("primary")
                private DataSource dataSource;
            }

            // Micronaut扩展注解
            import io.micronaut.context.annotation.Primary;
            import io.micronaut.context.annotation.Requires;

            @Singleton
            @Primary  // Micronaut注解,标记为首选Bean
            @Requires(property = "datasource.enabled", value = "true")
            public class PrimaryDataSource implements DataSource {
                // 实现细节
            }
            ---

02.AOP面向切面编程
    a.编译时AOP实现
        a.代理生成机制
            Micronaut在编译期生成AOP代理类,避免了运行时动态代理的性能开销。支持方法拦截器(MethodInterceptor)和引入通知(Introduction Advice)。
        b.拦截器示例
            ---
            // 定义一个方法拦截器
            import io.micronaut.aop.MethodInterceptor;
            import io.micronaut.aop.MethodInvocationContext;
            import jakarta.inject.Singleton;

            @Singleton
            public class LoggingInterceptor implements MethodInterceptor<Object, Object> {
                @Override
                public Object intercept(MethodInvocationContext<Object, Object> context) {
                    String methodName = context.getMethodName();
                    System.out.println("Before: " + methodName);

                    Object result = context.proceed();

                    System.out.println("After: " + methodName);
                    return result;
                }
            }

            // 使用注解标记需要拦截的方法
            import io.micronaut.aop.Around;
            import java.lang.annotation.*;

            @Around  // 声明为环绕通知
            @Type(LoggingInterceptor.class)  // 指定拦截器类
            @Retention(RetentionPolicy.RUNTIME)
            @Target({ElementType.METHOD, ElementType.TYPE})
            public @interface Logged {
            }

            // 应用到业务类
            @Singleton
            public class ProductService {
                @Logged  // 该方法会被LoggingInterceptor拦截
                public Product findById(Long id) {
                    return productRepository.findById(id);
                }
            }
            ---
    b.内置AOP支持
        a.事务管理
            Micronaut提供@Transactional注解实现声明式事务管理,通过AOP拦截器自动处理事务的开启、提交和回滚。
        b.缓存抽象
            ---
            // 缓存注解示例
            import io.micronaut.cache.annotation.Cacheable;
            import io.micronaut.cache.annotation.CacheInvalidate;

            @Singleton
            public class UserService {
                // 方法结果会被缓存,缓存键为userId
                @Cacheable("users")
                public User findById(Long userId) {
                    return userRepository.findById(userId);
                }

                // 更新用户时使缓存失效
                @CacheInvalidate("users")
                public void updateUser(User user) {
                    userRepository.update(user);
                }
            }
            ---

03.HTTP服务器与客户端
    a.基于Netty的HTTP服务器
        a.非阻塞架构
            Micronaut内置的HTTP服务器基于Netty实现,采用事件驱动的非阻塞IO模型,可以高效处理大量并发连接。
        b.服务器配置
            ---
            // application.yml配置
            // micronaut:
            //   server:
            //     port: 8080
            //     netty:
            //       max-header-size: 16KB
            //       worker:
            //         threads: 8  # 工作线程数

            // 定义HTTP控制器
            import io.micronaut.http.annotation.Controller;
            import io.micronaut.http.annotation.Get;

            @Controller("/api")
            public class ApiController {
                @Get("/hello")
                public String hello() {
                    return "Hello Micronaut";
                }
            }
            ---
    b.声明式HTTP客户端
        a.客户端定义
            Micronaut提供声明式HTTP客户端,通过接口和注解定义,编译期生成客户端实现代码,支持同步、异步和响应式调用。
        b.客户端示例
            ---
            // 定义HTTP客户端接口
            import io.micronaut.http.client.annotation.Client;
            import io.micronaut.http.annotation.*;
            import io.reactivex.Single;

            @Client("https://api.github.com")
            public interface GithubClient {
                // 同步调用
                @Get("/users/{username}")
                User getUser(String username);

                // 异步调用(返回CompletableFuture)
                @Get("/repos/{owner}/{repo}")
                CompletableFuture<Repository> getRepositoryAsync(
                    String owner, String repo);

                // 响应式调用(返回Single)
                @Get("/users/{username}/repos")
                Single<List<Repository>> getUserRepos(String username);

                // POST请求
                @Post("/repos/{owner}/{repo}/issues")
                Issue createIssue(String owner, String repo, @Body IssueRequest issue);
            }

            // 注入并使用客户端
            @Singleton
            public class GithubService {
                private final GithubClient githubClient;

                public GithubService(GithubClient githubClient) {
                    this.githubClient = githubClient;
                }

                public User getUserInfo(String username) {
                    return githubClient.getUser(username);
                }
            }
            ---

04.配置管理
    a.多源配置支持
        a.配置来源
            Micronaut支持从多种来源加载配置,包括application.yml、环境变量、系统属性、配置中心等,并按优先级合并配置。
        b.配置示例
            ---
            // application.yml
            // datasource:
            //   url: jdbc:mysql://localhost:3306/mydb
            //   username: root
            //   password: secret
            //   pool:
            //     max-size: 10

            // 通过@ConfigurationProperties绑定配置
            import io.micronaut.context.annotation.ConfigurationProperties;

            @ConfigurationProperties("datasource")
            public class DataSourceConfig {
                private String url;
                private String username;
                private String password;
                private PoolConfig pool;

                // getter和setter省略

                @ConfigurationProperties("pool")
                public static class PoolConfig {
                    private int maxSize;
                    // getter和setter省略
                }
            }

            // 注入配置类
            @Singleton
            public class DatabaseService {
                private final DataSourceConfig config;

                public DatabaseService(DataSourceConfig config) {
                    this.config = config;
                    System.out.println("DB URL: " + config.getUrl());
                    System.out.println("Pool Size: " + config.getPool().getMaxSize());
                }
            }
            ---
    b.环境配置
        a.多环境支持
            Micronaut支持通过application-{env}.yml定义不同环境的配置,启动时通过micronaut.environments指定激活的环境。
        b.环境切换
            ---
            // application.yml(默认配置)
            // app:
            //   name: my-service
            //   version: 1.0

            // application-dev.yml(开发环境)
            // datasource:
            //   url: jdbc:h2:mem:devdb

            // application-prod.yml(生产环境)
            // datasource:
            //   url: jdbc:mysql://prod-server:3306/proddb

            // 启动时指定环境
            // java -Dmicronaut.environments=dev -jar app.jar
            // java -Dmicronaut.environments=prod -jar app.jar

            // 代码中获取当前环境
            import io.micronaut.context.env.Environment;

            @Singleton
            public class EnvironmentService {
                private final Environment environment;

                public EnvironmentService(Environment environment) {
                    this.environment = environment;
                }

                public void printActiveEnvironments() {
                    Set<String> activeNames = environment.getActiveNames();
                    System.out.println("Active environments: " + activeNames);
                }
            }
            ---

1.3 优缺点

01.优势
    a.启动速度快
        a.编译时优化
            通过编译时依赖注入和AOP代理生成,Micronaut消除了启动时的类扫描、反射分析和动态代理生成,启动速度比Spring Boot快5-10倍。
        b.性能测试
            ---
            // 启动时间对比测试(Hello World应用)
            // 测试环境:MacBook Pro M1, 16GB RAM, JDK 17

            // Spring Boot 2.7
            // 启动时间:2.5-3.5秒
            // 加载Bean数:150+

            // Micronaut 3.8
            // 启动时间:0.5-0.8秒
            // 加载Bean数:20+

            // 性能测试代码
            import io.micronaut.runtime.Micronaut;

            public class Application {
                public static void main(String[] args) {
                    long start = System.currentTimeMillis();
                    Micronaut.run(Application.class, args);
                    long end = System.currentTimeMillis();
                    System.out.println("启动耗时: " + (end - start) + "ms");
                }
            }
            ---
    b.内存占用低
        a.运行时内存优化
            Micronaut应用的堆内存占用通常只有Spring Boot应用的20-30%,这得益于编译时处理、避免反射和减少运行时元数据。
        b.内存监控
            ---
            // 内存占用监控代码
            import io.micronaut.scheduling.annotation.Scheduled;
            import jakarta.inject.Singleton;
            import java.lang.management.ManagementFactory;
            import java.lang.management.MemoryMXBean;

            @Singleton
            public class MemoryMonitor {
                private final MemoryMXBean memoryBean =
                    ManagementFactory.getMemoryMXBean();

                @Scheduled(fixedRate = "30s")
                public void printMemoryUsage() {
                    long heapUsed = memoryBean.getHeapMemoryUsage().getUsed() / 1024 / 1024;
                    long heapMax = memoryBean.getHeapMemoryUsage().getMax() / 1024 / 1024;
                    System.out.printf("堆内存使用: %dMB / %dMB%n", heapUsed, heapMax);
                }
            }

            // 典型内存占用(运行1小时后)
            // Spring Boot应用:堆内存 150-200MB
            // Micronaut应用:堆内存 30-50MB
            // 节省内存:70-80%
            ---
    c.GraalVM原生镜像支持
        a.原生编译优势
            Micronaut对GraalVM原生镜像提供一流支持,编译时处理的架构使得生成原生镜像更加容易,原生镜像启动时间可达毫秒级,内存占用进一步降低。
        b.原生镜像构建
            ---
            // Maven配置(pom.xml片段)
            <plugin>
                <groupId>org.graalvm.buildtools</groupId>
                <artifactId>native-maven-plugin</artifactId>
                <version>0.9.20</version>
                <configuration>
                    <imageName>micronaut-app</imageName>
                    <mainClass>com.example.Application</mainClass>
                    <buildArgs>
                        <arg>--no-fallback</arg>
                        <arg>--enable-http</arg>
                        <arg>--enable-https</arg>
                    </buildArgs>
                </configuration>
            </plugin>

            // 构建原生镜像
            // mvn clean package -Dpackaging=native-image

            // 原生镜像性能
            // 启动时间:20-50毫秒
            // RSS内存:15-25MB
            // 可执行文件大小:30-50MB
            // 适用场景:函数计算、容器化部署、边缘计算

            // Docker镜像大小对比
            // JVM应用 + OpenJDK:200-300MB
            // 原生镜像 + Alpine:50-80MB
            ---
    d.云原生设计
        a.服务发现与配置
            Micronaut内置支持Consul、Eureka等服务发现,以及多种配置中心,无需额外依赖即可实现微服务治理。
        b.分布式追踪
            ---
            // 集成Zipkin分布式追踪
            // application.yml
            // tracing:
            //   zipkin:
            //     enabled: true
            //     http:
            //       url: http://localhost:9411

            // 自动生成追踪数据,无需修改业务代码
            import io.micronaut.http.annotation.*;
            import jakarta.inject.Singleton;

            @Controller("/orders")
            public class OrderController {
                private final OrderService orderService;
                private final PaymentClient paymentClient;

                public OrderController(OrderService orderService,
                                     PaymentClient paymentClient) {
                    this.orderService = orderService;
                    this.paymentClient = paymentClient;
                }

                @Post
                public Order createOrder(@Body OrderRequest request) {
                    // 自动记录追踪信息,包括跨服务调用
                    Order order = orderService.create(request);
                    paymentClient.process(order.getId());
                    return order;
                }
            }
            ---

02.缺点
    a.生态不如Spring成熟
        a.社区规模
            Micronaut相对年轻(2018年发布),社区规模和第三方库数量远少于Spring生态,某些特定场景可能缺少现成的解决方案。
        b.学习资源
            官方文档完善,但中文资料、书籍和培训课程较少,遇到问题时可参考的案例有限。
    b.编译时间增加
        a.注解处理开销
            编译时依赖注入需要运行注解处理器,对于大型项目,首次编译和全量编译时间会明显增加。
        b.编译优化
            ---
            // Maven编译配置优化
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-compiler-plugin</artifactId>
                        <version>3.10.1</version>
                        <configuration>
                            <source>17</source>
                            <target>17</target>
                            <annotationProcessorPaths>
                                <path>
                                    <groupId>io.micronaut</groupId>
                                    <artifactId>micronaut-inject-java</artifactId>
                                    <version>3.8.0</version>
                                </path>
                            </annotationProcessorPaths>
                            <compilerArgs>
                                <arg>-Amicronaut.processing.incremental=true</arg>
                                <arg>-Amicronaut.processing.annotations=com.example.*</arg>
                            </compilerArgs>
                        </configuration>
                    </plugin>
                </plugins>
            </build>

            // 增量编译可减少重复编译时间
            // 限制注解处理范围可加快编译速度
            ---
    c.动态特性受限
        a.反射限制
            由于编译时处理的特性,Micronaut对动态反射、动态类加载的支持有限,某些依赖反射的框架可能无法集成。
        b.GraalVM限制
            原生镜像编译对反射、动态代理、JNI有严格限制,需要提前配置reflection-config.json等元数据文件。
    d.学习曲线
        a.概念差异
            对于熟悉Spring的开发者,需要理解Micronaut编译时处理的思想,转变运行时反射的开发习惯。
        b.调试复杂度
            编译时生成的代码不直观,调试时需要查看生成的BeanDefinition类,增加了问题排查的难度。

1.4 使用场景

01.微服务架构
    a.服务间通信
        a.HTTP微服务
            Micronaut的快速启动和低内存占用特别适合微服务架构,每个服务可以独立部署、快速扩缩容,降低容器编排的资源开销。
        b.服务实现示例
            ---
            // 用户服务
            import io.micronaut.http.annotation.*;
            import jakarta.inject.Singleton;

            @Controller("/users")
            public class UserController {
                private final UserService userService;

                public UserController(UserService userService) {
                    this.userService = userService;
                }

                @Get("/{id}")
                public User getUser(Long id) {
                    return userService.findById(id);
                }

                @Post
                public User createUser(@Body UserRequest request) {
                    return userService.create(request);
                }
            }

            // 订单服务调用用户服务
            import io.micronaut.http.client.annotation.Client;

            @Client("user-service")  // 服务名称,通过服务发现解析
            public interface UserClient {
                @Get("/users/{id}")
                User getUser(Long id);
            }

            @Singleton
            public class OrderService {
                private final UserClient userClient;

                public OrderService(UserClient userClient) {
                    this.userClient = userClient;
                }

                public Order createOrder(Long userId, OrderRequest request) {
                    // 跨服务调用
                    User user = userClient.getUser(userId);
                    // 创建订单逻辑
                    return new Order(user, request);
                }
            }
            ---
    b.服务注册与发现
        a.Consul集成
            Micronaut原生支持Consul服务发现,服务启动时自动注册,其他服务通过服务名称进行调用。
        b.配置示例
            ---
            // application.yml
            // consul:
            //   client:
            //     registration:
            //       enabled: true
            //     defaultZone: "${CONSUL_HOST:localhost}:${CONSUL_PORT:8500}"

            // 服务自动注册到Consul
            import io.micronaut.runtime.Micronaut;

            public class Application {
                public static void main(String[] args) {
                    // 启动时自动注册到Consul
                    Micronaut.run(Application.class, args);
                }
            }

            // 服务健康检查端点
            import io.micronaut.management.endpoint.health.HealthEndpoint;
            import io.micronaut.management.health.indicator.HealthResult;

            @Singleton
            public class CustomHealthIndicator implements HealthIndicator {
                @Override
                public Publisher<HealthResult> getResult() {
                    // 自定义健康检查逻辑
                    return Publishers.just(
                        HealthResult.builder("database").up().build()
                    );
                }
            }
            ---

02.无服务器Serverless应用
    a.AWS Lambda函数
        a.冷启动优化
            Micronaut的快速启动特性使其非常适合AWS Lambda等函数计算场景,可以将冷启动时间从数秒降低到毫秒级。
        b.Lambda函数实现
            ---
            // Maven依赖
            // <dependency>
            //     <groupId>io.micronaut.aws</groupId>
            //     <artifactId>micronaut-function-aws-api-proxy</artifactId>
            // </dependency>

            // Lambda处理器
            import io.micronaut.function.aws.proxy.MicronautLambdaHandler;

            public class LambdaHandler extends MicronautLambdaHandler {
                // Micronaut自动处理Lambda请求和响应
            }

            // HTTP控制器(与普通应用相同)
            @Controller("/api")
            public class ApiController {
                @Get("/hello")
                public String hello(@QueryValue String name) {
                    return "Hello " + name + " from Lambda!";
                }
            }

            // 性能指标
            // JVM模式冷启动:1-2秒
            // GraalVM原生镜像冷启动:50-200毫秒
            // 内存占用:128MB即可运行
            ---
    b.Azure Functions集成
        a.Azure Functions支持
            Micronaut提供Azure Functions适配器,可以将Micronaut应用部署为Azure Functions。
        b.实现示例
            ---
            // Maven依赖
            // <dependency>
            //     <groupId>io.micronaut.azure</groupId>
            //     <artifactId>micronaut-azure-function-http</artifactId>
            // </dependency>

            // Azure Functions入口
            import com.microsoft.azure.functions.*;
            import io.micronaut.azure.function.http.AzureHttpFunction;

            public class Function extends AzureHttpFunction {
                @FunctionName("hello")
                public HttpResponseMessage hello(
                    @HttpTrigger(name = "req", methods = {HttpMethod.GET},
                                 authLevel = AuthorizationLevel.ANONYMOUS)
                    HttpRequestMessage<Optional<String>> request,
                    ExecutionContext context) {
                    return super.route(request, context);
                }
            }
            ---

03.容器化与Kubernetes部署
    a.Docker容器化
        a.镜像优化
            Micronaut应用可以构建极小的Docker镜像,使用GraalVM原生镜像可以将镜像大小降低到50-80MB。
        b.Dockerfile示例
            ---
            // 多阶段构建Dockerfile
            FROM ghcr.io/graalvm/graalvm-ce:ol8-java17-22.3.0 AS builder

            WORKDIR /app
            COPY . .

            # 构建原生镜像
            RUN ./mvnw package -Dpackaging=native-image

            # 最终镜像使用Alpine Linux
            FROM alpine:3.17

            # 安装运行时依赖
            RUN apk --no-cache add ca-certificates

            WORKDIR /app
            COPY --from=builder /app/target/micronaut-app ./app

            # 暴露端口
            EXPOSE 8080

            # 启动应用
            ENTRYPOINT ["./app"]

            # 镜像大小对比
            # JVM应用 + OpenJDK:250-350MB
            # 原生镜像 + Alpine:50-80MB
            ---
    b.Kubernetes部署
        a.部署配置
            Micronaut应用的低资源占用使其可以在Kubernetes集群中高密度���署,降低基础设施成本。
        b.Kubernetes配置
            ---
            // k8s-deployment.yaml
            apiVersion: apps/v1
            kind: Deployment
            metadata:
              name: micronaut-app
            spec:
              replicas: 3
              selector:
                matchLabels:
                  app: micronaut-app
              template:
                metadata:
                  labels:
                    app: micronaut-app
                spec:
                  containers:
                  - name: app
                    image: myregistry/micronaut-app:1.0
                    ports:
                    - containerPort: 8080
                    resources:
                      requests:
                        memory: "64Mi"    # 最小64MB即可运行
                        cpu: "100m"
                      limits:
                        memory: "128Mi"
                        cpu: "500m"
                    livenessProbe:
                      httpGet:
                        path: /health
                        port: 8080
                      initialDelaySeconds: 5
                      periodSeconds: 10
                    readinessProbe:
                      httpGet:
                        path: /health/readiness
                        port: 8080
                      initialDelaySeconds: 5
                      periodSeconds: 5

            ---
            apiVersion: v1
            kind: Service
            metadata:
              name: micronaut-service
            spec:
              selector:
                app: micronaut-app
              ports:
              - protocol: TCP
                port: 80
                targetPort: 8080
              type: LoadBalancer
            ---

04.CLI工具与批处理
    a.命令行应用
        a.Picocli集成
            Micronaut集成Picocli框架,可以快速构建功能强大的命令行工具,启动速度快,适合频繁调用的脚本场景。
        b.CLI实现
            ---
            // Maven依赖
            // <dependency>
            //     <groupId>info.picocli</groupId>
            //     <artifactId>picocli</artifactId>
            // </dependency>
            // <dependency>
            //     <groupId>io.micronaut.picocli</groupId>
            //     <artifactId>micronaut-picocli</artifactId>
            // </dependency>

            import picocli.CommandLine.*;
            import io.micronaut.configuration.picocli.PicocliRunner;

            @Command(name = "data-processor",
                     description = "处理数据文件",
                     mixinStandardHelpOptions = true)
            public class DataProcessorCommand implements Runnable {
                @Option(names = {"-i", "--input"},
                        description = "输入文件路径",
                        required = true)
                private String inputFile;

                @Option(names = {"-o", "--output"},
                        description = "输出文件路径",
                        required = true)
                private String outputFile;

                @Option(names = {"-f", "--format"},
                        description = "输出格式: JSON, XML, CSV",
                        defaultValue = "JSON")
                private String format;

                public static void main(String[] args) {
                    PicocliRunner.run(DataProcessorCommand.class, args);
                }

                @Override
                public void run() {
                    System.out.println("处理文件: " + inputFile);
                    System.out.println("输出格式: " + format);
                    // 实际处理逻辑
                }
            }

            // 使用示例
            // java -jar app.jar -i data.csv -o result.json -f JSON
            // 启动时间: 200-500ms(JVM模式)
            // 启动时间: 20-50ms(GraalVM原生镜像)
            ---
    b.定时任务
        a.调度支持
            Micronaut内置定时任务调度支持,适合批处理、数据同步等场景。
        b.定时任务示例
            ---
            import io.micronaut.scheduling.annotation.Scheduled;
            import jakarta.inject.Singleton;

            @Singleton
            public class DataSyncJob {
                private final DataService dataService;

                public DataSyncJob(DataService dataService) {
                    this.dataService = dataService;
                }

                // 每天凌晨2点执行
                @Scheduled(cron = "0 0 2 * * ?")
                public void syncData() {
                    System.out.println("开始数据同步...");
                    dataService.syncFromRemote();
                    System.out.println("数据同步完成");
                }

                // 每30秒执行一次
                @Scheduled(fixedRate = "30s")
                public void healthCheck() {
                    dataService.checkHealth();
                }

                // 初始延迟10秒,之后每1分钟执行
                @Scheduled(initialDelay = "10s", fixedDelay = "1m")
                public void cleanupCache() {
                    dataService.clearExpiredCache();
                }
            }
            ---

1.5 架构原理

01.编译时处理架构
    a.注解处理器流程
        a.编译期扫描
            Micronaut使用Java标准的注解处理器API(javax.annotation.processing),在编译期扫描源代码中的注解,生成元数据和辅助类。
        b.处理流程图
            ---
            // 编译时处理流程
            // 1. javac编译器启动
            // 2. 加载Micronaut注解处理器
            //    - BeanDefinitionInjectProcessor(处理依赖注入)
            //    - TypeElementVisitorProcessor(处理AOP)
            //    - ConfigurationMetadataProcessor(处理配置)
            // 3. 遍历源代码中的注解
            // 4. 生成BeanDefinition类
            // 5. 生成AOP代理类
            // 6. 生成配置元数据
            // 7. 输出到target/classes目录

            // 注解处理器配置(Maven)
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>io.micronaut</groupId>
                            <artifactId>micronaut-inject-java</artifactId>
                        </path>
                        <path>
                            <groupId>io.micronaut</groupId>
                            <artifactId>micronaut-validation</artifactId>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
            ---
    b.BeanDefinition生成
        a.Bean元数据
            编译时为每个Bean生成一个BeanDefinition类,包含Bean的类型、作用域、依赖关系、生命周期回调等信息。
        b.生成代码示例
            ---
            // 源代码
            import jakarta.inject.Singleton;

            @Singleton
            public class EmailService {
                private final EmailConfig config;
                private final SmtpClient smtpClient;

                public EmailService(EmailConfig config, SmtpClient smtpClient) {
                    this.config = config;
                    this.smtpClient = smtpClient;
                }

                public void sendEmail(String to, String subject, String body) {
                    // 发送邮件逻辑
                }
            }

            // 编译后生成的BeanDefinition类(简化版)
            // $EmailService$Definition.java
            @Generated
            public class $EmailService$Definition
                extends AbstractInitializableBeanDefinition<EmailService>
                implements BeanFactory<EmailService> {

                // Bean的类型
                @Override
                public Class<EmailService> getBeanType() {
                    return EmailService.class;
                }

                // Bean的作用域
                @Override
                public Optional<Class<? extends Annotation>> getScope() {
                    return Optional.of(Singleton.class);
                }

                // 实例化Bean
                @Override
                public EmailService build(BeanResolutionContext context,
                                        BeanContext beanContext,
                                        BeanDefinition<EmailService> definition) {
                    // 解析依赖
                    EmailConfig config = (EmailConfig) beanContext
                        .getBean(EmailConfig.class);
                    SmtpClient smtpClient = (SmtpClient) beanContext
                        .getBean(SmtpClient.class);

                    // 直接调用构造器,无需反射
                    return new EmailService(config, smtpClient);
                }
            }
            ---

02.应用上下文初始化
    a.BeanContext加载
        a.上下文启动流程
            应用启动时,BeanContext加载所有编译期生成的BeanDefinition类,构建依赖关系图,按拓扑顺序实例化Bean。
        b.启动代码
            ---
            // Micronaut应用启动
            import io.micronaut.context.ApplicationContext;
            import io.micronaut.runtime.Micronaut;

            public class Application {
                public static void main(String[] args) {
                    // 启动应用上下文
                    ApplicationContext context = Micronaut.run(Application.class, args);

                    // 获取Bean实例
                    EmailService emailService = context.getBean(EmailService.class);
                    emailService.sendEmail("[email protected]", "Test", "Hello");

                    // 关闭上下文
                    context.close();
                }
            }

            // 内部执行流程
            // 1. 加载配置文件(application.yml)
            // 2. 扫描并加载所有BeanDefinition类
            // 3. 解析Bean依赖关系
            // 4. 按依赖顺序实例化Bean
            // 5. 执行Bean的@PostConstruct方法
            // 6. 发布ApplicationStartedEvent事件
            ---
    b.Bean生命周期
        a.生命周期回调
            Micronaut支持JSR-250标准的@PostConstruct和@PreDestroy注解,以及Micronaut特有的生命周期接口。
        b.生命周期示例
            ---
            import jakarta.inject.Singleton;
            import jakarta.annotation.PostConstruct;
            import jakarta.annotation.PreDestroy;
            import io.micronaut.context.event.ApplicationEventListener;
            import io.micronaut.context.event.StartupEvent;

            @Singleton
            public class DatabaseService implements
                ApplicationEventListener<StartupEvent> {

                private Connection connection;

                // 构造器注入
                public DatabaseService(DataSourceConfig config) {
                    System.out.println("1. 构造器执行");
                }

                // Bean初始化后执行
                @PostConstruct
                public void init() {
                    System.out.println("2. @PostConstruct执行");
                    connection = createConnection();
                }

                // 应用启动完成后执行
                @Override
                public void onApplicationEvent(StartupEvent event) {
                    System.out.println("3. StartupEvent触发");
                    // 执行启动后的初始化任务
                }

                // Bean销毁前执行
                @PreDestroy
                public void cleanup() {
                    System.out.println("4. @PreDestroy执行");
                    if (connection != null) {
                        connection.close();
                    }
                }

                private Connection createConnection() {
                    // 创建数据库连接
                    return null;
                }
            }
            ---

03.AOP代理实现
    a.编译时代理生成
        a.子类代理机制
            Micronaut在编译期为需要AOP的类生成子类代理,代理类重写被拦截的方法,插入拦截器调用逻辑。
        b.代理生成示例
            ---
            // 源代码:定义拦截器
            import io.micronaut.aop.MethodInterceptor;
            import io.micronaut.aop.MethodInvocationContext;

            @Singleton
            public class TimingInterceptor implements MethodInterceptor<Object, Object> {
                @Override
                public Object intercept(MethodInvocationContext<Object, Object> context) {
                    long start = System.nanoTime();
                    Object result = context.proceed();
                    long duration = System.nanoTime() - start;
                    System.out.println(context.getMethodName() + " 耗时: " +
                                     duration / 1_000_000 + "ms");
                    return result;
                }
            }

            // 定义拦截注解
            import io.micronaut.aop.Around;
            import java.lang.annotation.*;

            @Around
            @Type(TimingInterceptor.class)
            @Retention(RetentionPolicy.RUNTIME)
            public @interface Timed {
            }

            // 应用到服务类
            @Singleton
            public class ProductService {
                @Timed
                public Product findById(Long id) {
                    // 实际业务逻辑
                    return new Product(id, "Product " + id);
                }
            }

            // 编译后生成的代理类(简化版)
            // $ProductService$Intercepted.java
            @Generated
            public class $ProductService$Intercepted extends ProductService {
                private final ExecutableMethod<ProductService, Product> findByIdMethod;
                private final Interceptor<Product> timingInterceptor;

                @Override
                public Product findById(Long id) {
                    // 构建拦截器链
                    MethodInvocationContext<ProductService, Product> context =
                        new MethodInvocationContext<>(this, findByIdMethod,
                                                     new Object[]{id});

                    // 执行拦截器
                    return timingInterceptor.intercept(context);
                }
            }
            ---
    b.拦截器链执行
        a.拦截器顺序
            多个拦截器可以应用到同一个方法,Micronaut按照定义顺序构建拦截器链,依次执行。
        b.拦截器链示例
            ---
            // 定义多个拦截器
            @Around
            @Type(LoggingInterceptor.class)
            @Retention(RetentionPolicy.RUNTIME)
            public @interface Logged {
            }

            @Around
            @Type(CachingInterceptor.class)
            @Retention(RetentionPolicy.RUNTIME)
            public @interface Cached {
            }

            @Around
            @Type(TransactionalInterceptor.class)
            @Retention(RetentionPolicy.RUNTIME)
            public @interface Transactional {
            }

            // 应用多个拦截器
            @Singleton
            public class OrderService {
                @Logged         // 拦截器1:日志记录
                @Cached         // 拦截器2:缓存
                @Transactional  // 拦截器3:事务
                public Order findById(Long id) {
                    return orderRepository.findById(id);
                }
            }

            // 执行顺序
            // 1. LoggingInterceptor.before()
            // 2. CachingInterceptor.before()
            // 3. TransactionalInterceptor.before()
            // 4. 实际方法执行
            // 5. TransactionalInterceptor.after()
            // 6. CachingInterceptor.after()
            // 7. LoggingInterceptor.after()
            ---

04.模块化设计
    a.模块化架构
        a.核心模块
            Micronaut采用模块化设计,核心功能拆分为独立模块,应用可以按需引入依赖,减少不必要的代码。
        b.模块列表
            ---
            // 核心模块
            // micronaut-core:           核心依赖注入和AOP
            // micronaut-runtime:        应用运行时支持
            // micronaut-http:           HTTP服务器和客户端
            // micronaut-inject:         编译时依赖注入
            // micronaut-aop:            AOP支持

            // 数据访问模块
            // micronaut-data-jdbc:      JDBC支持
            // micronaut-data-jpa:       JPA支持
            // micronaut-data-r2dbc:     R2DBC响应式数据访问

            // 消息模块
            // micronaut-kafka:          Kafka集成
            // micronaut-rabbitmq:       RabbitMQ集成
            // micronaut-nats:           NATS集成

            // 云原生模块
            // micronaut-discovery-client: 服务发现客户端
            // micronaut-tracing:        分布式追踪
            // micronaut-metrics:        指标监控

            // Maven依赖示例(最小化应用)
            <dependencies>
                <dependency>
                    <groupId>io.micronaut</groupId>
                    <artifactId>micronaut-runtime</artifactId>
                </dependency>
                <dependency>
                    <groupId>io.micronaut</groupId>
                    <artifactId>micronaut-http-server-netty</artifactId>
                </dependency>
            </dependencies>
            ---
    b.扩展机制
        a.SPI机制
            Micronaut使用Java SPI(Service Provider Interface)机制实现插件式扩展,第三方库可以通过SPI注册自定义组件。
        b.自定义扩展
            ---
            // 定义扩展接口
            package io.micronaut.inject;

            public interface BeanDefinitionRegistry {
                void registerBeanDefinition(BeanDefinition<?> definition);
            }

            // 实现扩展
            package com.example.extension;

            public class CustomBeanRegistry implements BeanDefinitionRegistry {
                @Override
                public void registerBeanDefinition(BeanDefinition<?> definition) {
                    // 自定义Bean注册逻辑
                }
            }

            // SPI配置文件
            // src/main/resources/META-INF/services/io.micronaut.inject.BeanDefinitionRegistry
            // com.example.extension.CustomBeanRegistry

            // Micronaut启动时自动加载扩展
            ---

1.6 依赖注入特性

01.编译时依赖注入
    a.零反射实现
        a.编译期代码生成
            Micronaut在编译期生成所有依赖注入相关代码,运行时不需要通过反射扫描类路径、读取注解或动态创建代理对象,实现了真正的零反射依赖注入。
        b.性能对比
            ---
            // Spring Framework依赖注入(运行时反射)
            // 1. 启动时扫描类路径
            // 2. 使用反射读取@Component、@Service等注解
            // 3. 使用反射调用构造器创建Bean
            // 4. 使用反射设置字段值
            // 启动开销:2-5秒,内存开销:150-300MB

            // Micronaut依赖注入(编译时生成)
            // 1. 编译期生成BeanDefinition类
            // 2. 运行时直接加载BeanDefinition
            // 3. 直接调用构造器(无反射)
            // 4. 直接设置字段值(无反射)
            // 启动开销:0.5-1秒,内存开销:20-50MB

            // 示例:编译时生成的代码
            @Generated
            public class $UserService$Definition
                extends AbstractBeanDefinition<UserService> {

                @Override
                public UserService build(BeanContext context) {
                    // 直接调用构造器,无需反射
                    UserRepository repo = context.getBean(UserRepository.class);
                    return new UserService(repo);
                }
            }
            ---
    b.类型安全
        a.编译期类型检查
            由于依赖关系在编译期确定,编译器可以提前发现类型不匹配、循环依赖等问题,避免运行时错误。
        b.类型安全示例
            ---
            // 定义服务接口和实现
            public interface NotificationService {
                void send(String message);
            }

            @Singleton
            public class EmailNotificationService implements NotificationService {
                @Override
                public void send(String message) {
                    System.out.println("Email: " + message);
                }
            }

            @Singleton
            public class SmsNotificationService implements NotificationService {
                @Override
                public void send(String message) {
                    System.out.println("SMS: " + message);
                }
            }

            // 注入时指定类型
            @Singleton
            public class OrderService {
                private final NotificationService emailService;
                private final NotificationService smsService;

                public OrderService(
                    @Named("emailNotificationService") NotificationService emailService,
                    @Named("smsNotificationService") NotificationService smsService) {
                    this.emailService = emailService;
                    this.smsService = smsService;
                }

                public void placeOrder(Order order) {
                    emailService.send("订单已创建: " + order.getId());
                    smsService.send("订单已创建: " + order.getId());
                }
            }

            // 编译期会检查:
            // 1. NotificationService类型是否存在
            // 2. emailNotificationService和smsNotificationService是否存在
            // 3. 类型是否匹配
            // 如有错误,编译失败,避免运行时问题
            ---

02.注入方式
    a.构造器注入
        a.推荐方式
            构造器注入是Micronaut推荐的注入方式,保证了Bean的不可变性,所有依赖在对象创建时就已确定。
        b.构造器注入示例
            ---
            import jakarta.inject.Singleton;

            @Singleton
            public class PaymentService {
                private final PaymentGateway gateway;
                private final PaymentValidator validator;
                private final AuditLogger logger;

                // 构造器注入(@Inject可选,单构造器时自动注入)
                public PaymentService(PaymentGateway gateway,
                                    PaymentValidator validator,
                                    AuditLogger logger) {
                    this.gateway = gateway;
                    this.validator = validator;
                    this.logger = logger;
                }

                public PaymentResult processPayment(PaymentRequest request) {
                    logger.log("开始支付: " + request.getAmount());
                    if (!validator.validate(request)) {
                        return PaymentResult.invalid();
                    }
                    return gateway.charge(request);
                }
            }

            // 优点:
            // 1. 依赖明确,一目了然
            // 2. 字段可以声明为final,保证不可变
            // 3. 便于单元测试,直接new对象传入mock依赖
            // 4. 编译器可以检查依赖完整性
            ---
    b.字段注入
        a.字段注入语法
            Micronaut支持通过@Inject注解直接注入字段,但不推荐使用,因为会破坏封装性,且不利于测试。
        b.字段注入示例
            ---
            import jakarta.inject.Inject;
            import jakarta.inject.Singleton;

            @Singleton
            public class ReportService {
                // 字段注入
                @Inject
                private ReportGenerator generator;

                @Inject
                private DataSource dataSource;

                public Report generate(String type) {
                    return generator.generate(dataSource, type);
                }
            }

            // 缺点:
            // 1. 字段不能声明为final
            // 2. 依赖不明确,需要查看字段定义
            // 3. 单元测试困难,无法直接new对象
            // 4. 可能出现NullPointerException
            ---
    c.方法注入
        a.Setter注入
            通过@Inject标记setter方法实现注入,适合可选依赖或需要重新配置的场景。
        b.方法注入示例
            ---
            import jakarta.inject.Singleton;
            import jakarta.inject.Inject;

            @Singleton
            public class CacheService {
                private final CacheStore primaryStore;
                private CacheStore secondaryStore;  // 可选依赖

                public CacheService(CacheStore primaryStore) {
                    this.primaryStore = primaryStore;
                }

                // 方法注入(可选依赖)
                @Inject
                public void setSecondaryStore(
                    @jakarta.annotation.Nullable CacheStore secondaryStore) {
                    this.secondaryStore = secondaryStore;
                }

                public void put(String key, Object value) {
                    primaryStore.put(key, value);
                    if (secondaryStore != null) {
                        secondaryStore.put(key, value);  // 双写
                    }
                }
            }
            ---

03.作用域管理
    a.Singleton单例
        a.单例作用域
            @Singleton注解标记的Bean在整个应用生命周期内只创建一次,所有注入点共享同一个实例。
        b.单例示例
            ---
            import jakarta.inject.Singleton;
            import java.util.concurrent.atomic.AtomicLong;

            @Singleton
            public class RequestCounter {
                private final AtomicLong counter = new AtomicLong(0);

                public long increment() {
                    return counter.incrementAndGet();
                }

                public long getCount() {
                    return counter.get();
                }
            }

            // 任何地方注入的都是同一个实例
            @Controller("/api")
            public class ApiController {
                private final RequestCounter counter;

                public ApiController(RequestCounter counter) {
                    this.counter = counter;
                }

                @Get("/count")
                public long getRequestCount() {
                    return counter.getCount();
                }
            }

            @Controller("/admin")
            public class AdminController {
                private final RequestCounter counter;  // 同一个实例

                public AdminController(RequestCounter counter) {
                    this.counter = counter;
                }
            }
            ---
    b.Prototype原型
        a.原型作用域
            @Prototype注解标记的Bean每次注入时都会创建新实例,适合有状态的对象。
        b.原型示例
            ---
            import io.micronaut.context.annotation.Prototype;

            @Prototype
            public class OrderProcessor {
                private Order currentOrder;
                private ProcessingState state;

                public void process(Order order) {
                    this.currentOrder = order;
                    this.state = ProcessingState.PROCESSING;
                    // 处理订单逻辑
                }

                public ProcessingState getState() {
                    return state;
                }
            }

            // 每次注入都创建新实例
            @Singleton
            public class OrderService {
                private final BeanContext beanContext;

                public OrderService(BeanContext beanContext) {
                    this.beanContext = beanContext;
                }

                public void handleOrder(Order order) {
                    // 每次获取新实例
                    OrderProcessor processor =
                        beanContext.getBean(OrderProcessor.class);
                    processor.process(order);
                }
            }
            ---
    c.RequestScope请求作用域
        a.请求作用域
            @RequestScope注解标记的Bean在每个HTTP请求范围内是单例,请求结束后销毁。
        b.请求作用域示例
            ---
            import io.micronaut.runtime.http.scope.RequestScope;

            @RequestScope
            public class RequestContext {
                private String requestId;
                private String userId;
                private long startTime;

                public RequestContext() {
                    this.requestId = UUID.randomUUID().toString();
                    this.startTime = System.currentTimeMillis();
                }

                public String getRequestId() {
                    return requestId;
                }

                public void setUserId(String userId) {
                    this.userId = userId;
                }

                public long getElapsedTime() {
                    return System.currentTimeMillis() - startTime;
                }
            }

            // 在同一请求中共享RequestContext
            @Controller("/api")
            public class UserController {
                private final RequestContext context;

                public UserController(RequestContext context) {
                    this.context = context;
                }

                @Get("/user")
                public User getUser() {
                    System.out.println("Request ID: " + context.getRequestId());
                    return userService.findById(context.getUserId());
                }
            }
            ---

04.条件化Bean
    a.条件注入
        a.@Requires注解
            Micronaut提供@Requires注解实现条件化Bean注册,根据配置、环境、类路径等条件决定是否创建Bean。
        b.条件注入示例
            ---
            import io.micronaut.context.annotation.Requires;
            import jakarta.inject.Singleton;

            // 仅当配置属性存在且为true时创建
            @Singleton
            @Requires(property = "redis.enabled", value = "true")
            public class RedisCacheService implements CacheService {
                @Override
                public void put(String key, Object value) {
                    // Redis缓存实现
                }
            }

            // 仅当Redis不启用时创建
            @Singleton
            @Requires(property = "redis.enabled", value = "false", defaultValue = "false")
            public class InMemoryCacheService implements CacheService {
                @Override
                public void put(String key, Object value) {
                    // 内存缓存实现
                }
            }

            // 仅当类路径存在指定类时创建
            @Singleton
            @Requires(classes = com.mysql.cj.jdbc.Driver.class)
            public class MySQLDataSource implements DataSource {
                // MySQL数据源实现
            }

            // 仅在特定环境下创建
            @Singleton
            @Requires(env = "dev")
            public class MockPaymentGateway implements PaymentGateway {
                @Override
                public PaymentResult charge(PaymentRequest request) {
                    return PaymentResult.success();  // Mock实现
                }
            }
            ---
    b.Primary与Replaces
        a.Primary首选Bean
            @Primary注解标记首选Bean,当有多个同类型Bean时优先注入标记为Primary的。
        b.Primary示例
            ---
            import io.micronaut.context.annotation.Primary;

            public interface MessageSender {
                void send(String message);
            }

            @Singleton
            @Primary  // 标记为首选
            public class EmailSender implements MessageSender {
                @Override
                public void send(String message) {
                    System.out.println("Email: " + message);
                }
            }

            @Singleton
            public class SmsSender implements MessageSender {
                @Override
                public void send(String message) {
                    System.out.println("SMS: " + message);
                }
            }

            // 不指定名称时注入Primary Bean
            @Singleton
            public class NotificationService {
                private final MessageSender sender;  // 注入EmailSender

                public NotificationService(MessageSender sender) {
                    this.sender = sender;
                }
            }

            // Replaces注解替换Bean定义
            @Singleton
            @Replaces(EmailSender.class)  // 替换EmailSender
            public class MockEmailSender implements MessageSender {
                @Override
                public void send(String message) {
                    System.out.println("Mock Email: " + message);
                }
            }
            ---

1.7 编译时优化

01.性能优化策略
    a.消除反射开销
        a.反射性能损耗
            Java反射机制虽然灵活,但存在显著的性能开销,包括类型检查、安全检查、参数装箱拆箱等,Micronaut通过编译时代码生成完全避免了这些开销。
        b.性能对比测试
            ---
            // 性能测试代码
            import org.openjdk.jmh.annotations.*;
            import java.util.concurrent.TimeUnit;

            @BenchmarkMode(Mode.AverageTime)
            @OutputTimeUnit(TimeUnit.NANOSECONDS)
            @Warmup(iterations = 5, time = 1)
            @Measurement(iterations = 10, time = 1)
            @Fork(1)
            @State(Scope.Benchmark)
            public class InjectionBenchmark {

                // 反射方式创建对象
                @Benchmark
                public Object reflectionInjection() throws Exception {
                    Class<?> clazz = UserService.class;
                    Constructor<?> constructor = clazz.getConstructor(UserRepository.class);
                    UserRepository repo = new UserRepositoryImpl();
                    return constructor.newInstance(repo);
                }

                // 直接调用构造器
                @Benchmark
                public Object directInjection() {
                    UserRepository repo = new UserRepositoryImpl();
                    return new UserService(repo);
                }

                // Micronaut方式(编译时生成)
                @Benchmark
                public Object micronautInjection() {
                    BeanContext context = BeanContext.run();
                    return context.getBean(UserService.class);
                }
            }

            // 测试结果(纳秒级)
            // reflectionInjection:   5000-8000 ns/op
            // directInjection:       10-20 ns/op
            // micronautInjection:    15-30 ns/op
            // Micronaut性能接近直接调用,比反射快200-400倍
            ---
    b.启动时间优化
        a.启动流程简化
            Micronaut启动时无需扫描类路径、解析注解、构建依赖图,所有元数据在编译期已生成,启动流程大幅简化。
        b.启动时间分析
            ---
            // 启动时间监控
            import io.micronaut.context.event.ApplicationEventListener;
            import io.micronaut.context.event.StartupEvent;
            import io.micronaut.runtime.event.ApplicationStartupEvent;
            import jakarta.inject.Singleton;

            @Singleton
            public class StartupTimer implements
                ApplicationEventListener<ApplicationStartupEvent> {

                private long startTime;

                public StartupTimer() {
                    this.startTime = System.currentTimeMillis();
                }

                @Override
                public void onApplicationEvent(ApplicationStartupEvent event) {
                    long elapsed = System.currentTimeMillis() - startTime;
                    System.out.println("应用启动耗时: " + elapsed + "ms");

                    // 打印启动阶段耗时
                    ApplicationContext context = event.getSource();
                    System.out.println("Bean数量: " + context.getBeanDefinitions().size());
                }
            }

            // 启动时间对比(50个Bean的应用)
            // Spring Boot:      2000-3000ms
            // Micronaut JVM:    500-800ms
            // Micronaut Native: 20-50ms
            ---

02.编译时代码生成
    a.BeanIntrospection
        a.内省机制
            Micronaut提供编译时Bean内省(BeanIntrospection),无需反射即可读写Bean属性,适用于序列化、验证等场景。
        b.内省示例
            ---
            import io.micronaut.core.annotation.Introspected;

            // 标记为可内省
            @Introspected
            public class User {
                private Long id;
                private String username;
                private String email;

                // getter和setter
                public Long getId() { return id; }
                public void setId(Long id) { this.id = id; }

                public String getUsername() { return username; }
                public void setUsername(String username) { this.username = username; }

                public String getEmail() { return email; }
                public void setEmail(String email) { this.email = email; }
            }

            // 编译时生成$User$Introspection类
            // 使用内省API操作Bean
            import io.micronaut.core.beans.BeanIntrospection;
            import io.micronaut.core.beans.BeanProperty;

            public class IntrospectionExample {
                public static void main(String[] args) {
                    // 获取内省信息(无反射)
                    BeanIntrospection<User> introspection =
                        BeanIntrospection.getIntrospection(User.class);

                    // 创建实例(无反射)
                    User user = introspection.instantiate();

                    // 获取属性(无反射)
                    BeanProperty<User, String> usernameProperty =
                        introspection.getRequiredProperty("username", String.class);

                    // 设置属性值(无反射)
                    usernameProperty.set(user, "john_doe");

                    // 获取属性值(无反射)
                    String username = usernameProperty.get(user);
                    System.out.println("Username: " + username);

                    // 遍历所有属性
                    introspection.getBeanProperties().forEach(property -> {
                        System.out.println(property.getName() + ": " +
                                         property.get(user));
                    });
                }
            }
            ---
    b.配置属性绑定
        a.编译时绑定
            @ConfigurationProperties注解标记的类在编译期生成配置绑定代码,运行时直接加载配置值,无需反射。
        b.配置绑定示例
            ---
            import io.micronaut.context.annotation.ConfigurationProperties;
            import io.micronaut.core.annotation.Nullable;
            import jakarta.validation.constraints.*;

            @ConfigurationProperties("database")
            public class DatabaseConfig {
                @NotBlank
                private String url;

                @NotBlank
                private String username;

                @NotBlank
                private String password;

                @Min(1)
                @Max(100)
                private int poolSize = 10;

                @Nullable
                private Duration connectionTimeout;

                // getter和setter省略
            }

            // application.yml
            // database:
            //   url: jdbc:mysql://localhost:3306/mydb
            //   username: root
            //   password: secret
            //   pool-size: 20
            //   connection-timeout: 30s

            // 编译时生成$DatabaseConfig$Definition类
            // 包含配置路径映射、类型转换、验证规则
            @Generated
            public class $DatabaseConfig$Definition {
                public void inject(BeanContext context, DatabaseConfig bean) {
                    // 编译时生成的配置注入代码
                    Environment env = context.getEnvironment();
                    bean.setUrl(env.getProperty("database.url", String.class).get());
                    bean.setUsername(env.getProperty("database.username", String.class).get());
                    bean.setPassword(env.getProperty("database.password", String.class).get());
                    bean.setPoolSize(env.getProperty("database.pool-size", Integer.class).orElse(10));
                    bean.setConnectionTimeout(
                        env.getProperty("database.connection-timeout", Duration.class).orElse(null));
                }
            }
            ---

03.元数据生成
    a.注解元数据
        a.元数据提取
            Micronaut在编译期提取注解信息,生成AnnotationMetadata,运行时直接读取,避免反射解析注解。
        b.元数据使用
            ---
            import io.micronaut.core.annotation.AnnotationMetadata;
            import io.micronaut.inject.BeanDefinition;

            @Singleton
            public class MetadataInspector {
                private final BeanContext beanContext;

                public MetadataInspector(BeanContext beanContext) {
                    this.beanContext = beanContext;
                }

                public void inspectBean(Class<?> beanClass) {
                    // 获取Bean定义(编译时生成)
                    BeanDefinition<?> definition =
                        beanContext.getBeanDefinition(beanClass);

                    // 获取注解元数据(编译时提取)
                    AnnotationMetadata metadata = definition.getAnnotationMetadata();

                    // 检查注解(无反射)
                    if (metadata.hasAnnotation(Controller.class)) {
                        String value = metadata.stringValue(Controller.class).orElse("/");
                        System.out.println("Controller路径: " + value);
                    }

                    // 获取所有注解
                    metadata.getAnnotationNames().forEach(annotation -> {
                        System.out.println("注解: " + annotation);
                    });
                }
            }
            ---
    b.类型元数据
        a.泛型信息保留
            Micronaut在编译期保留完整的泛型类型信息,运行时可以准确获取泛型参数类型。
        b.泛型处理示例
            ---
            import io.micronaut.core.type.Argument;
            import io.micronaut.http.client.HttpClient;
            import io.micronaut.http.client.annotation.Client;

            @Singleton
            public class GenericClient {
                @Client("https://api.example.com")
                private HttpClient httpClient;

                // 泛型方法
                public <T> T get(String path, Class<T> responseType) {
                    // Micronaut保留了泛型类型信息
                    return httpClient.toBlocking().retrieve(path, responseType);
                }

                // 复杂泛型类型
                public <T> List<T> getList(String path, Class<T> elementType) {
                    // 构造List<T>类型
                    Argument<List<T>> argument =
                        Argument.listOf(elementType);

                    return httpClient.toBlocking().retrieve(path, argument);
                }
            }

            // 使用示例
            @Singleton
            public class UserService {
                private final GenericClient client;

                public UserService(GenericClient client) {
                    this.client = client;
                }

                public User getUser(Long id) {
                    // 泛型类型精确匹配
                    return client.get("/users/" + id, User.class);
                }

                public List<User> getAllUsers() {
                    // 泛型集合类型精确匹配
                    return client.getList("/users", User.class);
                }
            }
            ---

04.构建时优化选项
    a.增量编译
        a.增量编译支持
            Micronaut支持增量编译,仅重新处理修改的源文件,大幅减少开发时的编译时间。
        b.增量编译配置
            ---
            // Maven配置
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                    <compilerArgs>
                        <!-- 启用增量编译 -->
                        <arg>-Amicronaut.processing.incremental=true</arg>
                        <!-- 启用增量隔离模式 -->
                        <arg>-Amicronaut.processing.incremental.isolating=true</arg>
                    </compilerArgs>
                </configuration>
            </plugin>

            // Gradle配置
            tasks.withType(JavaCompile) {
                options.fork = true
                options.forkOptions.jvmArgs << '-Dmicronaut.processing.incremental=true'
                options.compilerArgs << '-Amicronaut.processing.incremental=true'
            }

            // 增量编译效果
            // 首次编译:30-60秒
            // 修改单个文件后编译:2-5秒
            // 提升:85-90%
            ---
    b.注解处理器优化
        a.处理范围限制
            可以限制注解处理器的扫描范围,仅处理特定包下的类,加快编译速度。
        b.范围限制配置
            ---
            // Maven配置
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <compilerArgs>
                        <!-- 限制处理范围到com.example包 -->
                        <arg>-Amicronaut.processing.annotations=com.example.*</arg>
                        <!-- 排除测试包 -->
                        <arg>-Amicronaut.processing.exclude=com.example.test.*</arg>
                    </compilerArgs>
                </configuration>
            </plugin>

            // 效果
            // 扫描范围缩小:编译时间减少20-40%
            // 生成代码减少:应用体积减小10-20%
            ---
    c.编译时验证
        a.循环依赖检测
            Micronaut在编译期检测Bean之间的循环依赖,提前发现问题,避免运行时错误。
        b.验证示例
            ---
            // 循环依赖示例
            @Singleton
            public class ServiceA {
                private final ServiceB serviceB;

                public ServiceA(ServiceB serviceB) {  // 依赖ServiceB
                    this.serviceB = serviceB;
                }
            }

            @Singleton
            public class ServiceB {
                private final ServiceA serviceA;

                public ServiceB(ServiceA serviceA) {  // 依赖ServiceA
                    this.serviceA = serviceA;
                }
            }

            // 编译时报错
            // Error: Circular dependency detected:
            //   ServiceA -> ServiceB -> ServiceA
            // 解决方法:使用Provider延迟注入
            @Singleton
            public class ServiceA {
                private final Provider<ServiceB> serviceB;

                public ServiceA(Provider<ServiceB> serviceB) {
                    this.serviceB = serviceB;
                }

                public void doSomething() {
                    serviceB.get().process();  // 延迟获取
                }
            }
            ---

1.8 云原生支持

01.容器化支持
    a.Docker镜像优化
        a.分层构建
            Micronaut应用支持Docker多阶段构建,可以生成极小的镜像,特别是使用GraalVM原生镜像时,镜像大小可降至50-80MB。
        b.镜像构建实践
            ---
            // JVM模式Dockerfile
            FROM eclipse-temurin:17-jre-alpine
            WORKDIR /app
            COPY target/micronaut-app-*.jar app.jar
            EXPOSE 8080
            ENTRYPOINT ["java", "-jar", "app.jar"]

            // 镜像大小:150-200MB
            // 启动时间:1-2秒
            // 内存占用:50-100MB

            // GraalVM原生镜像Dockerfile
            FROM ghcr.io/graalvm/graalvm-ce:ol8-java17-22 AS builder
            WORKDIR /app
            COPY . .
            RUN ./mvnw package -Dpackaging=native-image

            FROM alpine:3.17
            RUN apk --no-cache add ca-certificates
            WORKDIR /app
            COPY --from=builder /app/target/micronaut-app ./app
            EXPOSE 8080
            ENTRYPOINT ["./app"]

            // 镜像大小:50-80MB
            // 启动时间:20-50ms
            // 内存占用:20-40MB

            // Jib插件构建(无需Docker)
            // pom.xml
            <plugin>
                <groupId>com.google.cloud.tools</groupId>
                <artifactId>jib-maven-plugin</artifactId>
                <version>3.3.1</version>
                <configuration>
                    <to>
                        <image>myregistry/micronaut-app:latest</image>
                    </to>
                    <container>
                        <jvmFlags>
                            <jvmFlag>-Xms64m</jvmFlag>
                            <jvmFlag>-Xmx128m</jvmFlag>
                        </jvmFlags>
                        <ports>
                            <port>8080</port>
                        </ports>
                    </container>
                </configuration>
            </plugin>

            // 构建命令:mvn compile jib:build
            // 优点:不需要Docker daemon,构建速度快,镜像分层优化
            ---
    b.健康检查与就绪探测
        a.健康检查端点
            Micronaut内置health端点,支持Kubernetes的liveness和readiness探测。
        b.健康检查配置
            ---
            // application.yml
            // endpoints:
            //   health:
            //     enabled: true
            //     sensitive: false
            //   info:
            //     enabled: true

            // 自定义健康指示器
            import io.micronaut.management.health.indicator.HealthIndicator;
            import io.micronaut.management.health.indicator.HealthResult;
            import jakarta.inject.Singleton;
            import org.reactivestreams.Publisher;
            import reactor.core.publisher.Mono;

            @Singleton
            public class DatabaseHealthIndicator implements HealthIndicator {
                private final DataSource dataSource;

                public DatabaseHealthIndicator(DataSource dataSource) {
                    this.dataSource = dataSource;
                }

                @Override
                public Publisher<HealthResult> getResult() {
                    return Mono.fromCallable(() -> {
                        try (Connection conn = dataSource.getConnection()) {
                            boolean isValid = conn.isValid(2);
                            if (isValid) {
                                return HealthResult.builder("database")
                                    .status(HealthStatus.UP)
                                    .details(Map.of("connection", "active"))
                                    .build();
                            } else {
                                return HealthResult.builder("database")
                                    .status(HealthStatus.DOWN)
                                    .details(Map.of("connection", "invalid"))
                                    .build();
                            }
                        } catch (Exception e) {
                            return HealthResult.builder("database")
                                .status(HealthStatus.DOWN)
                                .exception(e)
                                .build();
                        }
                    });
                }
            }

            // Kubernetes配置
            // livenessProbe:
            //   httpGet:
            //     path: /health
            //     port: 8080
            //   initialDelaySeconds: 5
            //   periodSeconds: 10
            // readinessProbe:
            //   httpGet:
            //     path: /health/readiness
            //     port: 8080
            //   initialDelaySeconds: 5
            //   periodSeconds: 5
            ---

02.服务发现
    a.Consul集成
        a.服务注册
            Micronaut原生支持Consul服务发现,应用启动时自动注册到Consul,关闭时自动注销。
        b.Consul配置
            ---
            // Maven依赖
            // <dependency>
            //     <groupId>io.micronaut.discovery</groupId>
            //     <artifactId>micronaut-discovery-client</artifactId>
            // </dependency>

            // application.yml
            // consul:
            //   client:
            //     registration:
            //       enabled: true
            //     defaultZone: "${CONSUL_HOST:localhost}:${CONSUL_PORT:8500}"
            //     health-path: /health
            // micronaut:
            //   application:
            //     name: user-service

            // 服务自动注册
            import io.micronaut.runtime.Micronaut;

            public class Application {
                public static void main(String[] args) {
                    // 启动时自动注册到Consul
                    // 注册信息包括:服务名、IP、端口、健康检查路径
                    Micronaut.run(Application.class, args);
                }
            }

            // 服务调用(通过服务名)
            import io.micronaut.http.client.annotation.Client;

            @Client("user-service")  // 通过Consul解析服务地址
            public interface UserClient {
                @Get("/users/{id}")
                User getUser(Long id);
            }

            // 负载均衡(客户端负载均衡)
            // consul:
            //   client:
            //     load-balancer:
            //       enabled: true
            //       strategy: round-robin  # 轮询策略
            ---
    b.Eureka集成
        a.Eureka支持
            Micronaut也支持Netflix Eureka服务注册与发现,兼容Spring Cloud生态。
        b.Eureka配置
            ---
            // Maven依赖
            // <dependency>
            //     <groupId>io.micronaut.discovery</groupId>
            //     <artifactId>micronaut-discovery-client</artifactId>
            // </dependency>

            // application.yml
            // eureka:
            //   client:
            //     registration:
            //       enabled: true
            //     defaultZone: "${EUREKA_HOST:localhost}:${EUREKA_PORT:8761}/eureka"
            //     health-check-url: http://${micronaut.server.host}:${micronaut.server.port}/health

            // 服务调用示例
            @Singleton
            public class OrderService {
                @Client("order-service")
                private OrderClient orderClient;

                public Order getOrder(Long id) {
                    return orderClient.findById(id);
                }
            }
            ---

03.配置中心
    a.Consul配置中心
        a.分布式配置
            Micronaut支持从Consul KV存储读取配置,实现配置集中管理和动态更新。
        b.配置中心示例
            ---
            // application.yml
            // consul:
            //   client:
            //     config:
            //       enabled: true
            //       format: YAML  # 配置格式:YAML、JSON、PROPERTIES
            // micronaut:
            //   application:
            //     name: order-service
            //   config-client:
            //     enabled: true

            // Consul KV存储结构
            // config/
            //   application/        # 全局配置
            //     data              # database.url=jdbc:mysql://...
            //   order-service/      # 应用特定配置
            //     data              # order.max-items=100
            //   order-service,prod/ # 环境特定配置
            //     data              # database.url=jdbc:mysql://prod-db/...

            // 配置类
            import io.micronaut.context.annotation.ConfigurationProperties;
            import io.micronaut.context.annotation.Refreshable;

            @ConfigurationProperties("order")
            @Refreshable  // 支持配置动态刷新
            public class OrderConfig {
                private int maxItems;
                private Duration timeout;

                // getter和setter
            }

            // 配置刷新
            // POST /refresh
            // 触发配置重新加载,标记@Refreshable的Bean会重新创建
            ---
    b.Kubernetes ConfigMap
        a.ConfigMap集成
            Micronaut支持从Kubernetes ConfigMap和Secret读取配置,适合云原生部署。
        b.ConfigMap配置
            ---
            // Maven依赖
            // <dependency>
            //     <groupId>io.micronaut.kubernetes</groupId>
            //     <artifactId>micronaut-kubernetes-discovery-client</artifactId>
            // </dependency>

            // application.yml
            // kubernetes:
            //   client:
            //     config-maps:
            //       enabled: true
            //       paths:
            //         - /etc/config/app-config
            //     secrets:
            //       enabled: true
            //       paths:
            //         - /etc/secret/db-credentials

            // Kubernetes ConfigMap
            apiVersion: v1
            kind: ConfigMap
            metadata:
              name: app-config
            data:
              application.yml: |
                datasource:
                  url: jdbc:postgresql://postgres:5432/mydb
                  pool-size: 20

            // Kubernetes Secret
            apiVersion: v1
            kind: Secret
            metadata:
              name: db-credentials
            type: Opaque
            data:
              username: YWRtaW4=  # base64编码
              password: cGFzc3dvcmQ=

            // Deployment挂载ConfigMap和Secret
            apiVersion: apps/v1
            kind: Deployment
            spec:
              template:
                spec:
                  containers:
                  - name: app
                    volumeMounts:
                    - name: config
                      mountPath: /etc/config
                    - name: secret
                      mountPath: /etc/secret
                  volumes:
                  - name: config
                    configMap:
                      name: app-config
                  - name: secret
                    secret:
                      secretName: db-credentials
            ---

04.可观测性
    a.分布式追踪
        a.Zipkin集成
            Micronaut内置Zipkin追踪支持,自动为HTTP请求生成追踪信息,无需修改业务代码。
        b.追踪配置
            ---
            // Maven依赖
            // <dependency>
            //     <groupId>io.micronaut.tracing</groupId>
            //     <artifactId>micronaut-tracing-zipkin</artifactId>
            // </dependency>

            // application.yml
            // tracing:
            //   zipkin:
            //     enabled: true
            //     http:
            //       url: http://zipkin:9411
            //     sampler:
            //       probability: 1.0  # 采样率100%

            // 自动追踪HTTP请求
            @Controller("/orders")
            public class OrderController {
                @Inject
                private PaymentClient paymentClient;

                @Post
                public Order createOrder(@Body OrderRequest request) {
                    // Micronaut自动生成追踪ID并传播到下游服务
                    PaymentResult result = paymentClient.charge(request);
                    return orderService.create(request, result);
                }
            }

            // 自定义追踪
            import io.micronaut.tracing.annotation.NewSpan;
            import io.micronaut.tracing.annotation.SpanTag;

            @Singleton
            public class InventoryService {
                @NewSpan("check-inventory")
                public boolean checkStock(
                    @SpanTag("product-id") Long productId,
                    @SpanTag("quantity") int quantity) {
                    // 该方法会生成独立的追踪span
                    return inventoryRepository.getStock(productId) >= quantity;
                }
            }
            ---
    b.指标监控
        a.Micrometer集成
            Micronaut集成Micrometer指标库,支持Prometheus、InfluxDB等多种监控系统。
        b.监控配置
            ---
            // Maven依赖
            // <dependency>
            //     <groupId>io.micronaut.micrometer</groupId>
            //     <artifactId>micronaut-micrometer-registry-prometheus</artifactId>
            // </dependency>

            // application.yml
            // micronaut:
            //   metrics:
            //     enabled: true
            //     export:
            //       prometheus:
            //         enabled: true
            //         step: PT1M
            //         descriptions: true

            // 自动暴露/prometheus端点
            // 访问 http://localhost:8080/prometheus 获取指标

            // 自定义指标
            import io.micrometer.core.instrument.MeterRegistry;
            import io.micrometer.core.instrument.Counter;
            import jakarta.inject.Singleton;

            @Singleton
            public class OrderMetrics {
                private final Counter orderCounter;
                private final Timer orderProcessingTimer;

                public OrderMetrics(MeterRegistry registry) {
                    this.orderCounter = Counter.builder("orders.created")
                        .description("订单创建总数")
                        .tag("type", "online")
                        .register(registry);

                    this.orderProcessingTimer = Timer.builder("orders.processing.time")
                        .description("订单处理耗时")
                        .register(registry);
                }

                public void recordOrderCreated() {
                    orderCounter.increment();
                }

                public void recordProcessingTime(Runnable task) {
                    orderProcessingTimer.record(task);
                }
            }

            // Kubernetes ServiceMonitor(Prometheus Operator)
            apiVersion: monitoring.coreos.com/v1
            kind: ServiceMonitor
            metadata:
              name: micronaut-app
            spec:
              selector:
                matchLabels:
                  app: micronaut-app
              endpoints:
              - port: http
                path: /prometheus
                interval: 30s
            ---
    c.日志聚合
        a.结构化日志
            Micronaut支持结构化日志输出,便于日志采集和分析系统处理。
        b.日志配置
            ---
            // logback.xml
            <configuration>
                <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
                    <encoder class="net.logstash.logback.encoder.LogstashEncoder">
                        <includeContext>true</includeContext>
                        <includeMdc>true</includeMdc>
                        <customFields>{"app":"order-service","env":"prod"}</customFields>
                    </encoder>
                </appender>

                <root level="INFO">
                    <appender-ref ref="STDOUT" />
                </root>
            </configuration>

            // 输出JSON格式日志
            // {"@timestamp":"2024-01-15T10:30:45.123Z","level":"INFO",
            //  "thread":"default-nioEventLoopGroup-1-3","logger":"OrderController",
            //  "message":"创建订单","app":"order-service","env":"prod",
            //  "trace_id":"abc123","span_id":"def456"}

            // 使用MDC传递上下文
            import org.slf4j.MDC;
            import org.slf4j.Logger;
            import org.slf4j.LoggerFactory;

            @Singleton
            public class OrderService {
                private static final Logger log = LoggerFactory.getLogger(OrderService.class);

                public Order createOrder(OrderRequest request) {
                    MDC.put("user_id", request.getUserId().toString());
                    MDC.put("order_id", UUID.randomUUID().toString());

                    log.info("开始创建订单");
                    // 业务逻辑
                    log.info("订单创建成功");

                    MDC.clear();
                    return order;
                }
            }
            ---

2 核心组件

2.1 汇总:6个核心组件

01.组件概览
    a.核心组件列表
        Micronaut框架由6个核心组件构成,分别负责应用上下文管理、依赖注入、AOP代理、HTTP通信、配置管理和Bean生命周期,这些组件协同工作,构建了完整的应用运行时环境。
    b.组件关系图
        ---
        // Micronaut核心组件架构
        // ┌─────────────────────────────────────┐
        // │      ApplicationContext             │  应用上下文(顶层容器)
        // │  ┌───────────────────────────────┐  │
        // │  │   BeanContext                 │  │  Bean上下文(依赖注入容器)
        // │  │  ┌─────────────────────────┐  │  │
        // │  │  │  BeanDefinitionRegistry │  │  │  Bean定义注册表
        // │  │  └─────────────────────────┘  │  │
        // │  │  ┌─────────────────────────┐  │  │
        // │  │  │  InterceptorRegistry    │  │  │  AOP拦截器注册表
        // │  │  └─────────────────────────┘  │  │
        // │  └───────────────────────────────┘  │
        // │  ┌───────────────────────────────┐  │
        // │  │   Environment                 │  │  配置环境
        // │  └───────────────────────────────┘  │
        // │  ┌───────────────────────────────┐  │
        // │  │   HttpServerConfiguration     │  │  HTTP服务器
        // │  └───────────────────────────────┘  │
        // └─────────────────────────────────────┘

        // 组件初始化顺序
        // 1. Environment           - 加载配置
        // 2. BeanContext          - 初始化Bean容器
        // 3. BeanDefinitionRegistry - 注册Bean定义
        // 4. InterceptorRegistry   - 注册拦截器
        // 5. ApplicationContext    - 启动应用上下文
        // 6. HttpServer           - 启动HTTP服务器
        ---

02.组件依赖关系
    a.ApplicationContext
        a.作用
            ApplicationContext是Micronaut的顶层容器,管理整个应用的生命周期,继承自BeanContext,提供额外的环境管理、事件发布等功能。
        b.职责
            负责应用启动、配置加载、Bean实例化、事件传播、优雅关闭等核心任务。
    b.BeanContext
        a.作用
            BeanContext是依赖注入容器的核心,负责Bean的注册、实例化、依赖解析和生命周期管理。
        b.职责
            管理所有BeanDefinition,解析Bean依赖关系,按拓扑顺序创建Bean实例,处理作用域和单例缓存。
    c.AOP代理机制
        a.作用
            InterceptorRegistry管理所有AOP拦截器,在方法调用时执行拦截器链,实现声明式事务、缓存、日志等横切关注点。
        b.职责
            注册拦截器、构建拦截器链、执行方法拦截、管理拦截器顺序。
    d.HTTP客户端与服务器
        a.作用
            基于Netty的HTTP服务器和声明式HTTP客户端,提供高性能的非阻塞IO通信能力。
        b.职责
            处理HTTP请求和响应、路由分发、内容协商、客户端负载均衡。
    e.配置管理
        a.作用
            Environment组件负责从多种来源加载配置,合并配置优先级,提供类型安全的配置访问。
        b.职责
            加载配置文件、解析环境变量、管理配置优先级、支持配置刷新。
    f.Bean生命周期
        a.作用
            管理Bean的创建、初始化、使用和销毁全生命周期,支持生命周期回调和事件监听。
        b.职责
            执行@PostConstruct和@PreDestroy回调、发布生命周期事件、管理Bean销毁顺序。

03.组件交互流程
    a.应用启动流程
        a.启动阶段划分
            Micronaut应用启动分为环境初始化、Bean容器启动、HTTP服务器启动三个主要阶段。
        b.启动流程代码
            ---
            import io.micronaut.runtime.Micronaut;
            import io.micronaut.context.ApplicationContext;
            import io.micronaut.context.env.Environment;

            public class Application {
                public static void main(String[] args) {
                    // 创建并启动应用上下文
                    ApplicationContext context = Micronaut.run(Application.class, args);

                    // 内部执行流程
                    // 阶段1:环境初始化(50-100ms)
                    //   1.1 解析命令行参数
                    //   1.2 加载application.yml
                    //   1.3 解析环境变量
                    //   1.4 合并配置源

                    // 阶段2:Bean容器启动(200-400ms)
                    //   2.1 加载BeanDefinition类
                    //   2.2 解析Bean依赖关系
                    //   2.3 创建单例Bean实例
                    //   2.4 执行@PostConstruct回调
                    //   2.5 发布ApplicationStartedEvent

                    // 阶段3:HTTP服务器启动(100-200ms)
                    //   3.1 初始化Netty EventLoopGroup
                    //   3.2 绑定端口
                    //   3.3 注册路由处理器
                    //   3.4 发布ServerStartupEvent

                    // 总耗时:350-700ms(JVM模式)
                    // 总耗时:20-50ms(GraalVM原生镜像)
                }
            }

            // 监听启动事件
            import io.micronaut.runtime.event.ApplicationStartupEvent;
            import io.micronaut.context.event.ApplicationEventListener;

            @Singleton
            public class StartupListener implements
                ApplicationEventListener<ApplicationStartupEvent> {

                @Override
                public void onApplicationEvent(ApplicationStartupEvent event) {
                    System.out.println("应用启动完成");
                    ApplicationContext context = event.getSource();
                    Environment env = context.getEnvironment();
                    System.out.println("活跃环境: " + env.getActiveNames());
                }
            }
            ---
    b.请求处理流程
        a.HTTP请求流程
            HTTP请求从Netty服务器接收,经过过滤器链、路由匹配、参数绑定、控制器处理、响应序列化等阶段。
        b.请求流程示例
            ---
            // HTTP请求处理流程
            // 1. Netty接收HTTP请求
            // 2. HttpServerFilter过滤器链处理
            // 3. 路由匹配(UriRouteMatch)
            // 4. 参数绑定(ArgumentBinderRegistry)
            // 5. 执行控制器方法
            // 6. AOP拦截器处理
            // 7. 响应序列化(HttpResponseEncoder)
            // 8. Netty发送HTTP响应

            // 自定义过滤器
            import io.micronaut.http.*;
            import io.micronaut.http.annotation.Filter;
            import io.micronaut.http.filter.HttpServerFilter;
            import io.micronaut.http.filter.ServerFilterChain;
            import org.reactivestreams.Publisher;

            @Filter("/api/**")
            public class LoggingFilter implements HttpServerFilter {
                private static final Logger log = LoggerFactory.getLogger(LoggingFilter.class);

                @Override
                public Publisher<MutableHttpResponse<?>> doFilter(
                    HttpRequest<?> request,
                    ServerFilterChain chain) {

                    long start = System.currentTimeMillis();

                    // 记录请求
                    log.info("收到请求: {} {}", request.getMethod(), request.getPath());

                    // 继续处理请求
                    return Flux.from(chain.proceed(request))
                        .doOnNext(response -> {
                            long duration = System.currentTimeMillis() - start;
                            log.info("响应状态: {}, 耗时: {}ms",
                                   response.getStatus(), duration);
                        });
                }
            }

            // 控制器处理
            @Controller("/api/users")
            public class UserController {
                @Get("/{id}")
                public User getUser(Long id) {
                    // 参数id已自动绑定
                    return userService.findById(id);
                }
            }
            ---

04.组件扩展机制
    a.BeanCreatedEventListener
        a.Bean创建事件
            通过监听Bean创建事件,可以在Bean创建后、注入前对Bean进行自定义处理。
        b.事件监听示例
            ---
            import io.micronaut.context.event.BeanCreatedEvent;
            import io.micronaut.context.event.BeanCreatedEventListener;
            import jakarta.inject.Singleton;

            @Singleton
            public class DataSourceCustomizer implements
                BeanCreatedEventListener<DataSource> {

                @Override
                public DataSource onCreated(BeanCreatedEvent<DataSource> event) {
                    DataSource dataSource = event.getBean();

                    // 对DataSource进行自定义配置
                    if (dataSource instanceof HikariDataSource) {
                        HikariDataSource hikari = (HikariDataSource) dataSource;
                        hikari.setConnectionTimeout(30000);
                        hikari.setMaximumPoolSize(20);
                        System.out.println("DataSource配置已定制");
                    }

                    return dataSource;
                }
            }

            // 应用场景
            // 1. 数据源连接池配置
            // 2. HTTP客户端拦截器注册
            // 3. 缓存管理器初始化
            // 4. 第三方组件定制
            ---
    b.BeanDefinitionReference
        a.延迟加载
            BeanDefinitionReference提供Bean定义的引用,支持延迟加载,在需要时才实例化Bean。
        b.延迟加载示例
            ---
            import io.micronaut.context.BeanContext;
            import io.micronaut.inject.BeanDefinition;
            import io.micronaut.inject.BeanDefinitionReference;

            @Singleton
            public class LazyBeanLoader {
                private final BeanContext beanContext;

                public LazyBeanLoader(BeanContext beanContext) {
                    this.beanContext = beanContext;
                }

                public void loadBeansOnDemand() {
                    // 获取所有Bean定义引用(不实例化)
                    Collection<BeanDefinitionReference<?>> references =
                        beanContext.getBeanDefinitionReferences();

                    System.out.println("总共有 " + references.size() + " 个Bean定义");

                    // 按需加载Bean
                    for (BeanDefinitionReference<?> ref : references) {
                        if (ref.getBeanType().getPackage().getName().startsWith("com.example")) {
                            // 仅加载com.example包下的Bean
                            BeanDefinition<?> definition = ref.load(beanContext);
                            Object bean = beanContext.getBean(definition.getBeanType());
                            System.out.println("加载Bean: " + bean.getClass().getName());
                        }
                    }
                }
            }
            ---

2.2 应用上下文

01.ApplicationContext详解
    a.上下文创建
        a.创建方式
            ApplicationContext是Micronaut的顶层容器,可以通过Micronaut.run()或ApplicationContext.builder()创建,前者用于启动Web应用,后者用于非Web场景。
        b.创建示例
            ---
            import io.micronaut.context.ApplicationContext;
            import io.micronaut.runtime.Micronaut;

            // 方式1:Web应用启动
            public class WebApplication {
                public static void main(String[] args) {
                    // 创建并启动Web应用上下文
                    ApplicationContext context = Micronaut.run(WebApplication.class, args);
                    // 自动启动HTTP服务器
                }
            }

            // 方式2:非Web应用
            public class CliApplication {
                public static void main(String[] args) {
                    // 创建应用上下文(不启动HTTP服务器)
                    ApplicationContext context = ApplicationContext.builder()
                        .deduceEnvironment(true)  // 自动推断环境
                        .banner(false)            // 不显示banner
                        .start();

                    // 使用Bean
                    DataProcessor processor = context.getBean(DataProcessor.class);
                    processor.process();

                    // 关闭上下文
                    context.close();
                }
            }

            // 方式3:自定义配置
            public class CustomApplication {
                public static void main(String[] args) {
                    ApplicationContext context = ApplicationContext.builder()
                        .environments("dev", "test")  // 指定环境
                        .properties(Map.of(           // 添加属性
                            "datasource.url", "jdbc:h2:mem:testdb",
                            "app.version", "1.0.0"
                        ))
                        .singletons(new CustomBean())  // 注册单例
                        .packages("com.example")       // 限制扫描包
                        .start();

                    context.close();
                }
            }
            ---
    b.上下文配置
        a.构建器模式
            ApplicationContext.builder()提供流畅的API配置应用上下文,支持环境、属性、类加载器等自定义。
        b.配置选项
            ---
            import io.micronaut.context.ApplicationContextBuilder;

            public class ContextConfiguration {
                public static ApplicationContext createContext() {
                    ApplicationContextBuilder builder = ApplicationContext.builder();

                    return builder
                        // 环境配置
                        .environments("prod")
                        .deduceEnvironment(false)

                        // 类加载器
                        .classLoader(CustomClassLoader.class.getClassLoader())

                        // 自定义属性
                        .properties(Map.of(
                            "micronaut.server.port", "9090",
                            "micronaut.application.name", "my-service"
                        ))

                        // 预注册Bean
                        .singletons(new MetricsRegistry())

                        // 包扫描限制
                        .packages("com.example.services", "com.example.controllers")

                        // 排除包
                        .excludePackages("com.example.test")

                        // 启动时不启动服务器
                        .eagerInitSingletons(false)

                        // Banner配置
                        .banner(true)

                        // 启动上下文
                        .start();
                }
            }
            ---

02.Bean访问与管理
    a.Bean获取方法
        a.类型获取
            通过Bean的Class类型获取实例,如果存在多个同类型Bean会抛出异常,需要使用@Named或@Primary指定。
        b.获取示例
            ---
            import io.micronaut.context.ApplicationContext;
            import io.micronaut.context.exceptions.NoSuchBeanException;
            import io.micronaut.context.exceptions.NonUniqueBeanException;

            @Singleton
            public class BeanAccessor {
                private final ApplicationContext context;

                public BeanAccessor(ApplicationContext context) {
                    this.context = context;
                }

                public void accessBeans() {
                    // 1. 通过类型获取Bean
                    UserService userService = context.getBean(UserService.class);

                    // 2. 通过类型和限定符获取
                    DataSource primaryDs = context.getBean(DataSource.class,
                        Qualifiers.byName("primary"));

                    // 3. 检查Bean是否存在
                    boolean exists = context.containsBean(EmailService.class);

                    // 4. 可选获取(不存在返回Optional.empty)
                    Optional<CacheService> cacheService =
                        context.findBean(CacheService.class);

                    // 5. 获取所有同类型Bean
                    Collection<MessageSender> senders =
                        context.getBeansOfType(MessageSender.class);

                    // 6. 通过Argument获取(支持泛型)
                    Argument<List<String>> arg = Argument.listOf(String.class);
                    List<String> list = context.getBean(arg);
                }

                public void handleErrors() {
                    try {
                        context.getBean(NonExistentService.class);
                    } catch (NoSuchBeanException e) {
                        System.out.println("Bean不存在");
                    }

                    try {
                        context.getBean(NotificationService.class);
                    } catch (NonUniqueBeanException e) {
                        System.out.println("存在多个同类型Bean,需要使用@Named指定");
                    }
                }
            }
            ---
    b.Bean注册
        a.动态注册Bean
            除了通过注解自动注册Bean,还可以在运行时动态注册Bean实例或BeanDefinition。
        b.动态注册示例
            ---
            import io.micronaut.context.ApplicationContext;
            import io.micronaut.inject.BeanDefinition;
            import io.micronaut.context.BeanRegistration;

            public class DynamicBeanRegistration {
                public static void main(String[] args) {
                    ApplicationContext context = ApplicationContext.run();

                    // 1. 注册单例实例
                    Configuration config = new Configuration("prod");
                    context.registerSingleton(Configuration.class, config);

                    // 2. 注册带限定符的Bean
                    DataSource primaryDs = createPrimaryDataSource();
                    context.registerSingleton(DataSource.class, primaryDs,
                        Qualifiers.byName("primary"));

                    DataSource secondaryDs = createSecondaryDataSource();
                    context.registerSingleton(DataSource.class, secondaryDs,
                        Qualifiers.byName("secondary"));

                    // 3. 获取注册的Bean
                    Configuration retrievedConfig = context.getBean(Configuration.class);
                    DataSource primary = context.getBean(DataSource.class,
                        Qualifiers.byName("primary"));

                    // 4. 销毁Bean
                    context.destroyBean(Configuration.class);

                    context.close();
                }

                private static DataSource createPrimaryDataSource() {
                    return new HikariDataSource(/*...*/);
                }

                private static DataSource createSecondaryDataSource() {
                    return new HikariDataSource(/*...*/);
                }
            }
            ---

03.环境管理
    a.Environment组件
        a.环境概念
            Environment管理应用的配置环境,支持多环境配置、配置优先级、属性占位符解析等功能。
        b.环境使用
            ---
            import io.micronaut.context.env.Environment;
            import io.micronaut.context.env.PropertySource;
            import jakarta.inject.Singleton;

            @Singleton
            public class EnvironmentService {
                private final Environment environment;

                public EnvironmentService(Environment environment) {
                    this.environment = environment;
                }

                public void printEnvironmentInfo() {
                    // 获取活跃环境
                    Set<String> activeNames = environment.getActiveNames();
                    System.out.println("活跃环境: " + activeNames);

                    // 获取配置属性
                    String appName = environment.getProperty("micronaut.application.name",
                        String.class).orElse("unknown");
                    System.out.println("应用名称: " + appName);

                    Integer port = environment.getProperty("micronaut.server.port",
                        Integer.class).orElse(8080);
                    System.out.println("服务端口: " + port);

                    // 获取必需属性(不存在会抛异常)
                    String dbUrl = environment.getRequiredProperty("datasource.url",
                        String.class);

                    // 属性占位符解析
                    String value = environment.getPlaceholderResolver()
                        .resolveRequiredPlaceholders("${app.name}-${app.version}");

                    // 检查环境
                    boolean isDev = environment.getActiveNames().contains("dev");
                    boolean isProd = environment.getActiveNames().contains("prod");
                }

                public void listPropertySources() {
                    // 遍历所有配置源
                    for (PropertySource source : environment.getPropertySources()) {
                        System.out.println("配置源: " + source.getName());
                        System.out.println("优先级: " + source.getOrder());
                    }
                }
            }

            // 配置优先级(从高到低)
            // 1. 命令行参数
            // 2. 系统属性
            // 3. 环境变量
            // 4. application-{env}.yml
            // 5. application.yml
            // 6. 默认值
            ---
    b.多环境配置
        a.环境激活
            通过micronaut.environments属性或MICRONAUT_ENVIRONMENTS环境变量指定活跃环境。
        b.环境配置示例
            ---
            // application.yml(默认配置)
            // micronaut:
            //   application:
            //     name: order-service
            // datasource:
            //   url: jdbc:h2:mem:default
            //   driver-class-name: org.h2.Driver

            // application-dev.yml(开发环境)
            // datasource:
            //   url: jdbc:mysql://localhost:3306/dev_db
            //   username: dev_user
            //   password: dev_pass
            // logger:
            //   levels:
            //     com.example: DEBUG

            // application-prod.yml(生产环境)
            // datasource:
            //   url: jdbc:mysql://prod-db:3306/prod_db
            //   username: prod_user
            //   password: ${DB_PASSWORD}  # 从环境变量读取
            //   pool:
            //     maximum-pool-size: 50
            // logger:
            //   levels:
            //     com.example: INFO

            // 启动时指定环境
            // java -Dmicronaut.environments=dev -jar app.jar
            // java -Dmicronaut.environments=prod -jar app.jar
            // MICRONAUT_ENVIRONMENTS=prod java -jar app.jar

            // 多环境激活
            // java -Dmicronaut.environments=cloud,prod -jar app.jar

            // 环境条件Bean
            import io.micronaut.context.annotation.Requires;

            @Singleton
            @Requires(env = "dev")
            public class DevDataInitializer {
                @PostConstruct
                public void init() {
                    System.out.println("开发环境:初始化测试数据");
                }
            }

            @Singleton
            @Requires(env = "prod")
            public class ProdMonitoringService {
                @PostConstruct
                public void init() {
                    System.out.println("生产环境:启动监控服务");
                }
            }
            ---

04.事件系统
    a.应用事件
        a.内置事件类型
            Micronaut提供丰富的应用生命周期事件,可以监听这些事件执行自定义逻辑。
        b.事件监听
            ---
            import io.micronaut.context.event.ApplicationEventListener;
            import io.micronaut.context.event.*;
            import io.micronaut.runtime.event.*;
            import jakarta.inject.Singleton;

            // 监听应用启动事件
            @Singleton
            public class StartupListener implements
                ApplicationEventListener<ApplicationStartupEvent> {

                @Override
                public void onApplicationEvent(ApplicationStartupEvent event) {
                    System.out.println("应用启动完成");
                }
            }

            // 监听应用关闭事件
            @Singleton
            public class ShutdownListener implements
                ApplicationEventListener<ShutdownEvent> {

                @Override
                public void onApplicationEvent(ShutdownEvent event) {
                    System.out.println("应用即将关闭,清理资源...");
                }
            }

            // 监听HTTP服务器启动
            @Singleton
            public class ServerStartListener implements
                ApplicationEventListener<ServerStartupEvent> {

                @Override
                public void onApplicationEvent(ServerStartupEvent event) {
                    int port = event.getSource().getPort();
                    System.out.println("HTTP服务器启动,端口: " + port);
                }
            }

            // 监听Bean创建事件
            @Singleton
            public class BeanListener implements
                ApplicationEventListener<BeanCreatedEvent<DataSource>> {

                @Override
                public void onApplicationEvent(BeanCreatedEvent<DataSource> event) {
                    System.out.println("DataSource Bean已创建");
                }
            }
            ---
    b.自定义事件
        a.事件发布
            可以定义自定义事件并通过ApplicationEventPublisher发布,其他组件可以监听这些事件。
        b.自定义事件示例
            ---
            // 定义自定义事件
            public class OrderCreatedEvent {
                private final Order order;
                private final long timestamp;

                public OrderCreatedEvent(Order order) {
                    this.order = order;
                    this.timestamp = System.currentTimeMillis();
                }

                public Order getOrder() { return order; }
                public long getTimestamp() { return timestamp; }
            }

            // 发布事件
            import io.micronaut.context.event.ApplicationEventPublisher;
            import jakarta.inject.Singleton;

            @Singleton
            public class OrderService {
                private final ApplicationEventPublisher<OrderCreatedEvent> eventPublisher;

                public OrderService(ApplicationEventPublisher<OrderCreatedEvent> eventPublisher) {
                    this.eventPublisher = eventPublisher;
                }

                public Order createOrder(OrderRequest request) {
                    Order order = new Order(request);
                    // 保存订单
                    orderRepository.save(order);

                    // 发布事件
                    eventPublisher.publishEvent(new OrderCreatedEvent(order));

                    return order;
                }
            }

            // 监听自定义事件
            @Singleton
            public class OrderEventListener implements
                ApplicationEventListener<OrderCreatedEvent> {

                @Inject
                private NotificationService notificationService;

                @Inject
                private InventoryService inventoryService;

                @Override
                public void onApplicationEvent(OrderCreatedEvent event) {
                    Order order = event.getOrder();

                    // 发送通知
                    notificationService.sendOrderConfirmation(order);

                    // 扣减库存
                    inventoryService.decreaseStock(order.getItems());

                    System.out.println("订单事件处理完成: " + order.getId());
                }
            }

            // 异步事件监听
            import io.micronaut.scheduling.annotation.Async;

            @Singleton
            public class AsyncOrderListener implements
                ApplicationEventListener<OrderCreatedEvent> {

                @Async  // 异步执行
                @Override
                public void onApplicationEvent(OrderCreatedEvent event) {
                    // 在独立线程中处理事件
                    System.out.println("异步处理订单: " + event.getOrder().getId());
                }
            }
            ---

2.3 依赖注入容器

01.BeanContext详解
    a.容器职责
        a.核心功能
            BeanContext是Micronaut的依赖注入容器,负责管理所有Bean的定义、实例化、依赖解析和生命周期,它在编译时获得完整的依赖关系图,运行时高效地创建和管理Bean。
        b.容器操作
            ---
            import io.micronaut.context.BeanContext;
            import io.micronaut.context.ApplicationContext;
            import io.micronaut.inject.BeanDefinition;
            import io.micronaut.inject.qualifiers.Qualifiers;

            public class BeanContextExample {
                public static void main(String[] args) {
                    BeanContext context = ApplicationContext.run();

                    // 1. 获取Bean定义(不实例化)
                    BeanDefinition<UserService> definition =
                        context.getBeanDefinition(UserService.class);
                    System.out.println("Bean类型: " + definition.getBeanType());
                    System.out.println("是否单例: " + definition.isSingleton());

                    // 2. 获取所有Bean定义
                    Collection<BeanDefinition<?>> allDefinitions =
                        context.getBeanDefinitions();
                    System.out.println("总共有 " + allDefinitions.size() + " 个Bean");

                    // 3. 按类型查找Bean定义
                    Collection<BeanDefinition<DataSource>> dsDefinitions =
                        context.getBeanDefinitions(DataSource.class);

                    // 4. 创建Bean实例
                    UserService userService = context.createBean(UserService.class);

                    // 5. 销毁Bean
                    context.destroyBean(userService);

                    // 6. 获取或创建Bean
                    OrderService orderService = context.getBean(OrderService.class);

                    // 7. 刷新Bean(仅@Refreshable标记的Bean)
                    context.refreshBean(BeanIdentifier.of("configBean"));

                    context.close();
                }
            }
            ---
    b.依赖解析
        a.依赖图构建
            BeanContext在启动时根据编译时生成的BeanDefinition构建完整的依赖关系图,确定Bean的创建顺序。
        b.依赖解析示例
            ---
            // 定义Bean依赖关系
            @Singleton
            public class RepositoryImpl implements Repository {
                public RepositoryImpl() {
                    System.out.println("1. Repository创建");
                }
            }

            @Singleton
            public class ServiceImpl implements Service {
                private final Repository repository;

                public ServiceImpl(Repository repository) {
                    System.out.println("2. Service创建,依赖Repository");
                    this.repository = repository;
                }
            }

            @Singleton
            public class ControllerImpl implements Controller {
                private final Service service;

                public ControllerImpl(Service service) {
                    System.out.println("3. Controller创建,依赖Service");
                    this.service = service;
                }
            }

            // 启动应用
            // 输出顺序:
            // 1. Repository创建
            // 2. Service创建,依赖Repository
            // 3. Controller创建,依赖Service

            // 依赖关系图
            // Controller -> Service -> Repository
            // Micronaut按拓扑顺序创建:Repository -> Service -> Controller

            // 复杂依赖示例
            @Singleton
            public class ComplexService {
                private final Dependency1 dep1;
                private final Dependency2 dep2;
                private final Dependency3 dep3;

                public ComplexService(Dependency1 dep1,
                                    Dependency2 dep2,
                                    Dependency3 dep3) {
                    this.dep1 = dep1;
                    this.dep2 = dep2;
                    this.dep3 = dep3;
                }
            }

            // Micronaut在编译时分析:
            // 1. ComplexService依赖Dependency1、Dependency2、Dependency3
            // 2. 检查这3个依赖是否存在
            // 3. 检查是否存在循环依赖
            // 4. 生成创建顺序:先创建3个依赖,再创建ComplexService
            ---

02.Bean定义
    a.BeanDefinition接口
        a.元数据访问
            BeanDefinition提供Bean的完整元数据,包括类型、作用域、注解、构造器参数、依赖关系等信息。
        b.元数据查询
            ---
            import io.micronaut.inject.BeanDefinition;
            import io.micronaut.inject.ExecutableMethod;
            import io.micronaut.core.annotation.AnnotationMetadata;

            @Singleton
            public class BeanInspector {
                private final BeanContext beanContext;

                public BeanInspector(BeanContext beanContext) {
                    this.beanContext = beanContext;
                }

                public void inspectBean(Class<?> beanType) {
                    BeanDefinition<?> definition =
                        beanContext.getBeanDefinition(beanType);

                    // 基本信息
                    System.out.println("Bean类型: " + definition.getBeanType());
                    System.out.println("是否单例: " + definition.isSingleton());
                    System.out.println("是否可迭代: " + definition.isIterable());

                    // 作用域信息
                    Optional<Class<? extends Annotation>> scope = definition.getScope();
                    scope.ifPresent(s -> System.out.println("作用域: " + s.getName()));

                    // 注解元数据
                    AnnotationMetadata metadata = definition.getAnnotationMetadata();
                    System.out.println("注解: " + metadata.getAnnotationNames());

                    // 构造器参数
                    definition.getConstructor().getArguments()
                        .forEach(arg -> System.out.println("依赖: " + arg.getType()));

                    // 可执行方法(包含@PostConstruct等)
                    Collection<ExecutableMethod<?, ?>> methods =
                        definition.getExecutableMethods();
                    methods.forEach(method ->
                        System.out.println("方法: " + method.getName()));

                    // 注入字段
                    definition.getInjectedFields()
                        .forEach(field -> System.out.println("字段: " + field.getName()));

                    // 注入方法
                    definition.getInjectedMethods()
                        .forEach(method -> System.out.println("注入方法: " + method.getName()));
                }
            }
            ---
    b.BeanDefinitionRegistry
        a.注册表功能
            BeanDefinitionRegistry管理所有Bean定义的注册、查找和移除,是BeanContext的核心组成部分。
        b.注册表操作
            ---
            import io.micronaut.inject.BeanDefinitionRegistry;
            import io.micronaut.context.ApplicationContext;

            public class RegistryExample {
                public static void main(String[] args) {
                    ApplicationContext context = ApplicationContext.run();
                    BeanDefinitionRegistry registry = context;

                    // 1. 查找Bean定义
                    Optional<BeanDefinition<UserService>> definition =
                        registry.findBeanDefinition(UserService.class);

                    if (definition.isPresent()) {
                        BeanDefinition<UserService> def = definition.get();
                        System.out.println("找到Bean定义: " + def.getBeanType());
                    }

                    // 2. 查找所有Bean定义
                    Collection<BeanDefinition<?>> allBeans =
                        registry.getBeanDefinitions();

                    // 3. 按类型查找
                    Collection<BeanDefinition<Repository>> repositories =
                        registry.getBeanDefinitions(Repository.class);

                    // 4. 按限定符查找
                    BeanDefinition<DataSource> primaryDs =
                        registry.findBeanDefinition(DataSource.class,
                            Qualifiers.byName("primary")).orElse(null);

                    // 5. 检查Bean定义是否存在
                    boolean exists = registry.containsBean(EmailService.class);

                    // 6. 获取Bean定义数量
                    int count = registry.getBeanDefinitions().size();
                    System.out.println("注册的Bean总数: " + count);

                    context.close();
                }
            }
            ---

03.Bean实例化
    a.实例化策略
        a.单例缓存
            @Singleton标记的Bean首次创建后缓存在BeanContext中,后续注入直接从缓存获取,保证全局唯一。
        b.实例化流程
            ---
            // Bean实例化流程示例
            import io.micronaut.context.BeanContext;
            import io.micronaut.context.BeanResolutionContext;
            import io.micronaut.inject.BeanDefinition;

            // 编译时生成的BeanDefinition实现
            @Generated
            public class $OrderService$Definition
                extends AbstractInitializableBeanDefinition<OrderService> {

                @Override
                public OrderService build(BeanResolutionContext resolutionContext,
                                        BeanContext context,
                                        BeanDefinition<OrderService> definition) {
                    // 1. 解析依赖
                    OrderRepository repository =
                        (OrderRepository) super.getBeanForConstructorArgument(
                            resolutionContext, context, 0, null);

                    PaymentService paymentService =
                        (PaymentService) super.getBeanForConstructorArgument(
                            resolutionContext, context, 1, null);

                    // 2. 调用构造器创建实例(无反射)
                    OrderService bean = new OrderService(repository, paymentService);

                    // 3. 执行字段注入(如果有@Inject字段)
                    // super.injectBean(resolutionContext, context, bean);

                    // 4. 执行方法注入(如果有@Inject方法)
                    // super.injectBeanMethods(resolutionContext, context, bean);

                    // 5. 返回实例
                    return bean;
                }

                @Override
                protected Object injectBean(BeanResolutionContext resolutionContext,
                                          BeanContext context,
                                          Object bean) {
                    OrderService orderService = (OrderService) bean;

                    // 执行@PostConstruct方法
                    orderService.init();

                    return orderService;
                }
            }

            // 使用示例
            public class InstantiationExample {
                public static void main(String[] args) {
                    BeanContext context = BeanContext.run();

                    // 首次获取:触发实例化
                    OrderService service1 = context.getBean(OrderService.class);

                    // 再次获取:从缓存返回(单例)
                    OrderService service2 = context.getBean(OrderService.class);

                    // 验证是同一实例
                    System.out.println(service1 == service2);  // true

                    context.close();
                }
            }
            ---
    b.懒加载
        a.懒加载配置
            通过@Context(lazy=true)配置Bean懒加载,仅在首次使用时才创建实例。
        b.懒加载示例
            ---
            import io.micronaut.context.annotation.Context;

            @Singleton
            @Context(lazy = true)  // 懒加载
            public class HeavyService {
                public HeavyService() {
                    System.out.println("HeavyService初始化(耗时操作)");
                    // 加载大量数据、建立连接等耗时操作
                }

                public void process() {
                    System.out.println("处理业务逻辑");
                }
            }

            @Controller("/api")
            public class ApiController {
                private final HeavyService heavyService;

                public ApiController(HeavyService heavyService) {
                    this.heavyService = heavyService;
                    // 此时HeavyService尚未初始化
                }

                @Get("/process")
                public String process() {
                    // 首次调用时才初始化HeavyService
                    heavyService.process();
                    return "Done";
                }
            }

            // 启动流程
            // 1. 应用启动:HeavyService未初始化
            // 2. 首次访问/api/process:触发HeavyService初始化
            // 3. 后续访问:直接使用已创建的实例
            ---

04.作用域管理
    a.作用域类型
        a.支持的作用域
            Micronaut支持多种Bean作用域,包括Singleton、Prototype、RequestScope、ThreadLocal、Refreshable等。
        b.作用域示例
            ---
            import io.micronaut.context.annotation.Prototype;
            import io.micronaut.runtime.http.scope.RequestScope;
            import io.micronaut.context.annotation.ThreadLocal;
            import io.micronaut.context.annotation.Refreshable;

            // 单例作用域(默认)
            @Singleton
            public class ConfigService {
                // 应用生命周期内唯一实例
            }

            // 原型作用域(每次注入创建新实例)
            @Prototype
            public class TaskExecutor {
                private String taskId = UUID.randomUUID().toString();

                public String getTaskId() {
                    return taskId;
                }
            }

            // 请求作用域(每个HTTP请求内唯一)
            @RequestScope
            public class RequestContext {
                private String traceId = UUID.randomUUID().toString();
                private Map<String, Object> attributes = new HashMap<>();

                public void setAttribute(String key, Object value) {
                    attributes.put(key, value);
                }
            }

            // 线程局部作用域
            @ThreadLocal
            public class ThreadContext {
                private String threadId = Thread.currentThread().getName();
                // 每个线程独立实例
            }

            // 可刷新作用域(配置变更时重新创建)
            @Refreshable
            @ConfigurationProperties("dynamic")
            public class DynamicConfig {
                private int maxConnections;
                // POST /refresh端点触发时重新创建
            }

            // 使用示例
            @Singleton
            public class ScopeDemo {
                private final BeanContext beanContext;

                public ScopeDemo(BeanContext beanContext) {
                    this.beanContext = beanContext;
                }

                public void demonstrateScopes() {
                    // Singleton:同一实例
                    ConfigService config1 = beanContext.getBean(ConfigService.class);
                    ConfigService config2 = beanContext.getBean(ConfigService.class);
                    System.out.println("Singleton相同: " + (config1 == config2));  // true

                    // Prototype:不同实例
                    TaskExecutor task1 = beanContext.getBean(TaskExecutor.class);
                    TaskExecutor task2 = beanContext.getBean(TaskExecutor.class);
                    System.out.println("Prototype不同: " + (task1 != task2));  // true
                    System.out.println("Task1 ID: " + task1.getTaskId());
                    System.out.println("Task2 ID: " + task2.getTaskId());
                }
            }
            ---
    b.自定义作用域
        a.作用域注解
            可以定义自定义作用域注解,实现特定的Bean生命周期管理。
        b.自定义作用域示例
            ---
            import io.micronaut.context.scope.CustomScope;
            import io.micronaut.context.BeanResolutionContext;
            import io.micronaut.inject.BeanIdentifier;
            import jakarta.inject.Singleton;
            import java.lang.annotation.*;

            // 定义作用域注解
            @Documented
            @Retention(RetentionPolicy.RUNTIME)
            @Target({ElementType.TYPE, ElementType.METHOD})
            @Scope
            public @interface TenantScope {
            }

            // 实现作用域逻辑
            @Singleton
            public class TenantScopeImpl implements CustomScope<TenantScope> {
                private final Map<String, Map<BeanIdentifier, Object>> tenantBeans =
                    new ConcurrentHashMap<>();

                @Override
                public Class<TenantScope> annotationType() {
                    return TenantScope.class;
                }

                @Override
                public <T> T get(BeanResolutionContext resolutionContext,
                               BeanDefinition<T> beanDefinition,
                               BeanIdentifier identifier,
                               BeanProvider<T> provider) {
                    // 获取当前租户ID
                    String tenantId = TenantContext.getCurrentTenantId();

                    // 获取或创建租户级别的Bean
                    Map<BeanIdentifier, Object> beans =
                        tenantBeans.computeIfAbsent(tenantId, k -> new ConcurrentHashMap<>());

                    return (T) beans.computeIfAbsent(identifier, k -> provider.get());
                }

                @Override
                public <T> Optional<T> remove(BeanIdentifier identifier) {
                    String tenantId = TenantContext.getCurrentTenantId();
                    Map<BeanIdentifier, Object> beans = tenantBeans.get(tenantId);
                    if (beans != null) {
                        return Optional.ofNullable((T) beans.remove(identifier));
                    }
                    return Optional.empty();
                }
            }

            // 使用自定义作用域
            @TenantScope
            public class TenantDataSource implements DataSource {
                // 每个租户独立的数据源实例
            }
            ---

2.4 AOP代理机制

01.拦截器系统
    a.MethodInterceptor接口
        a.拦截器定义
            MethodInterceptor是Micronaut AOP的核心接口,所有方法拦截器都需要实现此接口,提供intercept方法来处理方法调用。
        b.拦截器实现
            ---
            import io.micronaut.aop.MethodInterceptor;
            import io.micronaut.aop.MethodInvocationContext;
            import jakarta.inject.Singleton;
            import org.slf4j.Logger;
            import org.slf4j.LoggerFactory;

            @Singleton
            public class PerformanceInterceptor implements MethodInterceptor<Object, Object> {
                private static final Logger log =
                    LoggerFactory.getLogger(PerformanceInterceptor.class);

                @Override
                public Object intercept(MethodInvocationContext<Object, Object> context) {
                    long startTime = System.nanoTime();

                    // 获取方法信息
                    String className = context.getTarget().getClass().getSimpleName();
                    String methodName = context.getMethodName();
                    Object[] parameters = context.getParameterValues();

                    log.debug("开始执行: {}.{}()", className, methodName);

                    try {
                        // 执行原方法
                        Object result = context.proceed();

                        long duration = (System.nanoTime() - startTime) / 1_000_000;
                        log.info("执行完成: {}.{}() 耗时{}ms",
                               className, methodName, duration);

                        // 性能告警
                        if (duration > 1000) {
                            log.warn("方法执行超时: {}.{}() 耗时{}ms",
                                   className, methodName, duration);
                        }

                        return result;
                    } catch (Exception e) {
                        long duration = (System.nanoTime() - startTime) / 1_000_000;
                        log.error("执行失败: {}.{}() 耗时{}ms, 错误: {}",
                                className, methodName, duration, e.getMessage());
                        throw e;
                    }
                }
            }

            // 定义拦截注解
            import io.micronaut.aop.Around;
            import java.lang.annotation.*;

            @Around
            @Type(PerformanceInterceptor.class)
            @Retention(RetentionPolicy.RUNTIME)
            @Target({ElementType.METHOD, ElementType.TYPE})
            public @interface Monitor {
            }

            // 应用拦截器
            @Singleton
            public class ProductService {
                @Monitor  // 该方法会被性能监控
                public Product findById(Long id) {
                    // 模拟数据库查询
                    return productRepository.findById(id);
                }

                @Monitor
                public List<Product> search(String keyword) {
                    // 模拟复杂查询
                    return productRepository.search(keyword);
                }
            }
            ---
    b.拦截器链
        a.多拦截器组合
            一个方法可以被多个拦截器拦截,Micronaut按照拦截器的Order值构建拦截器链,依次执行。
        b.拦截器链示例
            ---
            import io.micronaut.core.order.Ordered;

            // 拦截器1:认证(优先级最高)
            @Singleton
            public class AuthInterceptor implements MethodInterceptor<Object, Object>,
                Ordered {

                @Override
                public int getOrder() {
                    return 100;  // 优先级高(数值小)
                }

                @Override
                public Object intercept(MethodInvocationContext<Object, Object> context) {
                    System.out.println("1. 认证检查");
                    // 检查认证
                    return context.proceed();
                }
            }

            // 拦截器2:日志
            @Singleton
            public class LogInterceptor implements MethodInterceptor<Object, Object>,
                Ordered {

                @Override
                public int getOrder() {
                    return 200;
                }

                @Override
                public Object intercept(MethodInvocationContext<Object, Object> context) {
                    System.out.println("2. 日志记录");
                    Object result = context.proceed();
                    System.out.println("6. 日志记录完成");
                    return result;
                }
            }

            // 拦截器3:缓存
            @Singleton
            public class CacheInterceptor implements MethodInterceptor<Object, Object>,
                Ordered {

                @Override
                public int getOrder() {
                    return 300;
                }

                @Override
                public Object intercept(MethodInvocationContext<Object, Object> context) {
                    System.out.println("3. 缓存检查");
                    Object result = context.proceed();
                    System.out.println("5. 缓存更新");
                    return result;
                }
            }

            // 应用多个拦截器
            @Singleton
            public class OrderService {
                @Auth      // AuthInterceptor
                @Logged    // LogInterceptor
                @Cached    // CacheInterceptor
                public Order getOrder(Long id) {
                    System.out.println("4. 实际方法执行");
                    return orderRepository.findById(id);
                }
            }

            // 执行顺序
            // 1. 认证检查(Order=100)
            // 2. 日志记录(Order=200)
            // 3. 缓存检查(Order=300)
            // 4. 实际方法执行
            // 5. 缓存更新(Order=300)
            // 6. 日志记录完成(Order=200)
            // 认证检查完成隐含在最外层
            ---

02.Introduction通知
    a.接口实现注入
        a.Introduction概念
            Introduction通知允许为接口动态提供实现,常用于声明式HTTP客户端、Repository等场景。
        b.声明式客户端
            ---
            // 定义HTTP客户端接口(无需实现类)
            import io.micronaut.http.client.annotation.Client;
            import io.micronaut.http.annotation.*;

            @Client("https://api.github.com")
            public interface GitHubApi {
                @Get("/users/{username}")
                User getUser(String username);

                @Get("/repos/{owner}/{repo}")
                Repository getRepository(String owner, String repo);
            }

            // Micronaut编译时生成实现类
            @Generated
            public class $GitHubApi$Intercepted implements GitHubApi {
                private final HttpClient httpClient;

                public $GitHubApi$Intercepted(HttpClient httpClient) {
                    this.httpClient = httpClient;
                }

                @Override
                public User getUser(String username) {
                    // 自动生成HTTP调用代码
                    return httpClient.toBlocking().retrieve(
                        "/users/" + username, User.class);
                }

                @Override
                public Repository getRepository(String owner, String repo) {
                    return httpClient.toBlocking().retrieve(
                        "/repos/" + owner + "/" + repo, Repository.class);
                }
            }

            // 使用示例
            @Singleton
            public class GithubService {
                private final GitHubApi githubApi;

                public GithubService(GitHubApi githubApi) {
                    this.githubApi = githubApi;  // 注入编译时生成的实现
                }

                public User getUserInfo(String username) {
                    return githubApi.getUser(username);
                }
            }
            ---
    b.自定义Introduction
        a.Introduction注解
            通过@Introduction注解和MethodInterceptor可以实现自定义的接口代理。
        b.自定义Introduction示例
            ---
            import io.micronaut.aop.Introduction;
            import io.micronaut.context.annotation.Type;
            import java.lang.annotation.*;

            // 定义Introduction注解
            @Introduction
            @Type(CrudRepositoryInterceptor.class)
            @Retention(RetentionPolicy.RUNTIME)
            @Target(ElementType.TYPE)
            public @interface CrudRepository {
                Class<?> entity();
            }

            // 实现Introduction拦截器
            @Singleton
            public class CrudRepositoryInterceptor implements MethodInterceptor<Object, Object> {
                private final JdbcTemplate jdbcTemplate;

                public CrudRepositoryInterceptor(JdbcTemplate jdbcTemplate) {
                    this.jdbcTemplate = jdbcTemplate;
                }

                @Override
                public Object intercept(MethodInvocationContext<Object, Object> context) {
                    String methodName = context.getMethodName();

                    // 根据方法名生成SQL
                    if (methodName.equals("findById")) {
                        Long id = (Long) context.getParameterValues()[0];
                        String sql = "SELECT * FROM users WHERE id = ?";
                        return jdbcTemplate.queryForObject(sql, User.class, id);
                    } else if (methodName.equals("save")) {
                        User user = (User) context.getParameterValues()[0];
                        String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
                        jdbcTemplate.update(sql, user.getName(), user.getEmail());
                        return user;
                    }

                    return null;
                }
            }

            // 定义Repository接口
            @CrudRepository(entity = User.class)
            public interface UserRepository {
                User findById(Long id);
                User save(User user);
                void deleteById(Long id);
            }

            // 使用Repository(无需编写实现类)
            @Singleton
            public class UserService {
                private final UserRepository userRepository;

                public UserService(UserRepository userRepository) {
                    this.userRepository = userRepository;  // 注入代理实现
                }

                public User getUser(Long id) {
                    return userRepository.findById(id);
                }
            }
            ---

03.内置AOP功能
    a.声明式事务
        a.@Transactional注解
            Micronaut提供@Transactional注解实现声明式事务管理,通过AOP拦截器自动处理事务的开启、提交和回滚。
        b.事务示例
            ---
            import io.micronaut.transaction.annotation.Transactional;
            import jakarta.inject.Singleton;

            @Singleton
            public class OrderService {
                private final OrderRepository orderRepository;
                private final InventoryService inventoryService;
                private final PaymentService paymentService;

                public OrderService(OrderRepository orderRepository,
                                  InventoryService inventoryService,
                                  PaymentService paymentService) {
                    this.orderRepository = orderRepository;
                    this.inventoryService = inventoryService;
                    this.paymentService = paymentService;
                }

                @Transactional  // 方法执行在事务中
                public Order createOrder(OrderRequest request) {
                    // 1. 创建订单
                    Order order = new Order(request);
                    orderRepository.save(order);

                    // 2. 扣减库存
                    inventoryService.decreaseStock(request.getItems());

                    // 3. 处理支付
                    PaymentResult payment = paymentService.charge(request.getAmount());

                    if (!payment.isSuccess()) {
                        // 抛出异常,事务自动回滚
                        throw new PaymentFailedException("支付失败");
                    }

                    order.setPaymentId(payment.getTransactionId());
                    orderRepository.update(order);

                    return order;
                    // 方法正常返回,事务自动提交
                    // 方法抛出异常,事务自动回滚
                }

                // 只读事务(优化性能)
                @Transactional(readOnly = true)
                public List<Order> findUserOrders(Long userId) {
                    return orderRepository.findByUserId(userId);
                }

                // 自定义事务传播
                @Transactional(propagation = Propagation.REQUIRES_NEW)
                public void recordAuditLog(AuditLog log) {
                    // 在新事务中执行,不受外部事务影响
                    auditRepository.save(log);
                }
            }

            // 事务配置
            // application.yml
            // datasources:
            //   default:
            //     transaction-manager: jdbc
            //     isolation-level: READ_COMMITTED
            //     timeout: 30s
            ---
    b.声明式缓存
        a.缓存注解
            Micronaut提供@Cacheable、@CachePut、@CacheInvalidate注解实现声明式缓存,支持多种缓存后端。
        b.缓存示例
            ---
            import io.micronaut.cache.annotation.*;
            import jakarta.inject.Singleton;

            @Singleton
            public class ProductService {
                private final ProductRepository repository;

                public ProductService(ProductRepository repository) {
                    this.repository = repository;
                }

                // 缓存查询结果
                @Cacheable(value = "products", parameters = {"id"})
                public Product findById(Long id) {
                    System.out.println("从数据库查询产品: " + id);
                    return repository.findById(id);
                }

                // 更新缓存
                @CachePut(value = "products", parameters = {"id"})
                public Product updateProduct(Long id, Product product) {
                    repository.update(product);
                    return product;
                }

                // 使缓存失效
                @CacheInvalidate(value = "products", parameters = {"id"})
                public void deleteProduct(Long id) {
                    repository.deleteById(id);
                }

                // 使所有缓存失效
                @CacheInvalidate(value = "products", all = true)
                public void clearAllCache() {
                    System.out.println("清除所有产品缓存");
                }

                // 异步缓存
                @Cacheable(value = "products-async", parameters = {"id"})
                public CompletableFuture<Product> findByIdAsync(Long id) {
                    return CompletableFuture.supplyAsync(() ->
                        repository.findById(id));
                }
            }

            // 缓存配置(使用Redis)
            // application.yml
            // redis:
            //   uri: redis://localhost:6379
            // micronaut:
            //   caches:
            //     products:
            //       charset: UTF-8
            //       expire-after-write: 10m
            //       expire-after-access: 5m

            // Maven依赖
            // <dependency>
            //     <groupId>io.micronaut.cache</groupId>
            //     <artifactId>micronaut-cache-redis</artifactId>
            // </dependency>
            ---
    c.重试机制
        a.@Retryable注解
            Micronaut提供@Retryable注解实现方法重试,自动处理瞬时故障。
        b.重试示例
            ---
            import io.micronaut.retry.annotation.Retryable;
            import io.micronaut.retry.annotation.CircuitBreaker;
            import jakarta.inject.Singleton;

            @Singleton
            public class ExternalApiService {
                private final HttpClient httpClient;

                public ExternalApiService(@Client("external-api") HttpClient httpClient) {
                    this.httpClient = httpClient;
                }

                // 失败时重试,最多3次,延迟1秒
                @Retryable(attempts = "3", delay = "1s")
                public ApiResponse callExternalApi(String endpoint) {
                    System.out.println("调用外部API: " + endpoint);
                    return httpClient.toBlocking()
                        .retrieve(endpoint, ApiResponse.class);
                }

                // 自定义重试条件
                @Retryable(
                    attempts = "5",
                    delay = "2s",
                    multiplier = "2",  // 延迟倍增:2s, 4s, 8s, 16s
                    includes = {IOException.class, TimeoutException.class}
                )
                public Data fetchData(String url) {
                    return httpClient.toBlocking().retrieve(url, Data.class);
                }

                // 熔断器模式
                @CircuitBreaker(
                    attempts = "5",
                    delay = "5s",
                    reset = "30s"  // 30秒后尝试恢复
                )
                public String callUnstableService() {
                    // 连续失败5次后,熔断器打开
                    // 熔断期间直接失败,不调用实际方法
                    // 30秒后尝试恢复(半开状态)
                    return httpClient.toBlocking().retrieve("/unstable");
                }
            }

            // 重试事件监听
            import io.micronaut.retry.event.RetryEvent;
            import io.micronaut.context.event.ApplicationEventListener;

            @Singleton
            public class RetryEventListener implements
                ApplicationEventListener<RetryEvent> {

                @Override
                public void onApplicationEvent(RetryEvent event) {
                    System.out.println("重试事件: 第" + event.getRetryCount() +
                                     "次重试,异常: " + event.getThrowable().getMessage());
                }
            }
            ---

04.代理类生成
    a.子类代理
        a.生成机制
            Micronaut在编译期为需要AOP的类生成子类代理,子类重写被拦截的方法,插入拦截器调用逻辑。
        b.代理类结构
            ---
            // 源代码
            import jakarta.inject.Singleton;

            @Singleton
            public class UserService {
                private final UserRepository repository;

                public UserService(UserRepository repository) {
                    this.repository = repository;
                }

                @Monitor  // 需要AOP拦截
                public User findById(Long id) {
                    return repository.findById(id);
                }

                public void updateUser(User user) {
                    repository.update(user);
                }
            }

            // 编译时生成的代理子类(简化版)
            @Generated
            public class $UserService$Intercepted extends UserService {
                private final ExecutableMethod<UserService, User> findByIdMethod;
                private final Interceptor<User>[] interceptors;

                public $UserService$Intercepted(
                    UserRepository repository,
                    BeanContext beanContext) {
                    super(repository);

                    // 加载方法元数据
                    this.findByIdMethod = beanContext.getExecutableMethod(
                        UserService.class, "findById", Long.class);

                    // 加载拦截器
                    this.interceptors = beanContext.getBeansOfType(
                        Interceptor.class, Qualifiers.byStereotype(Monitor.class));
                }

                @Override
                public User findById(Long id) {
                    // 构建拦截器上下文
                    MethodInvocationContext<UserService, User> context =
                        new MethodInvocationContext<>(
                            this, findByIdMethod, new Object[]{id});

                    // 执行拦截器链
                    return interceptors[0].intercept(context);
                }

                @Override
                public void updateUser(User user) {
                    // 无拦截器的方法直接调用父类
                    super.updateUser(user);
                }
            }

            // 依赖注入时注入代理类
            @Controller("/users")
            public class UserController {
                private final UserService userService;

                public UserController(UserService userService) {
                    // 实际注入的是$UserService$Intercepted实例
                    this.userService = userService;
                }

                @Get("/{id}")
                public User getUser(Long id) {
                    // 调用代理方法,触发拦截器
                    return userService.findById(id);
                }
            }
            ---
    b.代理限制
        a.Final类和方法
            Micronaut使用子类代理,因此无法代理final类和final方法,需要避免使用final修饰需要AOP的类。
        b.Private方法
            私有方法无法被子类重写,因此不能被AOP拦截,拦截器只对public和protected方法有效。

2.5 HTTP客户端与服务器

01.HTTP服务器
    a.Netty服务器架构
        a.事件驱动模型
            Micronaut HTTP服务器基于Netty实现,采用事件驱动的非阻塞IO模型,使用少量线程处理大量并发连接,提供卓越的吞吐量和低延迟。
        b.服务器配置
            ---
            // application.yml
            // micronaut:
            //   server:
            //     port: 8080
            //     host: 0.0.0.0
            //     netty:
            //       max-header-size: 16KB
            //       max-initial-line-length: 8KB
            //       max-chunk-size: 16KB
            //       worker:
            //         threads: 8        # 工作线程数
            //       parent:
            //         threads: 2        # Boss线程数
            //       child-options:
            //         SO_KEEPALIVE: true
            //         TCP_NODELAY: true

            // 服务器事件监听
            import io.micronaut.runtime.server.event.*;
            import io.micronaut.context.event.ApplicationEventListener;
            import jakarta.inject.Singleton;

            @Singleton
            public class ServerEventListener implements
                ApplicationEventListener<ServerStartupEvent> {

                @Override
                public void onApplicationEvent(ServerStartupEvent event) {
                    int port = event.getSource().getPort();
                    String host = event.getSource().getHost();
                    System.out.println("HTTP服务器已启动: " + host + ":" + port);

                    // 输出服务器配置
                    EmbeddedServer server = event.getSource();
                    System.out.println("服务器URL: " + server.getURL());
                    System.out.println("服务器协议: " + server.getScheme());
                }
            }

            // 优雅关闭配置
            // micronaut:
            //   server:
            //     shutdown:
            //       grace-period: 30s  # 优雅关闭等待期
            ---
    b.请求处理流程
        a.Netty管道
            HTTP请求在Netty管道中流转,经过解码器、路由器、过滤器、控制器处理器等多个Handler。
        b.自定义Handler
            ---
            import io.netty.channel.*;
            import io.netty.handler.codec.http.*;
            import io.micronaut.http.netty.channel.ChannelPipelineCustomizer;
            import jakarta.inject.Singleton;

            @Singleton
            public class CustomChannelPipelineCustomizer
                implements ChannelPipelineCustomizer {

                @Override
                public boolean isServerChannel() {
                    return true;  // 作用于服务器端
                }

                @Override
                public void doOnConnect(ChannelPipeline pipeline) {
                    // 在管道中添加自定义Handler
                    pipeline.addAfter(
                        ChannelPipelineCustomizer.HANDLER_HTTP_AGGREGATOR,
                        "custom-logger",
                        new CustomLoggingHandler()
                    );
                }
            }

            // 自定义Handler
            public class CustomLoggingHandler extends ChannelInboundHandlerAdapter {
                @Override
                public void channelRead(ChannelHandlerContext ctx, Object msg) {
                    if (msg instanceof FullHttpRequest) {
                        FullHttpRequest request = (FullHttpRequest) msg;
                        System.out.println("收到请求: " + request.method() +
                                         " " + request.uri());
                    }
                    ctx.fireChannelRead(msg);
                }

                @Override
                public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
                    System.err.println("处理请求出错: " + cause.getMessage());
                    ctx.close();
                }
            }
            ---

02.HTTP客户端
    a.声明式客户端
        a.客户端定义
            通过@Client注解定义HTTP客户端接口,Micronaut在编译时生成实现类,支持同步、异步和响应式调用。
        b.客户端示例
            ---
            import io.micronaut.http.client.annotation.Client;
            import io.micronaut.http.annotation.*;
            import io.reactivex.rxjava3.core.Single;
            import io.reactivex.rxjava3.core.Flowable;

            @Client("https://jsonplaceholder.typicode.com")
            public interface JsonPlaceholderClient {
                // 同步GET请求
                @Get("/posts/{id}")
                Post getPost(Long id);

                // 同步POST请求
                @Post("/posts")
                Post createPost(@Body Post post);

                // 异步GET请求
                @Get("/posts/{id}")
                CompletableFuture<Post> getPostAsync(Long id);

                // 响应式GET请求(单个结果)
                @Get("/posts/{id}")
                Single<Post> getPostReactive(Long id);

                // 响应式GET请求(多个结果)
                @Get("/posts")
                Flowable<Post> getAllPosts();

                // 自定义请求头
                @Get("/posts/{id}")
                @Header(name = "User-Agent", value = "Micronaut-Client")
                Post getPostWithHeader(Long id);

                // 查询参数
                @Get("/posts")
                List<Post> searchPosts(
                    @QueryValue("userId") Long userId,
                    @QueryValue("_limit") Integer limit
                );

                // DELETE请求
                @Delete("/posts/{id}")
                void deletePost(Long id);

                // PUT请��
                @Put("/posts/{id}")
                Post updatePost(Long id, @Body Post post);
            }

            // 使用客户端
            @Singleton
            public class PostService {
                private final JsonPlaceholderClient client;

                public PostService(JsonPlaceholderClient client) {
                    this.client = client;
                }

                public Post getPost(Long id) {
                    return client.getPost(id);
                }

                public void processPostsAsync() {
                    // 异步调用
                    CompletableFuture<Post> future = client.getPostAsync(1L);
                    future.thenAccept(post ->
                        System.out.println("获取到文章: " + post.getTitle())
                    );
                }

                public void processPostsReactive() {
                    // 响应式调用
                    client.getAllPosts()
                        .filter(post -> post.getUserId() == 1)
                        .take(10)
                        .subscribe(post ->
                            System.out.println("文章: " + post.getTitle())
                        );
                }
            }
            ---
    b.低级客户端
        a.HttpClient接口
            对于更复杂的场景,可以直接使用HttpClient接口进行低级HTTP操作,完全控制请求和响应。
        b.低级客户端示例
            ---
            import io.micronaut.http.client.HttpClient;
            import io.micronaut.http.client.annotation.Client;
            import io.micronaut.http.*;
            import jakarta.inject.Singleton;

            @Singleton
            public class CustomHttpService {
                private final HttpClient httpClient;

                public CustomHttpService(@Client("https://api.example.com") HttpClient httpClient) {
                    this.httpClient = httpClient;
                }

                public String makeCustomRequest() {
                    // 构建请求
                    MutableHttpRequest<String> request = HttpRequest
                        .POST("/api/data", "{\"key\":\"value\"}")
                        .contentType(MediaType.APPLICATION_JSON)
                        .header("Authorization", "Bearer token123")
                        .header("X-Custom-Header", "custom-value");

                    // 同步调用
                    HttpResponse<String> response =
                        httpClient.toBlocking().exchange(request, String.class);

                    System.out.println("状态码: " + response.getStatus());
                    System.out.println("响应头: " + response.getHeaders().asMap());
                    return response.body();
                }

                public void makeReactiveRequest() {
                    // 响应式调用
                    Flux<HttpResponse<String>> flux = Flux.from(
                        httpClient.exchange(
                            HttpRequest.GET("/api/items"),
                            String.class
                        )
                    );

                    flux.subscribe(
                        response -> System.out.println("响应: " + response.body()),
                        error -> System.err.println("错误: " + error.getMessage()),
                        () -> System.out.println("完成")
                    );
                }

                public void streamingRequest() {
                    // 流式读取响应
                    Flux<ByteBuffer<?>> stream = Flux.from(
                        httpClient.dataStream(HttpRequest.GET("/api/large-file"))
                    );

                    stream.subscribe(buffer -> {
                        System.out.println("接收数据块: " + buffer.toByteArray().length + " bytes");
                    });
                }
            }
            ---

03.客户端配置
    a.连接池管理
        a.连接池配置
            HTTP客户端使用连接池复用连接,可以配置连接池大小、超时时间、Keep-Alive等参数。
        b.配置示例
            ---
            // application.yml
            // micronaut:
            //   http:
            //     client:
            //       pool:
            //         enabled: true
            //         max-connections: 50      # 最大连接数
            //       read-timeout: 30s          # 读超时
            //       connect-timeout: 10s       # 连接超时
            //       read-idle-timeout: 60s     # 读空闲超时
            //       connection-pool-idle-timeout: 30s

            // 针对特定服务的配置
            // micronaut:
            //   http:
            //     services:
            //       user-service:
            //         urls:
            //           - http://user-service-1:8080
            //           - http://user-service-2:8080
            //         pool:
            //           max-connections: 20
            //         read-timeout: 10s
            //         load-balancer:
            //           strategy: round-robin

            // 代码中配置客户端
            import io.micronaut.http.client.HttpClientConfiguration;
            import io.micronaut.context.annotation.Factory;
            import io.micronaut.context.annotation.Bean;

            @Factory
            public class HttpClientFactory {
                @Bean
                @Named("custom-client")
                public HttpClient createCustomClient() {
                    HttpClientConfiguration config = new HttpClientConfiguration();
                    config.setReadTimeout(Duration.ofSeconds(30));
                    config.setConnectTimeout(Duration.ofSeconds(10));
                    config.getPoolConfiguration().setMaxConnections(100);

                    return HttpClient.create(
                        new URL("https://api.example.com"),
                        config
                    );
                }
            }
            ---
    b.负载均衡
        a.客户端负载均衡
            当配置多个服务实例URL时,Micronaut自动实现客户端负载均衡,支持轮询、随机等策略。
        b.负载均衡示例
            ---
            // application.yml配置多个服务实例
            // micronaut:
            //   http:
            //     services:
            //       product-service:
            //         urls:
            //           - http://product-1:8080
            //           - http://product-2:8080
            //           - http://product-3:8080
            //         load-balancer:
            //           strategy: round-robin  # 轮询策略

            // 定义客户端
            @Client(id = "product-service")
            public interface ProductClient {
                @Get("/products/{id}")
                Product getProduct(Long id);
            }

            // Micronaut自动在3个实例间负载均衡
            @Singleton
            public class ProductService {
                private final ProductClient productClient;

                public ProductService(ProductClient productClient) {
                    this.productClient = productClient;
                }

                public Product getProduct(Long id) {
                    // 自动负载均衡到product-1/2/3
                    return productClient.getProduct(id);
                }
            }

            // 自定义负载均衡策略
            import io.micronaut.http.client.loadbalance.ServiceInstanceList;
            import io.micronaut.discovery.ServiceInstance;

            @Singleton
            @Replaces(RoundRobinLoadBalancer.class)
            public class WeightedLoadBalancer implements LoadBalancer {
                @Override
                public Publisher<ServiceInstance> select(ServiceInstanceList instances) {
                    // 根据权重选择实例
                    List<ServiceInstance> list = instances.getInstances();
                    ServiceInstance selected = selectByWeight(list);
                    return Publishers.just(selected);
                }

                private ServiceInstance selectByWeight(List<ServiceInstance> instances) {
                    // 权重选择逻辑
                    return instances.get(0);
                }
            }
            ---

02.服务器端点
    a.Controller定义
        a.控制器注解
            @Controller注解定义HTTP端点,支持路径前缀、版本控制等配置。
        b.控制器示例
            ---
            import io.micronaut.http.annotation.*;
            import io.micronaut.http.HttpResponse;
            import jakarta.inject.Singleton;

            @Controller("/api/v1/users")
            public class UserController {
                private final UserService userService;

                public UserController(UserService userService) {
                    this.userService = userService;
                }

                // GET请求
                @Get("/{id}")
                public User getUser(Long id) {
                    return userService.findById(id);
                }

                // POST请求
                @Post
                public HttpResponse<User> createUser(@Body UserRequest request) {
                    User user = userService.create(request);
                    return HttpResponse.created(user);
                }

                // PUT请求
                @Put("/{id}")
                public User updateUser(Long id, @Body UserRequest request) {
                    return userService.update(id, request);
                }

                // DELETE请求
                @Delete("/{id}")
                @Status(HttpStatus.NO_CONTENT)
                public void deleteUser(Long id) {
                    userService.delete(id);
                }

                // 查询参数
                @Get
                public List<User> searchUsers(
                    @QueryValue("name") Optional<String> name,
                    @QueryValue("page") @DefaultValue("0") int page,
                    @QueryValue("size") @DefaultValue("20") int size) {
                    return userService.search(name.orElse(null), page, size);
                }

                // 请求头
                @Get("/profile")
                public User getCurrentUser(
                    @Header("Authorization") String authToken) {
                    String userId = extractUserId(authToken);
                    return userService.findById(Long.parseLong(userId));
                }

                // Cookie
                @Get("/preferences")
                public UserPreferences getPreferences(
                    @CookieValue("session_id") String sessionId) {
                    return userService.getPreferences(sessionId);
                }
            }
            ---
    b.响应式端点
        a.响应式返回类型
            控制器方法可以返回响应式类型,实现非阻塞的异步处理。
        b.响应式端点示例
            ---
            import io.micronaut.http.annotation.*;
            import reactor.core.publisher.Mono;
            import reactor.core.publisher.Flux;

            @Controller("/api/products")
            public class ProductController {
                private final ProductService productService;

                public ProductController(ProductService productService) {
                    this.productService = productService;
                }

                // 返回Mono(单个结果)
                @Get("/{id}")
                public Mono<Product> getProduct(Long id) {
                    return productService.findByIdAsync(id);
                }

                // 返回Flux(多个结果)
                @Get
                public Flux<Product> getAllProducts() {
                    return productService.findAllAsync();
                }

                // Server-Sent Events
                @Get(uri = "/stream", produces = MediaType.TEXT_EVENT_STREAM)
                public Flux<Product> streamProducts() {
                    // 持续推送产品更新
                    return productService.watchProductUpdates();
                }

                // 响应式POST
                @Post
                public Mono<HttpResponse<Product>> createProduct(@Body Mono<Product> product) {
                    return product
                        .flatMap(p -> productService.saveAsync(p))
                        .map(HttpResponse::created);
                }
            }

            // 响应式服务实现
            @Singleton
            public class ProductService {
                private final ProductRepository repository;

                public ProductService(ProductRepository repository) {
                    this.repository = repository;
                }

                public Mono<Product> findByIdAsync(Long id) {
                    return Mono.fromCallable(() -> repository.findById(id))
                        .subscribeOn(Schedulers.boundedElastic());
                }

                public Flux<Product> findAllAsync() {
                    return Flux.fromIterable(repository.findAll())
                        .subscribeOn(Schedulers.boundedElastic());
                }

                public Flux<Product> watchProductUpdates() {
                    // 模拟实时推送
                    return Flux.interval(Duration.ofSeconds(5))
                        .map(i -> repository.findLatest());
                }
            }
            ---

03.客户端过滤器
    a.HttpClientFilter
        a.请求拦截
            HttpClientFilter可以拦截所有HTTP客户端请求,用于添加认证头、日志记录、重试等通用逻辑。
        b.过滤器示例
            ---
            import io.micronaut.http.*;
            import io.micronaut.http.annotation.Filter;
            import io.micronaut.http.filter.ClientFilterChain;
            import io.micronaut.http.filter.HttpClientFilter;
            import org.reactivestreams.Publisher;

            // 认证过滤器
            @Filter("/api/**")
            public class AuthFilter implements HttpClientFilter {
                private final TokenProvider tokenProvider;

                public AuthFilter(TokenProvider tokenProvider) {
                    this.tokenProvider = tokenProvider;
                }

                @Override
                public Publisher<? extends HttpResponse<?>> doFilter(
                    MutableHttpRequest<?> request,
                    ClientFilterChain chain) {

                    // 添加认证头
                    String token = tokenProvider.getAccessToken();
                    request.header("Authorization", "Bearer " + token);

                    return chain.proceed(request);
                }
            }

            // 日志过滤器
            @Filter("/**")
            public class LoggingClientFilter implements HttpClientFilter {
                private static final Logger log =
                    LoggerFactory.getLogger(LoggingClientFilter.class);

                @Override
                public Publisher<? extends HttpResponse<?>> doFilter(
                    MutableHttpRequest<?> request,
                    ClientFilterChain chain) {

                    log.info("发送请求: {} {}", request.getMethod(), request.getUri());

                    return Flux.from(chain.proceed(request))
                        .doOnNext(response ->
                            log.info("收到响应: 状态={}", response.getStatus())
                        )
                        .doOnError(error ->
                            log.error("请求失败: {}", error.getMessage())
                        );
                }
            }

            // 重试过滤器
            @Filter("/**")
            public class RetryClientFilter implements HttpClientFilter {
                @Override
                public Publisher<? extends HttpResponse<?>> doFilter(
                    MutableHttpRequest<?> request,
                    ClientFilterChain chain) {

                    return Flux.from(chain.proceed(request))
                        .retryWhen(Retry.backoff(3, Duration.ofSeconds(1))
                            .filter(throwable -> throwable instanceof IOException)
                        );
                }
            }
            ---
    b.自定义序列化
        a.MediaTypeCodec
            可以注册自定义的编解码器,支持自定义序列化格式。
        b.自定义编解码器
            ---
            import io.micronaut.http.codec.MediaTypeCodec;
            import io.micronaut.http.MediaType;
            import jakarta.inject.Singleton;
            import java.io.*;

            @Singleton
            public class CustomXmlCodec implements MediaTypeCodec {
                @Override
                public Collection<MediaType> getMediaTypes() {
                    return Collections.singletonList(MediaType.APPLICATION_XML_TYPE);
                }

                @Override
                public <T> T decode(Argument<T> type, InputStream inputStream)
                    throws CodecException {
                    // 自定义XML反序列化
                    try {
                        String xml = new String(inputStream.readAllBytes());
                        // 解析XML
                        return parseXml(xml, type.getType());
                    } catch (IOException e) {
                        throw new CodecException("XML解析失败", e);
                    }
                }

                @Override
                public <T> void encode(T object, OutputStream outputStream)
                    throws CodecException {
                    // 自定义XML序列化
                    try {
                        String xml = toXml(object);
                        outputStream.write(xml.getBytes());
                    } catch (IOException e) {
                        throw new CodecException("XML生成失败", e);
                    }
                }

                private <T> T parseXml(String xml, Class<T> type) {
                    // XML解析逻辑
                    return null;
                }

                private String toXml(Object object) {
                    // XML生成逻辑
                    return "";
                }
            }
            ---

2.6 配置管理

01.配置加载
    a.配置源优先级
        a.优先级顺序
            Micronaut从多个配置源加载配置,按优先级从高到低依次为命令行参数、系统属性、环境变量、application-{env}.yml、application.yml,高优先级配置会覆盖低优先级配置。
        b.配置加载示例
            ---
            // application.yml(优先级最低)
            // datasource:
            //   url: jdbc:h2:mem:default
            //   username: sa
            //   password: ""
            //   pool:
            //     max-size: 10

            // application-prod.yml(环境配置,优先级更高)
            // datasource:
            //   url: jdbc:mysql://prod-db:3306/mydb
            //   username: prod_user
            //   password: ${DB_PASSWORD}  # 从环境变量读取

            // 环境变量(优先级更高)
            // export DB_PASSWORD=secret123
            // export DATASOURCE_POOL_MAX_SIZE=50

            // 系统属性(优先级更高)
            // java -Ddatasource.url=jdbc:mysql://override:3306/db -jar app.jar

            // 命令行参数(优先级最高)
            // java -jar app.jar --datasource.username=admin

            // 最终生效的配置
            import io.micronaut.context.env.Environment;

            @Singleton
            public class ConfigInspector {
                private final Environment environment;

                public ConfigInspector(Environment environment) {
                    this.environment = environment;
                }

                public void printConfig() {
                    // 读取最终生效的配置
                    String url = environment.getProperty("datasource.url", String.class)
                        .orElse("unknown");
                    String username = environment.getProperty("datasource.username", String.class)
                        .orElse("unknown");
                    Integer poolSize = environment.getProperty("datasource.pool.max-size",
                        Integer.class).orElse(10);

                    System.out.println("数据库URL: " + url);
                    System.out.println("用户名: " + username);
                    System.out.println("连接池大小: " + poolSize);
                }
            }
            ---
    b.配置文件格式
        a.支持的格式
            Micronaut支持YAML、Properties、JSON、HOCON等多种配置文件格式,推荐使用YAML格式。
        b.格式示例
            ---
            // application.yml(YAML格式,推荐)
            // micronaut:
            //   application:
            //     name: order-service
            //   server:
            //     port: 8080
            // datasource:
            //   url: jdbc:mysql://localhost:3306/mydb
            //   pool:
            //     max-size: 20

            // application.properties(Properties格式)
            // micronaut.application.name=order-service
            // micronaut.server.port=8080
            // datasource.url=jdbc:mysql://localhost:3306/mydb
            // datasource.pool.max-size=20

            // application.json(JSON格式)
            // {
            //   "micronaut": {
            //     "application": {
            //       "name": "order-service"
            //     },
            //     "server": {
            //       "port": 8080
            //     }
            //   },
            //   "datasource": {
            //     "url": "jdbc:mysql://localhost:3306/mydb",
            //     "pool": {
            //       "max-size": 20
            //     }
            //   }
            // }

            // 指定配置文件
            // java -Dmicronaut.config.files=file:/path/to/config.yml -jar app.jar
            ---

02.配置绑定
    a.@ConfigurationProperties
        a.类型安全配置
            @ConfigurationProperties注解将配置绑定到POJO类,提供类型安全的配置访问,支持嵌套配置和验证。
        b.配置类示例
            ---
            import io.micronaut.context.annotation.ConfigurationProperties;
            import io.micronaut.core.annotation.Nullable;
            import jakarta.validation.constraints.*;
            import java.time.Duration;

            @ConfigurationProperties("app")
            public class AppConfig {
                @NotBlank
                private String name;

                @NotBlank
                private String version;

                @Min(1)
                @Max(65535)
                private int port = 8080;

                @Nullable
                private Duration requestTimeout;

                private DatabaseConfig database;
                private CacheConfig cache;

                // getter和setter省略

                @ConfigurationProperties("database")
                public static class DatabaseConfig {
                    @NotBlank
                    private String url;

                    @NotBlank
                    private String username;

                    @NotBlank
                    private String password;

                    @Min(1)
                    @Max(1000)
                    private int maxConnections = 50;

                    private PoolConfig pool;

                    @ConfigurationProperties("pool")
                    public static class PoolConfig {
                        private Duration maxLifetime = Duration.ofMinutes(30);
                        private Duration idleTimeout = Duration.ofMinutes(10);

                        // getter和setter省略
                    }

                    // getter和setter省略
                }

                @ConfigurationProperties("cache")
                public static class CacheConfig {
                    private boolean enabled = true;
                    private String provider = "caffeine";
                    private Duration ttl = Duration.ofMinutes(10);

                    // getter和setter省略
                }
            }

            // application.yml
            // app:
            //   name: my-service
            //   version: 1.0.0
            //   port: 9090
            //   request-timeout: 30s
            //   database:
            //     url: jdbc:postgresql://localhost:5432/mydb
            //     username: dbuser
            //     password: dbpass
            //     max-connections: 100
            //     pool:
            //       max-lifetime: 60m
            //       idle-timeout: 20m
            //   cache:
            //     enabled: true
            //     provider: redis
            //     ttl: 5m

            // 使用配置
            @Singleton
            public class AppService {
                private final AppConfig config;

                public AppService(AppConfig config) {
                    this.config = config;
                    System.out.println("应用名称: " + config.getName());
                    System.out.println("数据库URL: " + config.getDatabase().getUrl());
                    System.out.println("缓存提供者: " + config.getCache().getProvider());
                }
            }
            ---
    b.@Value注入
        a.属性值注入
            @Value注解直接将配置属性注入到字段或方法参数,支持占位符和默认值。
        b.Value注入示例
            ---
            import io.micronaut.context.annotation.Value;
            import jakarta.inject.Singleton;

            @Singleton
            public class ServiceConfig {
                @Value("${micronaut.application.name}")
                private String appName;

                @Value("${micronaut.server.port:8080}")  // 默认值8080
                private int serverPort;

                @Value("${api.timeout:30s}")
                private Duration apiTimeout;

                @Value("${feature.enabled:false}")
                private boolean featureEnabled;

                @Value("${api.base-url}")
                private String apiBaseUrl;

                public void printConfig() {
                    System.out.println("应用名: " + appName);
                    System.out.println("端口: " + serverPort);
                    System.out.println("API超时: " + apiTimeout);
                    System.out.println("功能启用: " + featureEnabled);
                    System.out.println("API地址: " + apiBaseUrl);
                }
            }

            // 构造器注入配置值
            @Singleton
            public class EmailService {
                private final String smtpHost;
                private final int smtpPort;
                private final String from;

                public EmailService(
                    @Value("${email.smtp.host}") String smtpHost,
                    @Value("${email.smtp.port:587}") int smtpPort,
                    @Value("${email.from}") String from) {
                    this.smtpHost = smtpHost;
                    this.smtpPort = smtpPort;
                    this.from = from;
                }

                public void sendEmail(String to, String subject, String body) {
                    System.out.println("SMTP服务器: " + smtpHost + ":" + smtpPort);
                    System.out.println("发件人: " + from);
                }
            }
            ---

03.动态配置
    a.@Refreshable刷新
        a.配置刷新机制
            @Refreshable注解标记的Bean在配置变更时会被重新创建,实现配置的动态更新。
        b.刷新示例
            ---
            import io.micronaut.context.annotation.Refreshable;
            import io.micronaut.context.annotation.ConfigurationProperties;

            @Refreshable  // 可刷新Bean
            @ConfigurationProperties("dynamic")
            public class DynamicConfig {
                private int maxConnections;
                private Duration timeout;
                private boolean debugMode;

                public DynamicConfig() {
                    System.out.println("DynamicConfig创建");
                }

                // getter和setter省略
            }

            @Singleton
            public class ConnectionManager {
                private final DynamicConfig config;

                public ConnectionManager(DynamicConfig config) {
                    this.config = config;
                }

                public void createConnection() {
                    // 总是使用最新的配置值
                    int max = config.getMaxConnections();
                    System.out.println("最大连接数: " + max);
                }
            }

            // 触发配置刷新
            // POST http://localhost:8080/refresh
            // 返回:{"changed": ["dynamic.max-connections", "dynamic.timeout"]}

            // 配置刷新流程
            // 1. 接收/refresh请求
            // 2. 重新加载配置文件
            // 3. 对比配置变更
            // 4. 销毁@Refreshable Bean
            // 5. 重新创建Bean(使用新配置)
            // 6. 返回变更的配置项列表

            // 启用refresh端点
            // application.yml
            // endpoints:
            //   refresh:
            //     enabled: true
            //     sensitive: false
            ---
    b.配置监听
        a.RefreshEvent
            可以监听配置刷新事件,在配置变更时执行自定义逻辑。
        b.刷新事件监听
            ---
            import io.micronaut.runtime.context.scope.refresh.RefreshEvent;
            import io.micronaut.context.event.ApplicationEventListener;
            import jakarta.inject.Singleton;

            @Singleton
            public class ConfigRefreshListener implements
                ApplicationEventListener<RefreshEvent> {

                private final ConnectionPool connectionPool;
                private final CacheManager cacheManager;

                public ConfigRefreshListener(ConnectionPool connectionPool,
                                           CacheManager cacheManager) {
                    this.connectionPool = connectionPool;
                    this.cacheManager = cacheManager;
                }

                @Override
                public void onApplicationEvent(RefreshEvent event) {
                    Set<String> changedKeys = event.getChanges();

                    System.out.println("配置已刷新,变更项: " + changedKeys);

                    // 如果数据库配置变更,重新初始化连接池
                    if (changedKeys.stream().anyMatch(key -> key.startsWith("datasource"))) {
                        connectionPool.reinitialize();
                    }

                    // 如果缓存配置变更,清除缓存
                    if (changedKeys.stream().anyMatch(key -> key.startsWith("cache"))) {
                        cacheManager.clearAll();
                    }
                }
            }
            ---

04.外部配置中心
    a.Consul配置
        a.Consul KV集成
            Micronaut支持从Consul KV存储读取配置,实现配置的集中管理和动态更新。
        b.Consul配置示例
            ---
            // Maven依赖
            // <dependency>
            //     <groupId>io.micronaut.discovery</groupId>
            //     <artifactId>micronaut-discovery-client</artifactId>
            // </dependency>

            // bootstrap.yml(在application.yml之前加载)
            // micronaut:
            //   application:
            //     name: order-service
            //   config-client:
            //     enabled: true
            // consul:
            //   client:
            //     config:
            //       enabled: true
            //       format: YAML
            //     defaultZone: ${CONSUL_HOST:localhost}:${CONSUL_PORT:8500}

            // Consul KV存储结构
            // config/
            //   application/           # 全局配置(所有应用共享)
            //     data: |
            //       logging:
            //         level: INFO
            //   order-service/         # 应用特定配置
            //     data: |
            //       order:
            //         max-items: 100
            //         timeout: 30s
            //   order-service,prod/    # 环境特定配置
            //     data: |
            //       datasource:
            //         url: jdbc:mysql://prod-db/orderdb

            // 配置读取
            @ConfigurationProperties("order")
            @Refreshable  // 支持Consul配置变更推送
            public class OrderConfig {
                private int maxItems;
                private Duration timeout;

                // getter和setter省略
            }

            // 使用配置
            @Singleton
            public class OrderService {
                private final OrderConfig config;

                public OrderService(OrderConfig config) {
                    this.config = config;
                }

                public void processOrder(Order order) {
                    int maxItems = config.getMaxItems();  // 从Consul读取
                    if (order.getItems().size() > maxItems) {
                        throw new IllegalArgumentException("订单商品数超过限制");
                    }
                }
            }

            // Consul配置变更自动刷新
            // 1. 在Consul UI修改配置
            // 2. Micronaut自动检测变更
            // 3. 发布RefreshEvent
            // 4. 重新创建@Refreshable Bean
            ---
    b.AWS Parameter Store
        a.AWS集成
            Micronaut支持从AWS Systems Manager Parameter Store读取配置,适合AWS云环境。
        b.AWS配置示例
            ---
            // Maven依赖
            // <dependency>
            //     <groupId>io.micronaut.aws</groupId>
            //     <artifactId>micronaut-aws-parameter-store</artifactId>
            // </dependency>

            // bootstrap.yml
            // aws:
            //   client:
            //     system-manager:
            //       parameterstore:
            //         enabled: true
            //         useSecureParameters: true
            // micronaut:
            //   application:
            //     name: order-service
            //   config-client:
            //     enabled: true

            // AWS Parameter Store结构
            // /config/application/             # 全局配置
            //   database.url
            //   database.username
            // /config/order-service/           # 应用配置
            //   order.max-items
            //   order.timeout
            // /config/order-service_prod/      # 环境配置
            //   database.password              # 使用SecureString加密

            // 配置类
            @ConfigurationProperties("order")
            public class OrderConfig {
                private int maxItems;
                private Duration timeout;

                // getter和setter省略
            }

            // AWS IAM权限要求
            // {
            //   "Version": "2012-10-17",
            //   "Statement": [{
            //     "Effect": "Allow",
            //     "Action": [
            //       "ssm:GetParameter",
            //       "ssm:GetParameters",
            //       "ssm:GetParametersByPath"
            //     ],
            //     "Resource": "arn:aws:ssm:*:*:parameter/config/*"
            //   }]
            // }
            ---

03.环境变量注入
    a.环境变量映射
        a.命名约定
            环境变量名使用大写字母和下划线,Micronaut自动映射到配置属性,如DATASOURCE_URL映射到datasource.url。
        b.环境变量示例
            ---
            // 环境变量定义
            // export MICRONAUT_APPLICATION_NAME=my-service
            // export MICRONAUT_SERVER_PORT=9090
            // export DATASOURCE_URL=jdbc:mysql://db:3306/mydb
            // export DATASOURCE_USERNAME=dbuser
            // export DATASOURCE_PASSWORD=secret123
            // export APP_FEATURE_ENABLED=true
            // export APP_MAX_CONNECTIONS=50

            // 配置类
            @ConfigurationProperties("app")
            public class AppConfig {
                private boolean featureEnabled;
                private int maxConnections;

                // getter和setter省略
            }

            // 读取配置
            @Singleton
            public class ConfigService {
                private final AppConfig appConfig;
                private final Environment environment;

                public ConfigService(AppConfig appConfig, Environment environment) {
                    this.appConfig = appConfig;
                    this.environment = environment;
                }

                public void printConfig() {
                    // 通过ConfigurationProperties读取
                    System.out.println("功能启用: " + appConfig.isFeatureEnabled());
                    System.out.println("最大连接: " + appConfig.getMaxConnections());

                    // 直接从Environment读取
                    String appName = environment.getProperty("micronaut.application.name",
                        String.class).orElse("unknown");
                    System.out.println("应用名: " + appName);

                    // 读取原始环境变量
                    String javaHome = System.getenv("JAVA_HOME");
                    System.out.println("JAVA_HOME: " + javaHome);
                }
            }

            // Docker Compose配置
            // version: '3.8'
            // services:
            //   app:
            //     image: micronaut-app:latest
            //     environment:
            //       - MICRONAUT_ENVIRONMENTS=prod
            //       - DATASOURCE_URL=jdbc:mysql://mysql:3306/proddb
            //       - DATASOURCE_USERNAME=produser
            //       - DATASOURCE_PASSWORD=${DB_PASSWORD}
            //       - APP_MAX_CONNECTIONS=100
            //     env_file:
            //       - .env.prod
            ---
    b.占位符解析
        a.属性占位符
            配置中可以使用${...}占位符引用其他配置属性或环境变量。
        b.占位符示例
            ---
            // application.yml
            // app:
            //   name: order-service
            //   version: 1.0.0
            //   display-name: ${app.name} v${app.version}  # 引用其他属性
            //
            // datasource:
            //   host: ${DB_HOST:localhost}                 # 从环境变量读取,默认localhost
            //   port: ${DB_PORT:3306}
            //   database: ${DB_NAME:mydb}
            //   url: jdbc:mysql://${datasource.host}:${datasource.port}/${datasource.database}
            //   username: ${DB_USER:root}
            //   password: ${DB_PASSWORD:}
            //
            // api:
            //   base-url: ${API_PROTOCOL:http}://${API_HOST}:${API_PORT:8080}
            //   endpoints:
            //     users: ${api.base-url}/users
            //     orders: ${api.base-url}/orders

            // 读取配置
            @Singleton
            public class ApiClient {
                @Value("${api.endpoints.users}")
                private String usersEndpoint;

                @Value("${api.endpoints.orders}")
                private String ordersEndpoint;

                public void printEndpoints() {
                    System.out.println("用户API: " + usersEndpoint);
                    System.out.println("订单API: " + ordersEndpoint);
                }
            }

            // 环境变量
            // export DB_HOST=prod-db.example.com
            // export DB_PORT=3306
            // export DB_NAME=production
            // export DB_USER=prod_user
            // export DB_PASSWORD=secret123
            // export API_HOST=api.example.com
            // export API_PORT=443
            // export API_PROTOCOL=https

            // 最终配置值
            // datasource.url=jdbc:mysql://prod-db.example.com:3306/production
            // api.endpoints.users=https://api.example.com:443/users
            ---

2.7 附:Bean生命周期

01.生命周期阶段
    a.Bean创建阶段
        a.实例化顺序
            BeanContext根据依赖关系图按拓扑顺序创建Bean,确保依赖的Bean先于依赖它的Bean创建,避免依赖未就绪的问题。
        b.创建流程
            ---
            // Bean创建流程示例
            import jakarta.inject.Singleton;
            import jakarta.annotation.PostConstruct;

            // 第1个创建:无依赖
            @Singleton
            public class ConfigLoader {
                public ConfigLoader() {
                    System.out.println("步骤1: ConfigLoader构造器执行");
                }

                @PostConstruct
                public void init() {
                    System.out.println("步骤2: ConfigLoader初始化");
                }
            }

            // 第2个创建:依赖ConfigLoader
            @Singleton
            public class DataSource {
                private final ConfigLoader configLoader;

                public DataSource(ConfigLoader configLoader) {
                    System.out.println("步骤3: DataSource构造器执行");
                    this.configLoader = configLoader;
                }

                @PostConstruct
                public void init() {
                    System.out.println("步骤4: DataSource初始化");
                }
            }

            // 第3个创建:依赖DataSource
            @Singleton
            public class UserRepository {
                private final DataSource dataSource;

                public UserRepository(DataSource dataSource) {
                    System.out.println("步骤5: UserRepository构造器执行");
                    this.dataSource = dataSource;
                }

                @PostConstruct
                public void init() {
                    System.out.println("步骤6: UserRepository初始化");
                }
            }

            // 第4个创建:依赖UserRepository
            @Singleton
            public class UserService {
                private final UserRepository repository;

                public UserService(UserRepository repository) {
                    System.out.println("步骤7: UserService构造器执行");
                    this.repository = repository;
                }

                @PostConstruct
                public void init() {
                    System.out.println("步骤8: UserService初始化");
                }
            }

            // 应用启动输出
            // 步骤1: ConfigLoader构造器执行
            // 步骤2: ConfigLoader初始化
            // 步骤3: DataSource构造器执行
            // 步骤4: DataSource初始化
            // 步骤5: UserRepository构造器执行
            // 步骤6: UserRepository初始化
            // 步骤7: UserService构造器执行
            // 步骤8: UserService初始化
            ---
    b.初始化回调
        a.@PostConstruct注解
            @PostConstruct方法在Bean构造完成、依赖注入完成后执行,用于初始化资源、建立连接等操作。
        b.PostConstruct示例
            ---
            import jakarta.annotation.PostConstruct;
            import jakarta.inject.Singleton;
            import java.sql.Connection;

            @Singleton
            public class DatabaseInitializer {
                private final DataSource dataSource;
                private Connection connection;

                public DatabaseInitializer(DataSource dataSource) {
                    this.dataSource = dataSource;
                    System.out.println("构造器:dataSource注入完成");
                }

                @PostConstruct
                public void initialize() {
                    System.out.println("@PostConstruct:开始初始化");

                    try {
                        // 建立数据库连接
                        connection = dataSource.getConnection();
                        System.out.println("数据库连接已建立");

                        // 执行初始化SQL
                        Statement stmt = connection.createStatement();
                        stmt.execute("CREATE TABLE IF NOT EXISTS users (...)");
                        System.out.println("数据库表初始化完成");

                    } catch (SQLException e) {
                        throw new RuntimeException("数据库初始化失败", e);
                    }
                }

                public Connection getConnection() {
                    return connection;
                }
            }

            // 多个@PostConstruct方法
            @Singleton
            public class MultiInitBean {
                @PostConstruct
                public void init1() {
                    System.out.println("初始化步骤1");
                }

                @PostConstruct
                public void init2() {
                    System.out.println("初始化步骤2");
                }
                // 执行顺序不确定,避免依赖顺序
            }
            ---

02.生命周期事件
    a.ApplicationEventListener
        a.事件类型
            Micronaut提供丰富的生命周期事件,包括启动事件、关闭事件、Bean创建事件等,可以监听这些事件执行自定义逻辑。
        b.事件监听示例
            ---
            import io.micronaut.context.event.ApplicationEventListener;
            import io.micronaut.runtime.event.*;
            import io.micronaut.context.event.*;
            import jakarta.inject.Singleton;

            // 监听应用启动事件
            @Singleton
            public class StartupInitializer implements
                ApplicationEventListener<ApplicationStartupEvent> {

                @Inject
                private DataMigrationService migrationService;

                @Override
                public void onApplicationEvent(ApplicationStartupEvent event) {
                    System.out.println("应用启动完成,执行数据迁移");
                    migrationService.migrate();
                }
            }

            // 监听服务器启动事件
            @Singleton
            public class ServerReadyListener implements
                ApplicationEventListener<ServerStartupEvent> {

                @Override
                public void onApplicationEvent(ServerStartupEvent event) {
                    EmbeddedServer server = event.getSource();
                    System.out.println("服务器已就绪: " + server.getURL());

                    // 注册到服务发现
                    registerToServiceDiscovery(server);
                }

                private void registerToServiceDiscovery(EmbeddedServer server) {
                    // 服务注册逻辑
                }
            }

            // 监听应用关闭事件
            @Singleton
            public class ShutdownHandler implements
                ApplicationEventListener<ShutdownEvent> {

                @Inject
                private ConnectionPool connectionPool;

                @Override
                public void onApplicationEvent(ShutdownEvent event) {
                    System.out.println("应用即将关闭,清理资源");

                    // 关闭连接池
                    connectionPool.close();

                    // 注销服务
                    deregisterFromServiceDiscovery();
                }

                private void deregisterFromServiceDiscovery() {
                    // 服务注销逻辑
                }
            }

            // 监听Bean创建事件
            import io.micronaut.context.event.BeanCreatedEvent;

            @Singleton
            public class DataSourceListener implements
                ApplicationEventListener<BeanCreatedEvent<DataSource>> {

                @Override
                public void onApplicationEvent(BeanCreatedEvent<DataSource> event) {
                    DataSource dataSource = event.getBean();
                    System.out.println("DataSource Bean已创建");

                    // 配置连接池
                    if (dataSource instanceof HikariDataSource) {
                        HikariDataSource hikari = (HikariDataSource) dataSource;
                        hikari.setMaximumPoolSize(50);
                    }
                }
            }
            ---
    b.自定义生命周期事件
        a.事件定义与发布
            可以定义自定义生命周期事件,通过ApplicationEventPublisher发布,实现组件间解耦通信。
        b.自定义事件示例
            ---
            // 定义数据迁移事件
            public class DataMigrationEvent {
                private final String version;
                private final boolean success;
                private final long duration;

                public DataMigrationEvent(String version, boolean success, long duration) {
                    this.version = version;
                    this.success = success;
                    this.duration = duration;
                }

                public String getVersion() { return version; }
                public boolean isSuccess() { return success; }
                public long getDuration() { return duration; }
            }

            // 发布事件
            import io.micronaut.context.event.ApplicationEventPublisher;

            @Singleton
            public class DataMigrationService {
                private final ApplicationEventPublisher<DataMigrationEvent> eventPublisher;

                public DataMigrationService(
                    ApplicationEventPublisher<DataMigrationEvent> eventPublisher) {
                    this.eventPublisher = eventPublisher;
                }

                public void migrate() {
                    long start = System.currentTimeMillis();
                    String version = "1.0.0";

                    try {
                        // 执行迁移
                        executeMigration(version);

                        long duration = System.currentTimeMillis() - start;
                        // 发布成功事件
                        eventPublisher.publishEvent(
                            new DataMigrationEvent(version, true, duration));

                    } catch (Exception e) {
                        long duration = System.currentTimeMillis() - start;
                        // 发布失败事件
                        eventPublisher.publishEvent(
                            new DataMigrationEvent(version, false, duration));
                        throw e;
                    }
                }

                private void executeMigration(String version) {
                    // 迁移逻辑
                }
            }

            // 监听迁移事件
            @Singleton
            public class MigrationEventListener implements
                ApplicationEventListener<DataMigrationEvent> {

                @Inject
                private AuditLogger auditLogger;

                @Inject
                private MetricsService metricsService;

                @Override
                public void onApplicationEvent(DataMigrationEvent event) {
                    // 记录审计日���
                    auditLogger.log("数据迁移",
                        "版本: " + event.getVersion() +
                        ", 结果: " + (event.isSuccess() ? "成功" : "失败") +
                        ", 耗时: " + event.getDuration() + "ms");

                    // 记录指标
                    metricsService.recordMigration(
                        event.getVersion(),
                        event.isSuccess(),
                        event.getDuration()
                    );

                    // 失败时告警
                    if (!event.isSuccess()) {
                        sendAlert("数据迁移失败: " + event.getVersion());
                    }
                }

                private void sendAlert(String message) {
                    // 发送告警
                }
            }
            ---

03.Bean销毁
    a.@PreDestroy注解
        a.销毁回调
            @PreDestroy方法在Bean销毁前执行,用于关闭连接、释放资源、清理缓存等清理操作。
        b.PreDestroy示例
            ---
            import jakarta.annotation.PreDestroy;
            import jakarta.inject.Singleton;

            @Singleton
            public class ConnectionManager {
                private final List<Connection> connections = new ArrayList<>();

                public Connection getConnection() {
                    Connection conn = createConnection();
                    connections.add(conn);
                    return conn;
                }

                @PreDestroy
                public void cleanup() {
                    System.out.println("@PreDestroy:开始清理连接");

                    for (Connection conn : connections) {
                        try {
                            if (!conn.isClosed()) {
                                conn.close();
                                System.out.println("连接已关闭");
                            }
                        } catch (SQLException e) {
                            System.err.println("关闭连接失败: " + e.getMessage());
                        }
                    }

                    connections.clear();
                    System.out.println("所有连接已清理");
                }

                private Connection createConnection() {
                    // 创建连接
                    return null;
                }
            }

            // 实现Closeable接口
            @Singleton
            public class ResourceHolder implements Closeable {
                private InputStream inputStream;

                public ResourceHolder() throws IOException {
                    this.inputStream = new FileInputStream("/data/resource.dat");
                }

                @Override
                @PreDestroy
                public void close() throws IOException {
                    if (inputStream != null) {
                        inputStream.close();
                        System.out.println("资源已关闭");
                    }
                }
            }
            ---
    b.销毁顺序
        a.依赖反向销毁
            Bean销毁顺序与创建顺序相反,先销毁依赖其他Bean的Bean,后销毁被依赖的Bean,确保销毁时依赖仍可用。
        b.销毁顺序示例
            ---
            // Bean依赖关系:Controller -> Service -> Repository -> DataSource

            @Singleton
            public class DataSource {
                @PreDestroy
                public void close() {
                    System.out.println("4. DataSource销毁");
                }
            }

            @Singleton
            public class Repository {
                private final DataSource dataSource;

                public Repository(DataSource dataSource) {
                    this.dataSource = dataSource;
                }

                @PreDestroy
                public void cleanup() {
                    System.out.println("3. Repository销毁");
                }
            }

            @Singleton
            public class Service {
                private final Repository repository;

                public Service(Repository repository) {
                    this.repository = repository;
                }

                @PreDestroy
                public void cleanup() {
                    System.out.println("2. Service销毁");
                }
            }

            @Controller("/api")
            public class Controller {
                private final Service service;

                public Controller(Service service) {
                    this.service = service;
                }

                @PreDestroy
                public void cleanup() {
                    System.out.println("1. Controller销毁");
                }
            }

            // 应用关闭输出顺序
            // 1. Controller销毁
            // 2. Service销毁
            // 3. Repository销毁
            // 4. DataSource销毁
            ---

02.生命周期接口
    a.Lifecycle接口
        a.接口定义
            实现io.micronaut.context.LifeCycle接口可以更精细地控制Bean的启动和停止逻辑。
        b.Lifecycle实现
            ---
            import io.micronaut.context.LifeCycle;
            import jakarta.inject.Singleton;

            @Singleton
            public class BackgroundTaskManager implements LifeCycle<BackgroundTaskManager> {
                private ScheduledExecutorService executor;
                private volatile boolean running = false;

                @Override
                public BackgroundTaskManager start() {
                    System.out.println("启动后台任务管理器");
                    executor = Executors.newScheduledThreadPool(4);
                    running = true;

                    // 启动定时任务
                    executor.scheduleAtFixedRate(
                        () -> System.out.println("执行后台任务"),
                        0, 10, TimeUnit.SECONDS
                    );

                    return this;
                }

                @Override
                public BackgroundTaskManager stop() {
                    System.out.println("停止后台任务管理器");
                    running = false;

                    if (executor != null) {
                        executor.shutdown();
                        try {
                            if (!executor.awaitTermination(30, TimeUnit.SECONDS)) {
                                executor.shutdownNow();
                            }
                        } catch (InterruptedException e) {
                            executor.shutdownNow();
                        }
                    }

                    return this;
                }

                @Override
                public boolean isRunning() {
                    return running;
                }
            }

            // 启动和停止由BeanContext自动管理
            // 应用启动时自动调用start()
            // 应用关闭时自动调用stop()
            ---
    b.DisposableBean接口
        a.资源释放
            实现DisposableBean接口的dispose()方法,在Bean销毁时释放资源。
        b.DisposableBean示例
            ---
            import io.micronaut.context.annotation.Bean;
            import io.micronaut.context.annotation.Factory;
            import io.micronaut.core.io.Closeable;

            @Factory
            public class ResourceFactory {
                @Bean
                @Singleton
                public CustomResource createResource() {
                    return new CustomResource();
                }
            }

            public class CustomResource implements Closeable {
                private final FileChannel channel;

                public CustomResource() throws IOException {
                    this.channel = FileChannel.open(
                        Paths.get("/data/resource.dat"),
                        StandardOpenOption.READ
                    );
                    System.out.println("资源已打开");
                }

                public ByteBuffer read(int size) throws IOException {
                    ByteBuffer buffer = ByteBuffer.allocate(size);
                    channel.read(buffer);
                    return buffer;
                }

                @Override
                public void close() throws IOException {
                    if (channel != null && channel.isOpen()) {
                        channel.close();
                        System.out.println("资源已关闭");
                    }
                }
            }

            // BeanContext关闭时自动调用close()
            ---

03.作用域生命周期
    a.RequestScope生命周期
        a.请求级Bean
            @RequestScope标记的Bean在每个HTTP请求开始时创建,请求结束时销毁,适合存储请求级上下文信息。
        b.RequestScope示例
            ---
            import io.micronaut.runtime.http.scope.RequestScope;
            import jakarta.annotation.PreDestroy;

            @RequestScope
            public class RequestTraceContext {
                private final String traceId;
                private final long startTime;
                private Map<String, Object> attributes;

                public RequestTraceContext() {
                    this.traceId = UUID.randomUUID().toString();
                    this.startTime = System.currentTimeMillis();
                    this.attributes = new HashMap<>();
                    System.out.println("请求上下文创建: " + traceId);
                }

                public void setAttribute(String key, Object value) {
                    attributes.put(key, value);
                }

                public Object getAttribute(String key) {
                    return attributes.get(key);
                }

                public String getTraceId() {
                    return traceId;
                }

                public long getElapsedTime() {
                    return System.currentTimeMillis() - startTime;
                }

                @PreDestroy
                public void cleanup() {
                    long duration = getElapsedTime();
                    System.out.println("请求完成: " + traceId + ", 耗时: " + duration + "ms");
                    attributes.clear();
                }
            }

            // 在同一请求中共享RequestTraceContext
            @Controller("/api")
            public class ApiController {
                private final RequestTraceContext traceContext;
                private final LogService logService;

                public ApiController(RequestTraceContext traceContext,
                                   LogService logService) {
                    this.traceContext = traceContext;
                    this.logService = logService;
                }

                @Get("/users/{id}")
                public User getUser(Long id) {
                    traceContext.setAttribute("user_id", id);
                    logService.log("查询用户: " + id);
                    return userService.findById(id);
                }
            }

            @Singleton
            public class LogService {
                private final RequestTraceContext traceContext;  // 同一实例

                public LogService(RequestTraceContext traceContext) {
                    this.traceContext = traceContext;
                }

                public void log(String message) {
                    System.out.println("[" + traceContext.getTraceId() + "] " + message);
                }
            }
            ---
    b.Refreshable生命周期
        a.配置刷新重建
            @Refreshable标记的Bean在配置刷新时会被销毁并重新创建,获取最新的配置值。
        b.Refreshable示例
            ---
            import io.micronaut.context.annotation.Refreshable;
            import io.micronaut.context.annotation.ConfigurationProperties;
            import jakarta.annotation.PostConstruct;
            import jakarta.annotation.PreDestroy;

            @Refreshable
            @ConfigurationProperties("cache")
            public class CacheConfig {
                private int maxSize;
                private Duration ttl;

                public CacheConfig() {
                    System.out.println("CacheConfig创建");
                }

                @PostConstruct
                public void init() {
                    System.out.println("CacheConfig初始化: maxSize=" + maxSize +
                                     ", ttl=" + ttl);
                }

                @PreDestroy
                public void cleanup() {
                    System.out.println("CacheConfig销毁(配置已变更)");
                }

                // getter和setter省略
            }

            @Singleton
            public class CacheManager {
                private final CacheConfig config;

                public CacheManager(CacheConfig config) {
                    this.config = config;
                }

                public void printConfig() {
                    // 总是访问最新的CacheConfig实例
                    System.out.println("当前缓存配置: " + config.getMaxSize());
                }
            }

            // 配置刷新流程
            // 1. POST /refresh
            // 2. 重新加载配置文件
            // 3. 调用CacheConfig.cleanup()(@PreDestroy)
            // 4. 销毁旧CacheConfig实例
            // 5. 创建新CacheConfig实例
            // 6. 调用CacheConfig.init()(@PostConstruct)
            // 7. 重新注入到CacheManager
            ---

04.优雅关闭
    a.关闭流程
        a.优雅关闭机制
            应用接收到关闭信号时,先停止接受新请求,等待现有请求处理完成,然后依次销毁Bean,最后关闭线程池。
        b.关闭流程示例
            ---
            // application.yml配置
            // micronaut:
            //   server:
            //     shutdown:
            //       grace-period: 30s  # 优雅关闭等待时间

            // 监控关闭过程
            import io.micronaut.runtime.event.ShutdownEvent;
            import io.micronaut.runtime.server.event.ServerShutdownEvent;

            @Singleton
            public class ShutdownMonitor implements
                ApplicationEventListener<ShutdownEvent> {

                @Inject
                private ActiveRequestTracker requestTracker;

                @Override
                public void onApplicationEvent(ShutdownEvent event) {
                    System.out.println("收到关闭信号");

                    // 等待活跃请求完成
                    int activeRequests = requestTracker.getActiveCount();
                    System.out.println("当前活跃请求数: " + activeRequests);

                    while (activeRequests > 0) {
                        try {
                            Thread.sleep(1000);
                            activeRequests = requestTracker.getActiveCount();
                            System.out.println("等待请求完成,剩余: " + activeRequests);
                        } catch (InterruptedException e) {
                            break;
                        }
                    }

                    System.out.println("所有请求已完成,开始销毁Bean");
                }
            }

            // 关闭流程
            // 1. 接收SIGTERM信号
            // 2. 触发ShutdownEvent
            // 3. HTTP服务器停止接受新连接
            // 4. 等待活跃请求完成(最多30秒)
            // 5. 按依赖反向顺序销毁Bean
            // 6. 调用所有@PreDestroy方法
            // 7. 关闭线程池
            // 8. JVM退出
            ---
    b.关闭Hook
        a.JVM关闭Hook
            Micronaut自动注册JVM关闭Hook,确保应用被kill时也能执行清理逻辑。
        b.关闭Hook示例
            ---
            import jakarta.inject.Singleton;

            @Singleton
            public class CustomShutdownHook {
                public CustomShutdownHook() {
                    // 注册自定义关闭Hook
                    Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                        System.out.println("JVM即将退出,执行最后的清理");
                        // 刷新日志缓冲区
                        // 保存临时数据
                        // 发送关闭通知
                    }));
                }

                @PreDestroy
                public void cleanup() {
                    System.out.println("Bean销毁前的清理");
                }
            }

            // 关闭方式对比
            // kill -15 <pid>   (SIGTERM)  → 优雅关闭,执行@PreDestroy和Hook
            // kill -9 <pid>    (SIGKILL)  → 强制终止,无法执行清理
            // Ctrl+C                      → 优雅关闭,执行@PreDestroy和Hook
            // context.close()             → 程序关闭,执行@PreDestroy
            ---

3 依赖注入详解

3.1 注解驱动注入

01.JSR-330标准注解
    a.@Inject注解
        a.注入标记
            @Inject是JSR-330标准注解,用于标记需要依赖注入的构造器、字段或方法,Micronaut完全支持此标准,保证代码可移植性。
        b.Inject使用示例
            ---
            import jakarta.inject.Inject;
            import jakarta.inject.Singleton;

            @Singleton
            public class OrderService {
                // 字段注入
                @Inject
                private OrderRepository orderRepository;

                @Inject
                private PaymentService paymentService;

                private NotificationService notificationService;

                // 构造器注入(推荐方式)
                // 单个构造器时@Inject可省略
                public OrderService() {
                    System.out.println("无参构造器");
                }

                // 方法注入
                @Inject
                public void setNotificationService(NotificationService service) {
                    this.notificationService = service;
                    System.out.println("方法注入完成");
                }

                public Order createOrder(OrderRequest request) {
                    Order order = new Order(request);
                    orderRepository.save(order);
                    paymentService.process(order);
                    notificationService.notify(order);
                    return order;
                }
            }

            // 注入执行顺序
            // 1. 调用构造器
            // 2. 注入@Inject字段
            // 3. 调用@Inject方法
            // 4. 调用@PostConstruct方法

            // 构造器注入示例(推荐)
            @Singleton
            public class UserService {
                private final UserRepository repository;
                private final EmailService emailService;

                // 单构造器时@Inject可省略
                public UserService(UserRepository repository,
                                 EmailService emailService) {
                    this.repository = repository;
                    this.emailService = emailService;
                }
            }

            // 多构造器时必须标记@Inject
            @Singleton
            public class ProductService {
                private final ProductRepository repository;
                private final CacheService cacheService;

                // 默认构造器
                public ProductService() {
                    this(null, null);
                }

                // 注入构造器
                @Inject
                public ProductService(ProductRepository repository,
                                    CacheService cacheService) {
                    this.repository = repository;
                    this.cacheService = cacheService;
                }
            }
            ---
    b.@Singleton注解
        a.单例作用域
            @Singleton是JSR-330标准注解,标记Bean为单例作用域,整个应用生命周期内只创建一次。
        b.Singleton示例
            ---
            import jakarta.inject.Singleton;
            import java.util.concurrent.ConcurrentHashMap;
            import java.util.concurrent.atomic.AtomicLong;

            @Singleton
            public class SessionManager {
                private final Map<String, Session> sessions = new ConcurrentHashMap<>();
                private final AtomicLong sessionCounter = new AtomicLong(0);

                public String createSession(String userId) {
                    String sessionId = UUID.randomUUID().toString();
                    Session session = new Session(sessionId, userId);
                    sessions.put(sessionId, session);
                    sessionCounter.incrementAndGet();
                    System.out.println("创建会话: " + sessionId);
                    return sessionId;
                }

                public Session getSession(String sessionId) {
                    return sessions.get(sessionId);
                }

                public void invalidateSession(String sessionId) {
                    sessions.remove(sessionId);
                    System.out.println("会话失效: " + sessionId);
                }

                public long getActiveSessionCount() {
                    return sessions.size();
                }

                public long getTotalSessionCount() {
                    return sessionCounter.get();
                }
            }

            // 任何地方注入的都是同一个SessionManager实例
            @Controller("/auth")
            public class AuthController {
                private final SessionManager sessionManager;

                public AuthController(SessionManager sessionManager) {
                    this.sessionManager = sessionManager;
                }

                @Post("/login")
                public LoginResponse login(@Body LoginRequest request) {
                    String sessionId = sessionManager.createSession(request.getUserId());
                    return new LoginResponse(sessionId);
                }
            }

            @Controller("/api")
            public class ApiController {
                private final SessionManager sessionManager;  // 同一实例

                public ApiController(SessionManager sessionManager) {
                    this.sessionManager = sessionManager;
                }

                @Get("/session/count")
                public long getSessionCount() {
                    return sessionManager.getActiveSessionCount();
                }
            }
            ---
    c.@Named注解
        a.Bean限定符
            @Named注解为Bean指定名称,用于区分同类型的多个Bean实现。
        b.Named使用示例
            ---
            import jakarta.inject.Named;
            import jakarta.inject.Singleton;

            // 定义接口
            public interface DataSource {
                Connection getConnection();
            }

            // 主数据源
            @Singleton
            @Named("primary")
            public class PrimaryDataSource implements DataSource {
                @Override
                public Connection getConnection() {
                    System.out.println("获取主库连接");
                    return createConnection("jdbc:mysql://master:3306/db");
                }

                private Connection createConnection(String url) {
                    // 创建连接
                    return null;
                }
            }

            // 从数据源
            @Singleton
            @Named("secondary")
            public class SecondaryDataSource implements DataSource {
                @Override
                public Connection getConnection() {
                    System.out.println("获取从库连接");
                    return createConnection("jdbc:mysql://slave:3306/db");
                }

                private Connection createConnection(String url) {
                    return null;
                }
            }

            // 注入指定名称的Bean
            @Singleton
            public class UserRepository {
                private final DataSource primaryDataSource;
                private final DataSource secondaryDataSource;

                public UserRepository(
                    @Named("primary") DataSource primaryDataSource,
                    @Named("secondary") DataSource secondaryDataSource) {
                    this.primaryDataSource = primaryDataSource;
                    this.secondaryDataSource = secondaryDataSource;
                }

                public User findById(Long id) {
                    // 写操作使用主库
                    Connection conn = primaryDataSource.getConnection();
                    return queryUser(conn, id);
                }

                public List<User> search(String keyword) {
                    // 读操作使用从库
                    Connection conn = secondaryDataSource.getConnection();
                    return searchUsers(conn, keyword);
                }

                private User queryUser(Connection conn, Long id) {
                    return null;
                }

                private List<User> searchUsers(Connection conn, String keyword) {
                    return Collections.emptyList();
                }
            }
            ---

02.Micronaut扩展注解
    a.@Primary注解
        a.首选Bean
            @Primary注解标记首选Bean,当存在多个同类型Bean且未指定@Named时,优先注入标记为@Primary的Bean。
        b.Primary示例
            ---
            import io.micronaut.context.annotation.Primary;
            import jakarta.inject.Singleton;

            public interface CacheProvider {
                void put(String key, Object value);
                Object get(String key);
            }

            // Redis缓存实现(首选)
            @Singleton
            @Primary
            public class RedisCacheProvider implements CacheProvider {
                @Override
                public void put(String key, Object value) {
                    System.out.println("Redis缓存写入: " + key);
                }

                @Override
                public Object get(String key) {
                    System.out.println("Redis缓存读取: " + key);
                    return null;
                }
            }

            // 内存缓存实现
            @Singleton
            public class InMemoryCacheProvider implements CacheProvider {
                private final Map<String, Object> cache = new ConcurrentHashMap<>();

                @Override
                public void put(String key, Object value) {
                    cache.put(key, value);
                    System.out.println("内存缓存写入: " + key);
                }

                @Override
                public Object get(String key) {
                    System.out.println("内存缓存读取: " + key);
                    return cache.get(key);
                }
            }

            // 不指定@Named时注入Primary Bean
            @Singleton
            public class ProductService {
                private final CacheProvider cacheProvider;  // 注入RedisCacheProvider

                public ProductService(CacheProvider cacheProvider) {
                    this.cacheProvider = cacheProvider;
                    System.out.println("注入的缓存提供者: " +
                                     cacheProvider.getClass().getSimpleName());
                }

                public Product getProduct(Long id) {
                    Object cached = cacheProvider.get("product:" + id);
                    if (cached != null) {
                        return (Product) cached;
                    }

                    Product product = productRepository.findById(id);
                    cacheProvider.put("product:" + id, product);
                    return product;
                }
            }

            // 明确注入非Primary Bean
            @Singleton
            public class BackupService {
                private final CacheProvider memoryCache;

                public BackupService(@Named("inMemoryCacheProvider") CacheProvider memoryCache) {
                    this.memoryCache = memoryCache;
                }
            }
            ---
    b.@Requires条件注入
        a.条件Bean创建
            @Requires注解根据条件决定是否创建Bean,条件包括配置属性、环境、类路径、Bean存在性等。
        b.Requires示例
            ---
            import io.micronaut.context.annotation.Requires;
            import jakarta.inject.Singleton;

            // 条件1:配置属性存在且为true
            @Singleton
            @Requires(property = "redis.enabled", value = "true")
            public class RedisCacheService implements CacheService {
                @Override
                public void cache(String key, Object value) {
                    System.out.println("使用Redis缓存");
                }
            }

            // 条件2:配置属性不为true(默认false)
            @Singleton
            @Requires(property = "redis.enabled", value = "false", defaultValue = "false")
            public class LocalCacheService implements CacheService {
                @Override
                public void cache(String key, Object value) {
                    System.out.println("使用本地缓存");
                }
            }

            // 条件3:类路径存在指定类
            @Singleton
            @Requires(classes = com.mysql.cj.jdbc.Driver.class)
            public class MySQLDataSource implements DataSource {
                // MySQL驱动存在时才创建
            }

            // 条件4:Bean存在
            @Singleton
            @Requires(beans = DataSource.class)
            public class DatabaseMigration {
                // 仅当DataSource Bean存在时创建
            }

            // 条件5:Bean不存在
            @Singleton
            @Requires(missingBeans = CustomAuthProvider.class)
            public class DefaultAuthProvider implements AuthProvider {
                // 仅当CustomAuthProvider不存在时创建
            }

            // 条件6:指定环境
            @Singleton
            @Requires(env = "dev")
            public class MockEmailService implements EmailService {
                @Override
                public void send(String to, String subject, String body) {
                    System.out.println("Mock发送邮件到: " + to);
                }
            }

            @Singleton
            @Requires(env = "prod")
            public class SmtpEmailService implements EmailService {
                @Override
                public void send(String to, String subject, String body) {
                    System.out.println("通过SMTP发送邮件到: " + to);
                }
            }

            // 条件7:非指定环境
            @Singleton
            @Requires(notEnv = "test")
            public class ProductionMetrics {
                // 非test环境时创建
            }

            // 条件8:SDK版本
            @Singleton
            @Requires(sdk = Requires.Sdk.JAVA, value = "17")
            public class Java17Feature {
                // 仅Java 17及以上版本创建
            }

            // 条件9:配置属性匹配模式
            @Singleton
            @Requires(property = "datasource.url", pattern = "jdbc:mysql:.*")
            public class MySQLSpecificConfig {
                // 仅当数据库URL为MySQL时创建
            }

            // 条件10:多条件组合(AND关系)
            @Singleton
            @Requires(property = "feature.enabled", value = "true")
            @Requires(env = "prod")
            @Requires(beans = DataSource.class)
            public class AdvancedFeature {
                // 所有条件都满足时才创建
            }
            ---
    c.@Factory工厂类
        a.工厂模式
            @Factory注解标记工厂类,类中的@Bean方法可以创建和配置第三方Bean,适合无法添加@Singleton注解的外部类。
        b.Factory示例
            ---
            import io.micronaut.context.annotation.Factory;
            import io.micronaut.context.annotation.Bean;
            import jakarta.inject.Singleton;
            import com.zaxxer.hikari.HikariConfig;
            import com.zaxxer.hikari.HikariDataSource;

            @Factory
            public class DataSourceFactory {
                // 创建HikariCP数据源
                @Bean
                @Singleton
                @Named("primary")
                public DataSource primaryDataSource(
                    @Value("${datasource.primary.url}") String url,
                    @Value("${datasource.primary.username}") String username,
                    @Value("${datasource.primary.password}") String password) {

                    HikariConfig config = new HikariConfig();
                    config.setJdbcUrl(url);
                    config.setUsername(username);
                    config.setPassword(password);
                    config.setMaximumPoolSize(20);
                    config.setMinimumIdle(5);
                    config.setConnectionTimeout(30000);
                    config.setIdleTimeout(600000);
                    config.setMaxLifetime(1800000);

                    System.out.println("创建主数据源: " + url);
                    return new HikariDataSource(config);
                }

                // 创建从数据源
                @Bean
                @Singleton
                @Named("secondary")
                public DataSource secondaryDataSource(
                    @Value("${datasource.secondary.url}") String url,
                    @Value("${datasource.secondary.username}") String username,
                    @Value("${datasource.secondary.password}") String password) {

                    HikariConfig config = new HikariConfig();
                    config.setJdbcUrl(url);
                    config.setUsername(username);
                    config.setPassword(password);
                    config.setMaximumPoolSize(10);

                    System.out.println("创建从数据源: " + url);
                    return new HikariDataSource(config);
                }

                // 创建ObjectMapper
                @Bean
                @Singleton
                public ObjectMapper objectMapper() {
                    ObjectMapper mapper = new ObjectMapper();
                    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
                    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
                    mapper.registerModule(new JavaTimeModule());
                    return mapper;
                }

                // 条件化工厂方法
                @Bean
                @Singleton
                @Requires(property = "aws.enabled", value = "true")
                public AmazonS3 amazonS3(
                    @Value("${aws.access-key}") String accessKey,
                    @Value("${aws.secret-key}") String secretKey,
                    @Value("${aws.region}") String region) {

                    AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
                    return AmazonS3ClientBuilder.standard()
                        .withCredentials(new AWSStaticCredentialsProvider(credentials))
                        .withRegion(region)
                        .build();
                }
            }

            // 使用工厂创建的Bean
            @Singleton
            public class UserRepository {
                private final DataSource dataSource;
                private final ObjectMapper objectMapper;

                public UserRepository(
                    @Named("primary") DataSource dataSource,
                    ObjectMapper objectMapper) {
                    this.dataSource = dataSource;
                    this.objectMapper = objectMapper;
                }
            }
            ---

02.泛型注入
    a.泛型Bean
        a.泛型类型保留
            Micronaut在编译期保留完整的泛型类型信息,支持注入泛型Bean,类型参数精确匹配。
        b.泛型注入示例
            ---
            import jakarta.inject.Singleton;

            // 定义泛型接口
            public interface Repository<T, ID> {
                T findById(ID id);
                List<T> findAll();
                T save(T entity);
                void deleteById(ID id);
            }

            // 泛型实现1:User Repository
            @Singleton
            public class UserRepository implements Repository<User, Long> {
                @Override
                public User findById(Long id) {
                    System.out.println("查询用户: " + id);
                    return new User(id, "User" + id);
                }

                @Override
                public List<User> findAll() {
                    return Arrays.asList(new User(1L, "Alice"), new User(2L, "Bob"));
                }

                @Override
                public User save(User entity) {
                    System.out.println("保存用户: " + entity.getName());
                    return entity;
                }

                @Override
                public void deleteById(Long id) {
                    System.out.println("删除用户: " + id);
                }
            }

            // 泛型实现2:Product Repository
            @Singleton
            public class ProductRepository implements Repository<Product, String> {
                @Override
                public Product findById(String id) {
                    System.out.println("查询产品: " + id);
                    return new Product(id, "Product-" + id);
                }

                @Override
                public List<Product> findAll() {
                    return Arrays.asList(
                        new Product("P001", "商品1"),
                        new Product("P002", "商品2")
                    );
                }

                @Override
                public Product save(Product entity) {
                    System.out.println("保存产品: " + entity.getName());
                    return entity;
                }

                @Override
                public void deleteById(String id) {
                    System.out.println("删除产品: " + id);
                }
            }

            // 注入泛型Bean(类型精确匹配)
            @Singleton
            public class UserService {
                private final Repository<User, Long> userRepository;

                public UserService(Repository<User, Long> userRepository) {
                    this.userRepository = userRepository;  // 注入UserRepository
                }

                public User getUser(Long id) {
                    return userRepository.findById(id);
                }
            }

            @Singleton
            public class ProductService {
                private final Repository<Product, String> productRepository;

                public ProductService(Repository<Product, String> productRepository) {
                    this.productRepository = productRepository;  // 注入ProductRepository
                }

                public Product getProduct(String id) {
                    return productRepository.findById(id);
                }
            }

            // Micronaut根据泛型参数精确匹配Bean
            // Repository<User, Long> → UserRepository
            // Repository<Product, String> → ProductRepository
            ---
    b.Provider注入
        a.延迟获取
            Provider<T>接口提供延迟获取Bean的能力,在需要时才从容器获取Bean实例,可以解决循环依赖和提升启动性能。
        b.Provider示例
            ---
            import jakarta.inject.Provider;
            import jakarta.inject.Singleton;

            // 场景1:解决循环依赖
            @Singleton
            public class ServiceA {
                private final Provider<ServiceB> serviceBProvider;

                public ServiceA(Provider<ServiceB> serviceBProvider) {
                    this.serviceBProvider = serviceBProvider;
                    System.out.println("ServiceA创建");
                }

                public void doSomething() {
                    // 延迟获取ServiceB
                    ServiceB serviceB = serviceBProvider.get();
                    serviceB.process();
                }
            }

            @Singleton
            public class ServiceB {
                private final ServiceA serviceA;

                public ServiceB(ServiceA serviceA) {
                    this.serviceA = serviceA;
                    System.out.println("ServiceB创建");
                }

                public void process() {
                    System.out.println("ServiceB处理业务");
                }
            }

            // 场景2:获取Prototype Bean
            @Singleton
            public class TaskManager {
                private final Provider<TaskExecutor> executorProvider;

                public TaskManager(Provider<TaskExecutor> executorProvider) {
                    this.executorProvider = executorProvider;
                }

                public void executeTasks(List<Task> tasks) {
                    for (Task task : tasks) {
                        // 每个任务使用新的Executor实例
                        TaskExecutor executor = executorProvider.get();
                        executor.execute(task);
                    }
                }
            }

            @Prototype
            public class TaskExecutor {
                private final String executorId = UUID.randomUUID().toString();

                public void execute(Task task) {
                    System.out.println("Executor " + executorId + " 执行任务: " + task);
                }
            }

            // 场景3:条件获取Bean
            @Singleton
            public class NotificationService {
                private final Provider<EmailService> emailProvider;
                private final Provider<SmsService> smsProvider;

                public NotificationService(
                    Provider<EmailService> emailProvider,
                    Provider<SmsService> smsProvider) {
                    this.emailProvider = emailProvider;
                    this.smsProvider = smsProvider;
                }

                public void notify(String userId, String message, NotificationType type) {
                    switch (type) {
                        case EMAIL:
                            emailProvider.get().send(userId, message);
                            break;
                        case SMS:
                            smsProvider.get().send(userId, message);
                            break;
                        case BOTH:
                            emailProvider.get().send(userId, message);
                            smsProvider.get().send(userId, message);
                            break;
                    }
                }
            }
            ---

3.2 构造器注入

01.构造器注入最佳实践
    a.推荐使用原因
        a.不可变性保证
            构造器注入允许将依赖字段声明为final,保证对象创建后依赖不可变,提高线程安全性和代码可预测性。
        b.依赖明确性
            所有依赖在构造器参数中明确声明,一眼就能看出类的依赖关系,便于理解和维护。
        c.易于测试
            ---
            import jakarta.inject.Singleton;

            @Singleton
            public class OrderService {
                private final OrderRepository orderRepository;
                private final PaymentGateway paymentGateway;
                private final NotificationService notificationService;
                private final AuditLogger auditLogger;

                // 构造器注入:所有依赖声明为final
                public OrderService(OrderRepository orderRepository,
                                  PaymentGateway paymentGateway,
                                  NotificationService notificationService,
                                  AuditLogger auditLogger) {
                    this.orderRepository = orderRepository;
                    this.paymentGateway = paymentGateway;
                    this.notificationService = notificationService;
                    this.auditLogger = auditLogger;
                }

                public Order createOrder(OrderRequest request) {
                    // 创建订单
                    Order order = new Order(request);
                    orderRepository.save(order);

                    // 处理支付
                    PaymentResult payment = paymentGateway.charge(
                        request.getUserId(),
                        request.getAmount()
                    );

                    if (!payment.isSuccess()) {
                        throw new PaymentFailedException("支付失败");
                    }

                    // 发送通知
                    notificationService.sendOrderConfirmation(order);

                    // 记录审计日志
                    auditLogger.log("订单创建", order.getId());

                    return order;
                }
            }

            // 单元测试(无需Micronaut容器)
            import org.junit.jupiter.api.Test;
            import org.mockito.Mockito;

            public class OrderServiceTest {
                @Test
                public void testCreateOrder() {
                    // 创建Mock依赖
                    OrderRepository mockRepository = Mockito.mock(OrderRepository.class);
                    PaymentGateway mockGateway = Mockito.mock(PaymentGateway.class);
                    NotificationService mockNotification = Mockito.mock(NotificationService.class);
                    AuditLogger mockLogger = Mockito.mock(AuditLogger.class);

                    // 直接通过构造器创建服务实例
                    OrderService service = new OrderService(
                        mockRepository,
                        mockGateway,
                        mockNotification,
                        mockLogger
                    );

                    // 配置Mock行为
                    Mockito.when(mockGateway.charge(Mockito.any(), Mockito.any()))
                        .thenReturn(PaymentResult.success());

                    // 测试
                    OrderRequest request = new OrderRequest(1L, 100.0);
                    Order order = service.createOrder(request);

                    // 验证
                    Mockito.verify(mockRepository).save(Mockito.any(Order.class));
                    Mockito.verify(mockGateway).charge(1L, 100.0);
                }
            }
            ---
    b.多构造器处理
        a.@Inject标记
            当类有多个构造器时,必须使用@Inject标记用于依赖注入的构造器。
        b.多构造器示例
            ---
            import jakarta.inject.Inject;
            import jakarta.inject.Singleton;

            @Singleton
            public class ReportService {
                private final ReportRepository repository;
                private final TemplateEngine templateEngine;
                private final ExportService exportService;

                // 默认构造器(用于测试)
                public ReportService() {
                    this(null, null, null);
                }

                // 部分依赖构造器
                public ReportService(ReportRepository repository) {
                    this(repository, new DefaultTemplateEngine(), null);
                }

                // 完整依赖构造器(标记@Inject)
                @Inject
                public ReportService(ReportRepository repository,
                                   TemplateEngine templateEngine,
                                   ExportService exportService) {
                    this.repository = repository;
                    this.templateEngine = templateEngine;
                    this.exportService = exportService;
                    System.out.println("使用完整依赖创建ReportService");
                }

                public Report generateReport(String templateName, Map<String, Object> data) {
                    String content = templateEngine.render(templateName, data);
                    Report report = new Report(content);
                    repository.save(report);
                    return report;
                }

                public byte[] exportToPdf(Long reportId) {
                    Report report = repository.findById(reportId);
                    return exportService.toPdf(report);
                }
            }

            // Micronaut会调用标记@Inject的构造器
            // 如果没有@Inject标记且有多个构造器,编译报错
            ---

02.构造器参数处理
    a.可选依赖
        a.@Nullable注解
            构造器参数可以标记@Nullable,表示该依赖是可选的,容器中不存在时注入null。
        b.可选依赖示例
            ---
            import io.micronaut.core.annotation.Nullable;
            import jakarta.inject.Singleton;

            @Singleton
            public class EmailService {
                private final SmtpClient smtpClient;
                private final EmailTemplate templateEngine;
                private final AttachmentService attachmentService;  // 可选依赖

                public EmailService(
                    SmtpClient smtpClient,
                    EmailTemplate templateEngine,
                    @Nullable AttachmentService attachmentService) {  // 可选

                    this.smtpClient = smtpClient;
                    this.templateEngine = templateEngine;
                    this.attachmentService = attachmentService;

                    if (attachmentService == null) {
                        System.out.println("AttachmentService不可用,禁用附件功能");
                    }
                }

                public void sendEmail(String to, String subject, String body) {
                    String html = templateEngine.render(body);
                    smtpClient.send(to, subject, html);
                }

                public void sendEmailWithAttachment(String to, String subject,
                                                   String body, File attachment) {
                    if (attachmentService == null) {
                        throw new UnsupportedOperationException("附件服务不可用");
                    }

                    String html = templateEngine.render(body);
                    byte[] attachmentData = attachmentService.readFile(attachment);
                    smtpClient.sendWithAttachment(to, subject, html, attachmentData);
                }
            }

            // Optional包装
            @Singleton
            public class CacheService {
                private final CacheProvider primaryCache;
                private final Optional<CacheProvider> secondaryCache;

                public CacheService(
                    @Named("primary") CacheProvider primaryCache,
                    @Named("secondary") Optional<CacheProvider> secondaryCache) {

                    this.primaryCache = primaryCache;
                    this.secondaryCache = secondaryCache;
                }

                public void put(String key, Object value) {
                    primaryCache.put(key, value);

                    // 双写到备用缓存
                    secondaryCache.ifPresent(cache -> cache.put(key, value));
                }
            }
            ---
    b.默认值参数
        a.@Value注入配置
            构造器参数可以使用@Value注解注入配置值,支持默认值。
        b.配置参数示例
            ---
            import io.micronaut.context.annotation.Value;
            import jakarta.inject.Singleton;
            import java.time.Duration;

            @Singleton
            public class HttpClientService {
                private final String baseUrl;
                private final Duration timeout;
                private final int maxRetries;
                private final boolean enableLogging;

                public HttpClientService(
                    @Value("${api.base-url}") String baseUrl,
                    @Value("${api.timeout:30s}") Duration timeout,
                    @Value("${api.max-retries:3}") int maxRetries,
                    @Value("${api.logging.enabled:false}") boolean enableLogging) {

                    this.baseUrl = baseUrl;
                    this.timeout = timeout;
                    this.maxRetries = maxRetries;
                    this.enableLogging = enableLogging;

                    System.out.println("HTTP客户端配置:");
                    System.out.println("  Base URL: " + baseUrl);
                    System.out.println("  Timeout: " + timeout);
                    System.out.println("  Max Retries: " + maxRetries);
                    System.out.println("  Logging: " + enableLogging);
                }

                public ApiResponse callApi(String endpoint) {
                    String url = baseUrl + endpoint;
                    if (enableLogging) {
                        System.out.println("调用API: " + url);
                    }
                    // API调用逻辑
                    return new ApiResponse();
                }
            }

            // 混合注入Bean和配置
            @Singleton
            public class DatabaseService {
                private final DataSource dataSource;
                private final String schema;
                private final int queryTimeout;

                public DatabaseService(
                    DataSource dataSource,  // 注入Bean
                    @Value("${database.schema:public}") String schema,  // 注入配置
                    @Value("${database.query-timeout:30}") int queryTimeout) {

                    this.dataSource = dataSource;
                    this.schema = schema;
                    this.queryTimeout = queryTimeout;
                }

                public List<User> queryUsers() {
                    try (Connection conn = dataSource.getConnection()) {
                        Statement stmt = conn.createStatement();
                        stmt.setQueryTimeout(queryTimeout);
                        ResultSet rs = stmt.executeQuery(
                            "SELECT * FROM " + schema + ".users"
                        );
                        return mapResultSet(rs);
                    } catch (SQLException e) {
                        throw new RuntimeException("查询失败", e);
                    }
                }

                private List<User> mapResultSet(ResultSet rs) throws SQLException {
                    List<User> users = new ArrayList<>();
                    while (rs.next()) {
                        users.add(new User(rs.getLong("id"), rs.getString("name")));
                    }
                    return users;
                }
            }
            ---

03.构造器验证
    a.参数验证
        a.Bean Validation集成
            构造器参数可以使用Bean Validation注解进行验证,Micronaut在Bean创建时自动执行验证。
        b.验证示例
            ---
            import io.micronaut.context.annotation.ConfigurationProperties;
            import jakarta.validation.constraints.*;
            import jakarta.inject.Singleton;

            @ConfigurationProperties("server")
            public class ServerConfig {
                @NotBlank(message = "主机名不能为空")
                private String host;

                @Min(value = 1, message = "端口必须大于0")
                @Max(value = 65535, message = "端口必须小于65536")
                private int port;

                @NotNull
                @Pattern(regexp = "https?://.*", message = "URL格式无效")
                private String baseUrl;

                // 构造器验证
                public ServerConfig(
                    @NotBlank String host,
                    @Min(1) @Max(65535) int port,
                    @NotNull String baseUrl) {

                    this.host = host;
                    this.port = port;
                    this.baseUrl = baseUrl;
                }

                // getter和setter省略
            }

            // 验证失败时抛出异常
            // application.yml配置错误
            // server:
            //   host: ""        # 空字符串,违反@NotBlank
            //   port: 99999     # 超出范围,违反@Max
            //   base-url: "invalid"  # 格式错误,违反@Pattern

            // 启动时抛出异常
            // jakarta.validation.ConstraintViolationException:
            //   - host: 主机名不能为空
            //   - port: 端口必须小于65536
            //   - baseUrl: URL格式无效

            // 自定义验证器
            import jakarta.validation.Constraint;
            import jakarta.validation.ConstraintValidator;
            import jakarta.validation.ConstraintValidatorContext;

            @Constraint(validatedBy = UrlValidator.class)
            @Retention(RetentionPolicy.RUNTIME)
            @Target({ElementType.PARAMETER, ElementType.FIELD})
            public @interface ValidUrl {
                String message() default "URL格式无效";
                Class<?>[] groups() default {};
                Class<? extends Payload>[] payload() default {};
            }

            public class UrlValidator implements
                ConstraintValidator<ValidUrl, String> {

                @Override
                public boolean isValid(String value,
                                     ConstraintValidatorContext context) {
                    if (value == null || value.isEmpty()) {
                        return false;
                    }
                    try {
                        new URL(value);
                        return true;
                    } catch (MalformedURLException e) {
                        return false;
                    }
                }
            }

            // 使用自定义验证器
            @Singleton
            public class ApiClient {
                private final String apiUrl;

                public ApiClient(@ValidUrl String apiUrl) {
                    this.apiUrl = apiUrl;
                }
            }
            ---
    b.依赖检查
        a.编译时检查
            Micronaut在编译期检查构造器参数的依赖是否存在,提前发现依赖缺失问题。
        b.依赖检查示例
            ---
            // 定义服务
            @Singleton
            public class UserService {
                private final UserRepository repository;
                private final EmailService emailService;

                public UserService(UserRepository repository,
                                 EmailService emailService) {
                    this.repository = repository;
                    this.emailService = emailService;
                }
            }

            // 场景1:缺少EmailService Bean
            // 如果项目中没有定义EmailService的实现
            // 编译时报错:
            // error: No bean of type [EmailService] exists.
            //        Make sure the bean is not disabled by bean requirements
            //        and if the bean is enabled then ensure the class is
            //        declared a bean.

            // 场景2:循环依赖
            @Singleton
            public class ServiceA {
                public ServiceA(ServiceB serviceB) {
                }
            }

            @Singleton
            public class ServiceB {
                public ServiceB(ServiceA serviceA) {
                }
            }

            // 编译时报错:
            // error: Circular dependency detected:
            //   ServiceA -> ServiceB -> ServiceA

            // 解决方案:使用Provider
            @Singleton
            public class ServiceA {
                private final Provider<ServiceB> serviceBProvider;

                public ServiceA(Provider<ServiceB> serviceBProvider) {
                    this.serviceBProvider = serviceBProvider;
                }

                public void doSomething() {
                    ServiceB serviceB = serviceBProvider.get();
                    serviceB.process();
                }
            }
            ---

02.构造器重载
    a.多构造器场景
        a.构造器选择
            当类有多个构造器时,Micronaut优先选择参数最多的构造器,或选择标记@Inject的构造器。
        b.构造器选择示例
            ---
            import jakarta.inject.Inject;
            import jakarta.inject.Singleton;

            @Singleton
            public class DataProcessor {
                private final DataSource dataSource;
                private final DataValidator validator;
                private final DataTransformer transformer;

                // 构造器1:最少依赖(用于测试)
                public DataProcessor(DataSource dataSource) {
                    this(dataSource, new DefaultValidator(), new DefaultTransformer());
                    System.out.println("使用构造器1");
                }

                // 构造器2:部分依赖
                public DataProcessor(DataSource dataSource, DataValidator validator) {
                    this(dataSource, validator, new DefaultTransformer());
                    System.out.println("使用构造器2");
                }

                // 构造器3:完整依赖(标记@Inject,优先使用)
                @Inject
                public DataProcessor(DataSource dataSource,
                                   DataValidator validator,
                                   DataTransformer transformer) {
                    this.dataSource = dataSource;
                    this.validator = validator;
                    this.transformer = transformer;
                    System.out.println("使用构造器3(完整依赖)");
                }

                public ProcessResult process(Data data) {
                    if (!validator.validate(data)) {
                        throw new ValidationException("数据验证失败");
                    }

                    Data transformed = transformer.transform(data);
                    saveToDatabase(dataSource, transformed);

                    return ProcessResult.success();
                }

                private void saveToDatabase(DataSource ds, Data data) {
                    // 保存逻辑
                }
            }

            // Micronaut注入时使用构造器3
            // 输出:使用构造器3(完整依赖)
            ---
    b.Builder模式集成
        a.工厂方法
            对于使用Builder模式的类,可以通过@Factory方法创建Bean。
        b.Builder示例
            ---
            // 第三方库的Builder类
            public class HttpClientConfig {
                private String baseUrl;
                private Duration timeout;
                private int maxRetries;

                private HttpClientConfig() {}

                public static Builder builder() {
                    return new Builder();
                }

                public static class Builder {
                    private String baseUrl;
                    private Duration timeout = Duration.ofSeconds(30);
                    private int maxRetries = 3;

                    public Builder baseUrl(String baseUrl) {
                        this.baseUrl = baseUrl;
                        return this;
                    }

                    public Builder timeout(Duration timeout) {
                        this.timeout = timeout;
                        return this;
                    }

                    public Builder maxRetries(int maxRetries) {
                        this.maxRetries = maxRetries;
                        return this;
                    }

                    public HttpClientConfig build() {
                        HttpClientConfig config = new HttpClientConfig();
                        config.baseUrl = this.baseUrl;
                        config.timeout = this.timeout;
                        config.maxRetries = this.maxRetries;
                        return config;
                    }
                }

                // getter方法省略
            }

            // 使用Factory创建Bean
            import io.micronaut.context.annotation.Factory;
            import io.micronaut.context.annotation.Bean;

            @Factory
            public class HttpClientConfigFactory {
                @Bean
                @Singleton
                public HttpClientConfig httpClientConfig(
                    @Value("${http.client.base-url}") String baseUrl,
                    @Value("${http.client.timeout:30s}") Duration timeout,
                    @Value("${http.client.max-retries:3}") int maxRetries) {

                    return HttpClientConfig.builder()
                        .baseUrl(baseUrl)
                        .timeout(timeout)
                        .maxRetries(maxRetries)
                        .build();
                }
            }

            // 注入配置Bean
            @Singleton
            public class ApiService {
                private final HttpClientConfig config;

                public ApiService(HttpClientConfig config) {
                    this.config = config;
                    System.out.println("API配置: " + config.getBaseUrl());
                }
            }
            ---

03.构造器依赖排序
    a.依赖拓扑排序
        a.创建顺序
            Micronaut根据Bean之间的依赖关系进行拓扑排序,确保依赖的Bean先于依赖它的Bean创建。
        b.排序示例
            ---
            // 定义4层依赖关系
            @Singleton
            public class Layer1Config {
                public Layer1Config() {
                    System.out.println("1. Layer1Config创建(无依赖)");
                }
            }

            @Singleton
            public class Layer2DataSource {
                private final Layer1Config config;

                public Layer2DataSource(Layer1Config config) {
                    this.config = config;
                    System.out.println("2. Layer2DataSource创建(依赖Layer1)");
                }
            }

            @Singleton
            public class Layer2Cache {
                private final Layer1Config config;

                public Layer2Cache(Layer1Config config) {
                    this.config = config;
                    System.out.println("3. Layer2Cache创建(依赖Layer1)");
                }
            }

            @Singleton
            public class Layer3Repository {
                private final Layer2DataSource dataSource;

                public Layer3Repository(Layer2DataSource dataSource) {
                    this.dataSource = dataSource;
                    System.out.println("4. Layer3Repository创建(依赖Layer2DataSource)");
                }
            }

            @Singleton
            public class Layer3Service {
                private final Layer2DataSource dataSource;
                private final Layer2Cache cache;

                public Layer3Service(Layer2DataSource dataSource, Layer2Cache cache) {
                    this.dataSource = dataSource;
                    this.cache = cache;
                    System.out.println("5. Layer3Service创建(依赖Layer2DataSource和Layer2Cache)");
                }
            }

            @Singleton
            public class Layer4Controller {
                private final Layer3Repository repository;
                private final Layer3Service service;

                public Layer4Controller(Layer3Repository repository, Layer3Service service) {
                    this.repository = repository;
                    this.service = service;
                    System.out.println("6. Layer4Controller创建(依赖Layer3)");
                }
            }

            // 依赖关系图
            // Layer1Config
            //   ├── Layer2DataSource
            //   │     ├── Layer3Repository
            //   │     │     └── Layer4Controller
            //   │     └── Layer3Service
            //   │           └── Layer4Controller
            //   └── Layer2Cache
            //         └── Layer3Service

            // Micronaut创建顺序(拓扑排序)
            // 1. Layer1Config
            // 2. Layer2DataSource
            // 3. Layer2Cache
            // 4. Layer3Repository
            // 5. Layer3Service
            // 6. Layer4Controller

            // 启动输出
            // 1. Layer1Config创建(无依赖)
            // 2. Layer2DataSource创建(依赖Layer1)
            // 3. Layer2Cache创建(依赖Layer1)
            // 4. Layer3Repository创建(依赖Layer2DataSource)
            // 5. Layer3Service创建(依赖Layer2DataSource和Layer2Cache)
            // 6. Layer4Controller创建(依赖Layer3)
            ---
    b.并行实例化
        a.无依赖Bean并行创建
            对于没有依赖关系的Bean,Micronaut可以并行创建,提升启动速度。
        b.并行创建示例
            ---
            // 独立的服务Bean(无相互依赖)
            @Singleton
            public class MetricsService {
                public MetricsService() {
                    System.out.println(Thread.currentThread().getName() +
                                     ": MetricsService创建");
                    simulateInitialization();
                }

                private void simulateInitialization() {
                    try { Thread.sleep(100); } catch (InterruptedException e) {}
                }
            }

            @Singleton
            public class LoggingService {
                public LoggingService() {
                    System.out.println(Thread.currentThread().getName() +
                                     ": LoggingService创建");
                    simulateInitialization();
                }

                private void simulateInitialization() {
                    try { Thread.sleep(100); } catch (InterruptedException e) {}
                }
            }

            @Singleton
            public class CacheService {
                public CacheService() {
                    System.out.println(Thread.currentThread().getName() +
                                     ": CacheService创建");
                    simulateInitialization();
                }

                private void simulateInitialization() {
                    try { Thread.sleep(100); } catch (InterruptedException e) {}
                }
            }

            // 这3个Bean无相互依赖,可以并行创建
            // 输出示例(线程名可能不同)
            // ForkJoinPool-1: MetricsService创建
            // ForkJoinPool-2: LoggingService创建
            // ForkJoinPool-3: CacheService创建

            // 串行创建耗时:300ms
            // 并行创建耗时:100ms
            // 性能提升:3倍
            ---

3.3 字段注入与方法注入

01.字段注入
    a.字段注入语法
        a.@Inject字段
            通过@Inject注解标记字段实现依赖注入,Micronaut在Bean创建后自动为字段赋值,但不推荐使用此方式。
        b.字段注入示例
            ---
            import jakarta.inject.Inject;
            import jakarta.inject.Singleton;

            @Singleton
            public class ReportGenerator {
                // 字段注入
                @Inject
                private TemplateEngine templateEngine;

                @Inject
                private DataSource dataSource;

                @Inject
                @Named("pdf")
                private ExportService pdfExporter;

                @Inject
                @Named("excel")
                private ExportService excelExporter;

                public Report generateReport(String templateName, Map<String, Object> data) {
                    // 使用注入的依赖
                    String content = templateEngine.render(templateName, data);
                    Report report = new Report(content);

                    // 保存到数据库
                    try (Connection conn = dataSource.getConnection()) {
                        saveReport(conn, report);
                    } catch (SQLException e) {
                        throw new RuntimeException("保存报告失败", e);
                    }

                    return report;
                }

                public byte[] exportToPdf(Long reportId) {
                    Report report = loadReport(reportId);
                    return pdfExporter.export(report);
                }

                public byte[] exportToExcel(Long reportId) {
                    Report report = loadReport(reportId);
                    return excelExporter.export(report);
                }

                private void saveReport(Connection conn, Report report) {
                    // 保存逻辑
                }

                private Report loadReport(Long reportId) {
                    return new Report();
                }
            }

            // 字段注入的缺点
            // 1. 字段不能声明为final,对象可变
            // 2. 依赖关系不明确,需要查看字段定义
            // 3. 单元测试困难,无法直接new对象
            // 4. 可能出现NullPointerException(依赖未注入就调用)
            // 5. 破坏封装性,字段通常应该是private
            ---
    b.字段注入陷阱
        a.NullPointerException风险
            字段注入在构造器执行时依赖尚未注入,如果在构造器中使用依赖字段会导致NPE。
        b.NPE示例
            ---
            import jakarta.inject.Inject;
            import jakarta.inject.Singleton;

            @Singleton
            public class RiskyService {
                @Inject
                private ConfigService configService;

                public RiskyService() {
                    // ❌ 错误:此时configService还未注入,值为null
                    // String value = configService.getValue();  // NullPointerException!

                    System.out.println("构造器执行,configService=" +
                                     (configService == null ? "null" : "not null"));
                }

                @PostConstruct
                public void init() {
                    // ✅ 正确:@PostConstruct时字段已注入
                    String value = configService.getValue();
                    System.out.println("配置值: " + value);
                }

                public void doSomething() {
                    // ✅ 正确:实例方法调用时字段已注入
                    configService.update("key", "value");
                }
            }

            // 注入执行顺序
            // 1. 调用构造器(此时@Inject字段为null)
            // 2. 注入@Inject字段
            // 3. 调用@PostConstruct方法
            // 因此在构造器中不能使用@Inject字段!

            // 推荐使用构造器注入避免此问题
            @Singleton
            public class SafeService {
                private final ConfigService configService;

                public SafeService(ConfigService configService) {
                    // ✅ 安全:构造器参数已经是注入的实例
                    this.configService = configService;
                    String value = configService.getValue();  // 不会NPE
                    System.out.println("配置值: " + value);
                }
            }
            ---

02.方法注入
    a.Setter注入
        a.方法注入语法
            通过@Inject标记setter方法实现依赖注入,适合可选依赖或需要在Bean创建后动态配置的场景。
        b.Setter注入示例
            ---
            import jakarta.inject.Inject;
            import jakarta.inject.Singleton;
            import io.micronaut.core.annotation.Nullable;

            @Singleton
            public class EmailService {
                private final SmtpConfig config;
                private EmailTemplate defaultTemplate;
                private AttachmentHandler attachmentHandler;  // 可选依赖

                // 构造器注入必需依赖
                public EmailService(SmtpConfig config) {
                    this.config = config;
                    System.out.println("EmailService创建,config已注入");
                }

                // 方法注入:设置默认模板
                @Inject
                public void setDefaultTemplate(EmailTemplate defaultTemplate) {
                    this.defaultTemplate = defaultTemplate;
                    System.out.println("默认模板已注入");
                }

                // 方法注入:可选的附件处理器
                @Inject
                public void setAttachmentHandler(
                    @Nullable AttachmentHandler attachmentHandler) {
                    this.attachmentHandler = attachmentHandler;

                    if (attachmentHandler != null) {
                        System.out.println("附件处理器已注入");
                    } else {
                        System.out.println("附件处理器不可用");
                    }
                }

                public void sendEmail(String to, String subject, String body) {
                    String content = defaultTemplate.render(body);
                    send(to, subject, content);
                }

                public void sendEmailWithAttachment(String to, String subject,
                                                   String body, File file) {
                    if (attachmentHandler == null) {
                        throw new UnsupportedOperationException("附件功能不可用");
                    }

                    String content = defaultTemplate.render(body);
                    byte[] attachment = attachmentHandler.process(file);
                    sendWithAttachment(to, subject, content, attachment);
                }

                private void send(String to, String subject, String content) {
                    System.out.println("发送邮件到: " + to);
                }

                private void sendWithAttachment(String to, String subject,
                                              String content, byte[] attachment) {
                    System.out.println("发送带附件的邮件到: " + to);
                }
            }

            // 注入执行顺序
            // 1. 调用构造器(config注入)
            // 2. 调用setDefaultTemplate(defaultTemplate注入)
            // 3. 调用setAttachmentHandler(attachmentHandler注入)
            // 4. 调用@PostConstruct方法
            ---
    b.多参数方法注入
        a.方法注入多个依赖
            @Inject方法可以有多个参数,Micronaut会注入所有参数。
        b.多参数注入示例
            ---
            import jakarta.inject.Inject;
            import jakarta.inject.Singleton;

            @Singleton
            public class OrderProcessor {
                private InventoryService inventoryService;
                private PaymentService paymentService;
                private ShippingService shippingService;

                // 方法注入多个依赖
                @Inject
                public void setDependencies(
                    InventoryService inventoryService,
                    PaymentService paymentService,
                    ShippingService shippingService) {

                    this.inventoryService = inventoryService;
                    this.paymentService = paymentService;
                    this.shippingService = shippingService;

                    System.out.println("3个依赖已通过方法注入");
                }

                public void processOrder(Order order) {
                    // 检查库存
                    boolean inStock = inventoryService.checkStock(order.getItems());
                    if (!inStock) {
                        throw new OutOfStockException();
                    }

                    // 处理支付
                    PaymentResult payment = paymentService.charge(order);
                    if (!payment.isSuccess()) {
                        throw new PaymentFailedException();
                    }

                    // 安排发货
                    shippingService.schedule(order);
                }
            }

            // 多个@Inject方法
            @Singleton
            public class ComplexService {
                private DataSource dataSource;
                private CacheService cacheService;
                private MetricsService metricsService;
                private LoggingService loggingService;

                @Inject
                public void setDataAccess(DataSource dataSource, CacheService cacheService) {
                    this.dataSource = dataSource;
                    this.cacheService = cacheService;
                    System.out.println("数据访问依赖已注入");
                }

                @Inject
                public void setObservability(MetricsService metricsService,
                                            LoggingService loggingService) {
                    this.metricsService = metricsService;
                    this.loggingService = loggingService;
                    System.out.println("可观测性依赖已注入");
                }

                // 所有@Inject方法都会被调用
            }
            ---

03.注入方式对比
    a.三种注入方式比较
        a.构造器vs字段vs方法
            构造器注入保证不可变性和依赖完整性,字段注入简洁但不安全,方法注入适合可选依赖,应根据场景选择。
        b.对比示例
            ---
            // 推荐:构造器注入
            @Singleton
            public class GoodService {
                private final Repository repository;      // final,不可变
                private final Validator validator;        // final,不可变

                public GoodService(Repository repository, Validator validator) {
                    this.repository = repository;
                    this.validator = validator;
                    // 依赖在对象创建时就已确定
                }
            }

            // 优点:
            // ✅ 字段可以是final,保证不可变
            // ✅ 依赖明确,构造器签名清晰展示依赖
            // ✅ 便于测试,直接new对象传入mock
            // ✅ 不会出现NPE,构造器执行时依赖已就绪
            // ✅ 编译期检查依赖完整性

            // 不推荐:字段注入
            @Singleton
            public class BadService {
                @Inject
                private Repository repository;  // 不能是final
                @Inject
                private Validator validator;    // 不能是final

                public BadService() {
                    // 构造器中不能使用依赖(此时为null)
                }
            }

            // 缺点:
            // ❌ 字段不能是final,对象可变
            // ❌ 依赖隐藏,需要查看字段定义
            // ❌ 测试困难,必须通过容器创建
            // ❌ 可能NPE,构造器中依赖未就绪
            // ❌ 无编译期检查,运行时才发现依赖缺失

            // 适用场景:方法注入
            @Singleton
            public class FlexibleService {
                private final Repository repository;  // 必需依赖
                private CacheService cacheService;    // 可选依赖

                // 构造器注入必需依赖
                public FlexibleService(Repository repository) {
                    this.repository = repository;
                }

                // 方法注入可选依赖
                @Inject
                public void setCacheService(@Nullable CacheService cacheService) {
                    this.cacheService = cacheService;
                }

                public Data getData(String key) {
                    // 尝试从缓存获取
                    if (cacheService != null) {
                        Data cached = cacheService.get(key);
                        if (cached != null) return cached;
                    }

                    // 从数据库查询
                    Data data = repository.findByKey(key);

                    // 写入缓存
                    if (cacheService != null) {
                        cacheService.put(key, data);
                    }

                    return data;
                }
            }

            // 适用场景:
            // ✅ 可选依赖(依赖可能不存在)
            // ✅ 循环依赖(通过setter打破循环)
            // ✅ 需要重新配置依赖的场景
            ---
    b.性能对比
        a.注入性能
            构造器注入和字段注入的性能几乎相同,因为都是编译时生成代码,方法注入略有额外开销(多一次方法调用)。
        b.性能测试
            ---
            // 性能测试代码
            import io.micronaut.context.ApplicationContext;

            public class InjectionPerformanceTest {
                public static void main(String[] args) {
                    ApplicationContext context = ApplicationContext.run();

                    // 测试构造器注入
                    long start1 = System.nanoTime();
                    for (int i = 0; i < 10000; i++) {
                        context.createBean(ConstructorInjectionService.class);
                    }
                    long duration1 = System.nanoTime() - start1;
                    System.out.println("构造器注入: " + duration1 / 1_000_000 + "ms");

                    // 测试字段注入
                    long start2 = System.nanoTime();
                    for (int i = 0; i < 10000; i++) {
                        context.createBean(FieldInjectionService.class);
                    }
                    long duration2 = System.nanoTime() - start2;
                    System.out.println("字段注入: " + duration2 / 1_000_000 + "ms");

                    // 测试方法注入
                    long start3 = System.nanoTime();
                    for (int i = 0; i < 10000; i++) {
                        context.createBean(MethodInjectionService.class);
                    }
                    long duration3 = System.nanoTime() - start3;
                    System.out.println("方法注入: " + duration3 / 1_000_000 + "ms");

                    context.close();
                }
            }

            // 测试结果(10000次Bean创建)
            // 构造器注入: 85ms
            // 字段注入: 87ms
            // 方法注入: 92ms

            // 性能差异很小,优先考虑代码质量和可维护性
            // 推荐使用构造器注入
            ---

02.Setter方法注入
    a.标准Setter
        a.Bean属性设置
            Setter方法注入遵循JavaBean规范,方法名以set开头,接受一个参数。
        b.Setter示例
            ---
            import jakarta.inject.Inject;
            import jakarta.inject.Singleton;

            @Singleton
            public class ConfigurableService {
                private final DatabaseConfig dbConfig;  // 必需,构造器注入
                private CacheConfig cacheConfig;        // 可选,setter注入
                private int maxRetries = 3;             // 可选,默认值
                private Duration timeout = Duration.ofSeconds(30);

                public ConfigurableService(DatabaseConfig dbConfig) {
                    this.dbConfig = dbConfig;
                }

                @Inject
                public void setCacheConfig(@Nullable CacheConfig cacheConfig) {
                    this.cacheConfig = cacheConfig;
                    if (cacheConfig != null) {
                        System.out.println("缓存配置已设置");
                    }
                }

                @Inject
                public void setMaxRetries(@Value("${service.max-retries:3}") int maxRetries) {
                    this.maxRetries = maxRetries;
                    System.out.println("最大重试次数: " + maxRetries);
                }

                @Inject
                public void setTimeout(@Value("${service.timeout:30s}") Duration timeout) {
                    this.timeout = timeout;
                    System.out.println("超时时间: " + timeout);
                }

                public void execute() {
                    // 使用配置
                    System.out.println("数据库: " + dbConfig.getUrl());

                    if (cacheConfig != null) {
                        System.out.println("缓存: " + cacheConfig.getProvider());
                    }

                    System.out.println("最大重试: " + maxRetries);
                    System.out.println("超时: " + timeout);
                }
            }
            ---
    b.自定义方法注入
        a.任意方法名
            @Inject可以标记任意public方法,不限于setter方法,方法可以有多个参数。
        b.自定义方法示例
            ---
            import jakarta.inject.Inject;
            import jakarta.inject.Singleton;

            @Singleton
            public class OrderService {
                private OrderRepository repository;
                private PaymentService paymentService;
                private NotificationService notificationService;

                // 自定义方法名
                @Inject
                public void configureDependencies(
                    OrderRepository repository,
                    PaymentService paymentService) {

                    this.repository = repository;
                    this.paymentService = paymentService;
                    System.out.println("核心依赖已配置");
                }

                // 另一个注入方法
                @Inject
                public void setupNotification(NotificationService notificationService) {
                    this.notificationService = notificationService;
                    System.out.println("通知服务已配置");
                }

                // 初始化方法(在所有注入完成后执行)
                @PostConstruct
                public void initialize() {
                    System.out.println("所有依赖已就绪,初始化完成");
                }

                public Order createOrder(OrderRequest request) {
                    Order order = repository.save(new Order(request));
                    paymentService.process(order);
                    notificationService.notify(order);
                    return order;
                }
            }

            // 注入执行顺序
            // 1. 调用构造器
            // 2. 调用configureDependencies方法
            // 3. 调用setupNotification方法
            // 4. 调用initialize方法(@PostConstruct)
            ---

03.注入方式选择指南
    a.决策树
        a.选择流程
            根据依赖特性选择合适的注入方式,优先使用构造器注入,特殊场景才使用字段或方法注入。
        b.选择建议
            ---
            // 决策流程
            // 1. 依赖是否必需?
            //    ├─ 是 → 使用构造器注入
            //    └─ 否 → 继续判断
            //
            // 2. 依赖是否需要声明为final?
            //    ├─ 是 → 使用构造器注入
            //    └─ 否 → 继续判断
            //
            // 3. 是否需要在Bean创建后重新配置?
            //    ├─ 是 → 使用方法注入
            //    └─ 否 → 继续判断
            //
            // 4. 是否存在循环依赖?
            //    ├─ 是 → 使用Provider或方法注入
            //    └─ 否 → 使用构造器注入

            // 示例1:必需依赖 → 构造器注入
            @Singleton
            public class UserService {
                private final UserRepository repository;  // 必需

                public UserService(UserRepository repository) {
                    this.repository = repository;
                }
            }

            // 示例2:可选依赖 → 方法注入
            @Singleton
            public class EmailService {
                private final SmtpClient smtpClient;  // 必需
                private AttachmentService attachmentService;  // 可选

                public EmailService(SmtpClient smtpClient) {
                    this.smtpClient = smtpClient;
                }

                @Inject
                public void setAttachmentService(@Nullable AttachmentService service) {
                    this.attachmentService = service;
                }
            }

            // 示例3:循环依赖 → Provider
            @Singleton
            public class ServiceA {
                private final Provider<ServiceB> serviceBProvider;

                public ServiceA(Provider<ServiceB> serviceBProvider) {
                    this.serviceBProvider = serviceBProvider;
                }
            }

            // 示例4:大量依赖 → 考虑重构
            @Singleton
            public class GodService {
                // ❌ 不推荐:依赖过多,违反单一职责原则
                public GodService(
                    Dep1 d1, Dep2 d2, Dep3 d3, Dep4 d4, Dep5 d5,
                    Dep6 d6, Dep7 d7, Dep8 d8, Dep9 d9, Dep10 d10) {
                    // 依赖超过5个时应考虑拆分服务
                }
            }

            // ✅ 推荐:拆分为多个职责单一的服务
            @Singleton
            public class UserService {
                private final UserRepository repository;
                private final UserValidator validator;

                public UserService(UserRepository repository, UserValidator validator) {
                    this.repository = repository;
                    this.validator = validator;
                }
            }

            @Singleton
            public class OrderService {
                private final OrderRepository repository;
                private final PaymentService paymentService;

                public OrderService(OrderRepository repository, PaymentService paymentService) {
                    this.repository = repository;
                    this.paymentService = paymentService;
                }
            }
            ---
    b.最佳实践总结
        a.推荐模式
            优先使用构造器注入,依赖声明为final,每个类的依赖数量控制在5个以内,遵循单一职责原则。
        b.反模式
            ---
            // ❌ 反模式1:字段注入 + 在构造器中使用
            @Singleton
            public class BadService1 {
                @Inject
                private ConfigService config;

                public BadService1() {
                    String value = config.getValue();  // NPE!
                }
            }

            // ❌ 反模式2:字段注入 + 无法测试
            @Singleton
            public class BadService2 {
                @Inject
                private ExternalApi externalApi;

                public void process() {
                    externalApi.call();
                }
            }
            // 测试时无法mock externalApi

            // ❌ 反模式3:方法注入 + 必需依赖
            @Singleton
            public class BadService3 {
                private Repository repository;

                @Inject
                public void setRepository(Repository repository) {
                    this.repository = repository;
                }

                public void save(Entity entity) {
                    repository.save(entity);  // 如果setRepository未调用会NPE
                }
            }

            // ✅ 最佳实践
            @Singleton
            public class GoodService {
                private final Repository repository;          // 必需,final
                private final Validator validator;            // 必需,final
                private CacheService cacheService;            // 可选,非final

                // 构造器注入必需依赖
                public GoodService(Repository repository, Validator validator) {
                    this.repository = repository;
                    this.validator = validator;
                }

                // 方法注入可选依赖
                @Inject
                public void setCacheService(@Nullable CacheService cacheService) {
                    this.cacheService = cacheService;
                }

                public Entity save(Entity entity) {
                    if (!validator.validate(entity)) {
                        throw new ValidationException();
                    }

                    repository.save(entity);

                    if (cacheService != null) {
                        cacheService.put(entity.getId(), entity);
                    }

                    return entity;
                }
            }
            ---

3.4 作用域管理

01.内置作用域
    a.@Singleton作用域
        a.全局单例
            @Singleton标记的Bean在整个应用生命周期内只创建一次,所有注入点共享同一实例,适合无状态服务。
        b.单例示例
            ---
            import jakarta.inject.Singleton;

            @Singleton
            public class ConfigurationService {
                private final Map<String, String> config;

                public ConfigurationService() {
                    System.out.println("ConfigurationService实例化");
                    this.config = loadConfig();
                }

                private Map<String, String> loadConfig() {
                    // 加载配置文件
                    Map<String, String> map = new HashMap<>();
                    map.put("app.name", "MyApp");
                    map.put("app.version", "1.0.0");
                    return map;
                }

                public String get(String key) {
                    return config.get(key);
                }
            }

            // 验证单例行为
            @Singleton
            public class ServiceA {
                private final ConfigurationService configService;

                public ServiceA(ConfigurationService configService) {
                    this.configService = configService;
                    System.out.println("ServiceA获得ConfigService: " +
                                     System.identityHashCode(configService));
                }
            }

            @Singleton
            public class ServiceB {
                private final ConfigurationService configService;

                public ServiceB(ConfigurationService configService) {
                    this.configService = configService;
                    System.out.println("ServiceB获得ConfigService: " +
                                     System.identityHashCode(configService));
                }
            }

            // 输出结果
            // ConfigurationService实例化
            // ServiceA获得ConfigService: 123456789
            // ServiceB获得ConfigService: 123456789
            // 两个Service获得的是同一个ConfigService实例
            ---
    b.@Prototype作用域
        a.多实例模式
            @Prototype标记的Bean每次注入都会创建新实例,适合有状态的对象或需要隔离的场景。
        b.Prototype示例
            ---
            import io.micronaut.context.annotation.Prototype;
            import java.util.UUID;

            @Prototype
            public class RequestProcessor {
                private final String processorId;
                private final long createTime;
                private int requestCount = 0;

                public RequestProcessor() {
                    this.processorId = UUID.randomUUID().toString();
                    this.createTime = System.currentTimeMillis();
                    System.out.println("创建处理器: " + processorId);
                }

                public void processRequest(String request) {
                    requestCount++;
                    System.out.println("处理器[" + processorId + "] 处理第" +
                                     requestCount + "个请求: " + request);
                }

                public String getProcessorId() {
                    return processorId;
                }
            }

            // 每次注入都创建新实例
            @Singleton
            public class TaskManager {
                private final BeanContext beanContext;

                public TaskManager(BeanContext beanContext) {
                    this.beanContext = beanContext;
                }

                public void executeTasks() {
                    // 获取3个独立的处理器实例
                    RequestProcessor processor1 = beanContext.getBean(RequestProcessor.class);
                    RequestProcessor processor2 = beanContext.getBean(RequestProcessor.class);
                    RequestProcessor processor3 = beanContext.getBean(RequestProcessor.class);

                    // 并行处理
                    processor1.processRequest("Task-1");
                    processor2.processRequest("Task-2");
                    processor3.processRequest("Task-3");

                    System.out.println("Processor1 ID: " + processor1.getProcessorId());
                    System.out.println("Processor2 ID: " + processor2.getProcessorId());
                    System.out.println("Processor3 ID: " + processor3.getProcessorId());
                    // 3个ID都不相同
                }
            }

            // 输出结果
            // 创建处理器: a1b2c3d4-...
            // 创建处理器: e5f6g7h8-...
            // 创建处理器: i9j0k1l2-...
            // 处理器[a1b2c3d4-...] 处理第1个请求: Task-1
            // 处理器[e5f6g7h8-...] 处理第1个请求: Task-2
            // 处理器[i9j0k1l2-...] 处理第1个请求: Task-3
            // Processor1 ID: a1b2c3d4-...
            // Processor2 ID: e5f6g7h8-...
            // Processor3 ID: i9j0k1l2-...
            ---

02.请求作用域
    a.@RequestScope
        a.HTTP请求级别
            @RequestScope标记的Bean在每个HTTP请求开始时创建,请求结束时销毁,同一请求内所有注入点共享实例。
        b.RequestScope示例
            ---
            import io.micronaut.runtime.http.scope.RequestScope;
            import jakarta.annotation.PreDestroy;
            import java.util.UUID;

            @RequestScope
            public class RequestContext {
                private final String requestId;
                private final long startTime;
                private final Map<String, Object> attributes;

                public RequestContext() {
                    this.requestId = UUID.randomUUID().toString();
                    this.startTime = System.currentTimeMillis();
                    this.attributes = new HashMap<>();
                    System.out.println("请求上下文创建: " + requestId);
                }

                public void setAttribute(String key, Object value) {
                    attributes.put(key, value);
                }

                public Object getAttribute(String key) {
                    return attributes.get(key);
                }

                public String getRequestId() {
                    return requestId;
                }

                public long getElapsedTime() {
                    return System.currentTimeMillis() - startTime;
                }

                @PreDestroy
                public void cleanup() {
                    long duration = getElapsedTime();
                    System.out.println("请求完成: " + requestId +
                                     ", 耗时: " + duration + "ms");
                    attributes.clear();
                }
            }

            // 在Controller中使用
            @Controller("/api/orders")
            public class OrderController {
                private final RequestContext requestContext;
                private final OrderService orderService;

                public OrderController(RequestContext requestContext,
                                     OrderService orderService) {
                    this.requestContext = requestContext;
                    this.orderService = orderService;
                }

                @Post
                public Order createOrder(@Body OrderRequest request) {
                    // 设置请求属性
                    requestContext.setAttribute("user_id", request.getUserId());
                    requestContext.setAttribute("ip", request.getIp());

                    // 处理订单
                    Order order = orderService.createOrder(request);

                    // 记录请求信息
                    System.out.println("请求ID: " + requestContext.getRequestId());
                    System.out.println("耗时: " + requestContext.getElapsedTime() + "ms");

                    return order;
                }
            }

            // Service也可以注入同一RequestContext实例
            @Singleton
            public class OrderService {
                private final RequestContext requestContext;
                private final OrderRepository repository;

                public OrderService(RequestContext requestContext,
                                  OrderRepository repository) {
                    this.requestContext = requestContext;
                    this.repository = repository;
                }

                public Order createOrder(OrderRequest request) {
                    // 访问同一请求上下文
                    String requestId = requestContext.getRequestId();
                    Long userId = (Long) requestContext.getAttribute("user_id");

                    System.out.println("[" + requestId + "] 创建订单,用户ID: " + userId);

                    Order order = new Order();
                    order.setUserId(userId);
                    order.setRequestId(requestId);

                    return repository.save(order);
                }
            }

            // 请求流程
            // 1. 收到HTTP请求
            // 2. 创建RequestContext实例
            // 3. 注入到Controller和Service(同一实例)
            // 4. 处理请求
            // 5. 返回响应
            // 6. 调用RequestContext.cleanup()(@PreDestroy)
            // 7. 销毁RequestContext实例
            ---
    b.请��作用域传播
        a.异步场景
            RequestScope在异步执行中不会自动传播,需要手动传递上下文或使用ThreadLocal。
        b.异步处理示例
            ---
            import io.micronaut.scheduling.annotation.Async;
            import java.util.concurrent.CompletableFuture;

            @Singleton
            public class AsyncOrderService {
                private final RequestContext requestContext;

                public AsyncOrderService(RequestContext requestContext) {
                    this.requestContext = requestContext;
                }

                @Async
                public CompletableFuture<Order> createOrderAsync(OrderRequest request) {
                    // ⚠️ 警告:异步方法中RequestContext可能不可用
                    // 因为异步执行在不同线程,请求作用域不会传播

                    // 解决方案1:在调用前保存需要的数据
                    String requestId = requestContext.getRequestId();

                    return CompletableFuture.supplyAsync(() -> {
                        // 使用保存的requestId
                        System.out.println("异步处理订单: " + requestId);
                        return new Order();
                    });
                }
            }

            // 解决方案2:使用ThreadLocal传播上下文
            import io.micronaut.core.propagation.PropagatedContext;

            @Singleton
            public class ImprovedAsyncService {
                private final RequestContext requestContext;

                public ImprovedAsyncService(RequestContext requestContext) {
                    this.requestContext = requestContext;
                }

                @Async
                public CompletableFuture<Order> createOrderAsync(OrderRequest request) {
                    // 捕获当前上下文
                    try (PropagatedContext.Scope scope = PropagatedContext.getOrEmpty().plus(
                        "requestId", requestContext.getRequestId()).propagate()) {

                        return CompletableFuture.supplyAsync(() -> {
                            // 在异步线程中访问传播的上下文
                            String requestId = PropagatedContext.get()
                                .get("requestId", String.class).orElse("unknown");
                            System.out.println("异步处理订单: " + requestId);
                            return new Order();
                        });
                    }
                }
            }
            ---

03.ThreadLocal作用域
    a.@ThreadLocal注解
        a.线程级别隔离
            @ThreadLocal标记的Bean为每个线程创建独立实例,不同线程间互不干扰,适合线程上下文管理。
        b.ThreadLocal示例
            ---
            import io.micronaut.context.annotation.ThreadLocal;
            import java.util.HashMap;
            import java.util.Map;

            @ThreadLocal
            public class ThreadContext {
                private final String threadId;
                private final Map<String, Object> data;

                public ThreadContext() {
                    this.threadId = Thread.currentThread().getName();
                    this.data = new HashMap<>();
                    System.out.println("为线程创建上下文: " + threadId);
                }

                public void set(String key, Object value) {
                    data.put(key, value);
                }

                public Object get(String key) {
                    return data.get(key);
                }

                public String getThreadId() {
                    return threadId;
                }
            }

            // 多线程使用示例
            @Singleton
            public class ParallelProcessor {
                private final ThreadContext threadContext;
                private final ExecutorService executor;

                public ParallelProcessor(ThreadContext threadContext) {
                    this.threadContext = threadContext;
                    this.executor = Executors.newFixedThreadPool(3);
                }

                public void processInParallel() {
                    // 提交3个任务到不同线程
                    for (int i = 1; i <= 3; i++) {
                        int taskId = i;
                        executor.submit(() -> {
                            // 每个线程获得独立的ThreadContext实例
                            threadContext.set("task_id", taskId);
                            threadContext.set("start_time", System.currentTimeMillis());

                            System.out.println("线程 " + threadContext.getThreadId() +
                                             " 处理任务 " + threadContext.get("task_id"));

                            // 模拟处理
                            Thread.sleep(100);

                            long duration = System.currentTimeMillis() -
                                          (Long) threadContext.get("start_time");
                            System.out.println("线程 " + threadContext.getThreadId() +
                                             " 完成,耗时: " + duration + "ms");
                        });
                    }
                }
            }

            // 输出结果
            // 为线程创建上下文: pool-1-thread-1
            // 为线程创建上下文: pool-1-thread-2
            // 为线程创建上下文: pool-1-thread-3
            // 线程 pool-1-thread-1 处理任务 1
            // 线程 pool-1-thread-2 处理任务 2
            // 线程 pool-1-thread-3 处理任务 3
            // 线程 pool-1-thread-1 完成,耗时: 102ms
            // 线程 pool-1-thread-2 完成,耗时: 103ms
            // 线程 pool-1-thread-3 完成,耗时: 101ms
            ---
    b.线程池注意事项
        a.线程复用问题
            使用线程池时,ThreadLocal Bean会在线程首次执行时创建,线程复用时不会重新创建,可能导致状态污染。
        b.清理示例
            ---
            import jakarta.annotation.PreDestroy;

            @ThreadLocal
            public class SafeThreadContext {
                private final Map<String, Object> data = new HashMap<>();

                public void set(String key, Object value) {
                    data.put(key, value);
                }

                public Object get(String key) {
                    return data.get(key);
                }

                // 手动清理方法
                public void clear() {
                    data.clear();
                    System.out.println("线程上下文已清理: " +
                                     Thread.currentThread().getName());
                }

                @PreDestroy
                public void cleanup() {
                    // 线程结束时自动清理
                    clear();
                }
            }

            @Singleton
            public class TaskExecutor {
                private final SafeThreadContext threadContext;

                public TaskExecutor(SafeThreadContext threadContext) {
                    this.threadContext = threadContext;
                }

                public void executeTask(String taskData) {
                    try {
                        // 使用上下文
                        threadContext.set("task_data", taskData);
                        processTask();
                    } finally {
                        // ✅ 重要:任务完成后清理上下文
                        threadContext.clear();
                    }
                }

                private void processTask() {
                    String data = (String) threadContext.get("task_data");
                    System.out.println("处理任务: " + data);
                }
            }
            ---

04.@Refreshable作用域
    a.配置刷新
        a.动态重载
            @Refreshable标记的Bean在配置刷新时会被销毁并重新创建,自动获取最新配置值。
        b.Refreshable示例
            ---
            import io.micronaut.context.annotation.Refreshable;
            import io.micronaut.context.annotation.ConfigurationProperties;
            import jakarta.annotation.PostConstruct;
            import jakarta.annotation.PreDestroy;

            @Refreshable
            @ConfigurationProperties("database")
            public class DatabaseConfig {
                private String url;
                private int maxConnections;
                private Duration connectionTimeout;

                public DatabaseConfig() {
                    System.out.println("DatabaseConfig实例创建");
                }

                @PostConstruct
                public void init() {
                    System.out.println("DatabaseConfig初始化:");
                    System.out.println("  URL: " + url);
                    System.out.println("  最大连接数: " + maxConnections);
                    System.out.println("  超时时间: " + connectionTimeout);
                }

                @PreDestroy
                public void cleanup() {
                    System.out.println("DatabaseConfig销毁(配置已变更)");
                }

                // Getter和Setter
                public String getUrl() { return url; }
                public void setUrl(String url) { this.url = url; }
                public int getMaxConnections() { return maxConnections; }
                public void setMaxConnections(int maxConnections) {
                    this.maxConnections = maxConnections;
                }
                public Duration getConnectionTimeout() { return connectionTimeout; }
                public void setConnectionTimeout(Duration connectionTimeout) {
                    this.connectionTimeout = connectionTimeout;
                }
            }

            // 使用Refreshable Bean
            @Singleton
            public class ConnectionPool {
                private final DatabaseConfig config;

                public ConnectionPool(DatabaseConfig config) {
                    this.config = config;
                }

                public void printConfig() {
                    // 总是访问最新的DatabaseConfig实例
                    System.out.println("当前数据库URL: " + config.getUrl());
                    System.out.println("当前最大连接数: " + config.getMaxConnections());
                }
            }

            // 配置文件 application.yml
            // database:
            //   url: jdbc:mysql://localhost:3306/mydb
            //   max-connections: 10
            //   connection-timeout: 5s

            // 配置刷新流程
            // 1. 修改配置文件或环境变量
            // 2. POST /refresh 触发刷新
            // 3. 调用DatabaseConfig.cleanup()(@PreDestroy)
            // 4. 销毁旧DatabaseConfig实例
            // 5. 重新读取配置
            // 6. 创建新DatabaseConfig实例
            // 7. 调用DatabaseConfig.init()(@PostConstruct)
            // 8. 重新注入到依赖它的Bean
            ---
    b.刷新端点
        a.启用刷新功能
            需要添加management依赖并启用refresh端点,通过HTTP POST触发配置刷新。
        b.刷新配置
            ---
            // pom.xml
            // <dependency>
            //     <groupId>io.micronaut</groupId>
            //     <artifactId>micronaut-management</artifactId>
            // </dependency>

            // application.yml
            // endpoints:
            //   refresh:
            //     enabled: true
            //     sensitive: false  # 开发环境,生产环境应设为true

            // 触发刷新
            // curl -X POST http://localhost:8080/refresh

            // 监听刷新事件
            import io.micronaut.runtime.context.scope.refresh.RefreshEvent;
            import io.micronaut.context.event.ApplicationEventListener;

            @Singleton
            public class RefreshEventListener implements
                ApplicationEventListener<RefreshEvent> {

                @Override
                public void onApplicationEvent(RefreshEvent event) {
                    System.out.println("配置刷新事件触发");
                    System.out.println("刷新的配置键: " + event.getSource());

                    // 执行刷新后的操作
                    // 例如:重新连接数据库、更新缓存配置等
                }
            }

            // 编程式刷新
            import io.micronaut.management.endpoint.refresh.RefreshEndpoint;

            @Singleton
            public class ConfigManager {
                private final RefreshEndpoint refreshEndpoint;

                public ConfigManager(RefreshEndpoint refreshEndpoint) {
                    this.refreshEndpoint = refreshEndpoint;
                }

                public void refreshConfig() {
                    // 编程式触发刷新
                    String[] refreshedKeys = refreshEndpoint.refresh(null);

                    System.out.println("刷新了 " + refreshedKeys.length + " 个配置");
                    for (String key : refreshedKeys) {
                        System.out.println("  - " + key);
                    }
                }
            }
            ---

05.自定义作用域
    a.CustomScope接口
        a.作用域定义
            通过实现CustomScope接口可以创建自定义作用域,控制Bean的创建、缓存和销毁策略。
        b.自定义作用域实现
            ---
            import io.micronaut.context.scope.CustomScope;
            import io.micronaut.context.BeanResolutionContext;
            import io.micronaut.inject.BeanDefinition;
            import io.micronaut.inject.BeanIdentifier;
            import jakarta.inject.Singleton;
            import java.lang.annotation.*;

            // 1. 定义作用域注解
            @Documented
            @Retention(RetentionPolicy.RUNTIME)
            @Target({ElementType.TYPE, ElementType.METHOD})
            @Scope
            public @interface TenantScope {
            }

            // 2. 实现作用域逻辑
            @Singleton
            public class TenantScopeImpl implements CustomScope<TenantScope> {
                // 每个租户一个Bean实例缓存
                private final Map<String, Map<BeanIdentifier, Object>> tenantBeans =
                    new ConcurrentHashMap<>();

                @Override
                public Class<TenantScope> annotationType() {
                    return TenantScope.class;
                }

                @Override
                public <T> T get(BeanResolutionContext resolutionContext,
                               BeanDefinition<T> beanDefinition,
                               BeanIdentifier identifier,
                               Provider<T> provider) {
                    // 获取当前租户ID
                    String tenantId = getCurrentTenantId();

                    // 为每个租户维护独立的Bean缓存
                    Map<BeanIdentifier, Object> beans =
                        tenantBeans.computeIfAbsent(tenantId,
                            k -> new ConcurrentHashMap<>());

                    // 如果租户Bean不存在,创建新实例
                    return (T) beans.computeIfAbsent(identifier, k -> {
                        T bean = provider.get();
                        System.out.println("为租户[" + tenantId + "]创建Bean: " +
                                         beanDefinition.getBeanType().getSimpleName());
                        return bean;
                    });
                }

                @Override
                public <T> Optional<T> remove(BeanIdentifier identifier) {
                    String tenantId = getCurrentTenantId();
                    Map<BeanIdentifier, Object> beans = tenantBeans.get(tenantId);

                    if (beans != null) {
                        T removed = (T) beans.remove(identifier);
                        System.out.println("移除租户[" + tenantId + "]的Bean");
                        return Optional.ofNullable(removed);
                    }

                    return Optional.empty();
                }

                private String getCurrentTenantId() {
                    // 从ThreadLocal或请求头获取租户ID
                    return TenantContext.getCurrentTenantId();
                }

                // 清理指定租户的所有Bean
                public void clearTenant(String tenantId) {
                    Map<BeanIdentifier, Object> beans = tenantBeans.remove(tenantId);
                    if (beans != null) {
                        System.out.println("清理租户[" + tenantId + "]的" +
                                         beans.size() + "个Bean");
                    }
                }
            }

            // 3. 租户上下文管理
            @Singleton
            public class TenantContext {
                private static final ThreadLocal<String> currentTenant =
                    new ThreadLocal<>();

                public static void setCurrentTenantId(String tenantId) {
                    currentTenant.set(tenantId);
                }

                public static String getCurrentTenantId() {
                    String tenantId = currentTenant.get();
                    if (tenantId == null) {
                        throw new IllegalStateException("租户ID未设置");
                    }
                    return tenantId;
                }

                public static void clear() {
                    currentTenant.remove();
                }
            }
            ---
    b.使用自定义作用域
        a.应用场景
            自定义作用域适合多租户系统、会话管理、缓存策略等需要特殊Bean生命周期的场景。
        b.使用示例
            ---
            // 定义租户级别的服务
            @TenantScope
            public class TenantDataSource implements DataSource {
                private final String tenantId;
                private Connection connection;

                public TenantDataSource() {
                    this.tenantId = TenantContext.getCurrentTenantId();
                    System.out.println("创建租户数据源: " + tenantId);
                }

                @PostConstruct
                public void init() throws SQLException {
                    // 根据租户ID连接到对应数据库
                    String url = "jdbc:mysql://localhost:3306/tenant_" + tenantId;
                    this.connection = DriverManager.getConnection(url);
                    System.out.println("租户[" + tenantId + "]数据库连接已建立");
                }

                @Override
                public Connection getConnection() throws SQLException {
                    return connection;
                }

                @PreDestroy
                public void cleanup() throws SQLException {
                    if (connection != null && !connection.isClosed()) {
                        connection.close();
                        System.out.println("租户[" + tenantId + "]数据库连接已关闭");
                    }
                }
            }

            // 租户级别的Repository
            @TenantScope
            public class TenantUserRepository {
                private final TenantDataSource dataSource;

                public TenantUserRepository(TenantDataSource dataSource) {
                    this.dataSource = dataSource;
                    System.out.println("创建租户Repository");
                }

                public List<User> findAll() throws SQLException {
                    try (Connection conn = dataSource.getConnection();
                         Statement stmt = conn.createStatement();
                         ResultSet rs = stmt.executeQuery("SELECT * FROM users")) {

                        List<User> users = new ArrayList<>();
                        while (rs.next()) {
                            users.add(mapUser(rs));
                        }
                        return users;
                    }
                }

                private User mapUser(ResultSet rs) throws SQLException {
                    // 映射逻辑
                    return new User();
                }
            }

            // 使用示例
            @Controller("/api/users")
            public class UserController {
                private final TenantUserRepository userRepository;

                public UserController(TenantUserRepository userRepository) {
                    this.userRepository = userRepository;
                }

                @Get
                public List<User> getUsers(@Header("X-Tenant-Id") String tenantId) {
                    try {
                        // 设置当前租户
                        TenantContext.setCurrentTenantId(tenantId);

                        // 获取租户数据(使用租户级别的Repository)
                        return userRepository.findAll();

                    } finally {
                        // 清理租户上下文
                        TenantContext.clear();
                    }
                }
            }

            // 多租户请求示例
            // 请求1: GET /api/users  Header: X-Tenant-Id=tenant-001
            // 输出:
            // 创建租户数据源: tenant-001
            // 租户[tenant-001]数据库连接已建立
            // 创建租户Repository
            // 返回tenant-001的用户列表

            // 请求2: GET /api/users  Header: X-Tenant-Id=tenant-002
            // 输出:
            // 创建租户数据源: tenant-002
            // 租户[tenant-002]数据库连接已建立
            // 创建租户Repository
            // 返回tenant-002的用户列表

            // 请求3: GET /api/users  Header: X-Tenant-Id=tenant-001
            // 输出:
            // 返回tenant-001的用户列表(复用已创建的实例)
            ---

06.作用域选择指南
    a.选择决策
        a.作用域决策树
            根据Bean的特性选择合适的作用域,考虑线程安全性、状态管理、性能和资源占用。
        b.决策示例
            ---
            // 决策流程
            // 1. Bean是否有状态(包含可变字段)?
            //    ├─ 否(无状态)→ 使用@Singleton
            //    └─ 是(有状态)→ 继续判断

            // 2. 状态是否与HTTP请求相关?
            //    ├─ 是 → 使用@RequestScope
            //    └─ 否 → 继续判断

            // 3. 状态是否与线程相关?
            //    ├─ 是 → 使用@ThreadLocal
            //    └─ 否 → 继续判断

            // 4. 是否需要独立实例?
            //    ├─ 是 → 使用@Prototype
            //    └─ 否 → 继续判断

            // 5. 配置是否需要动态刷新?
            //    ├─ 是 → 使用@Refreshable
            //    └─ 否 → 使用@Singleton

            // 示例1:无状态服务 → Singleton
            @Singleton
            public class MathService {
                public int add(int a, int b) {
                    return a + b;
                }
                // 无状态,线程安全,使用单例
            }

            // 示例2:请求相关 → RequestScope
            @RequestScope
            public class UserSession {
                private User currentUser;
                private String sessionToken;
                // 每个请求独立实例
            }

            // 示例3:线程相关 → ThreadLocal
            @ThreadLocal
            public class TransactionContext {
                private String transactionId;
                private List<String> operations;
                // 每个线程独立实例
            }

            // 示例4:需要隔离 → Prototype
            @Prototype
            public class ReportGenerator {
                private List<ReportSection> sections = new ArrayList<>();

                public void addSection(ReportSection section) {
                    sections.add(section);
                }
                // 每次使用创建新实例,避免状态污染
            }

            // 示例5:动态配置 → Refreshable
            @Refreshable
            @ConfigurationProperties("feature-flags")
            public class FeatureFlags {
                private boolean newUIEnabled;
                private boolean betaFeaturesEnabled;
                // 配置变更时重新创建
            }

            // 示例6:有状态但需共享 → 需要重新设计
            // ❌ 错误示例
            @Singleton
            public class BadCounter {
                private int count = 0;  // 多线程不安全!

                public void increment() {
                    count++;  // 竞态条件
                }
            }

            // ✅ 正确方案1:使用原子类
            @Singleton
            public class SafeCounter {
                private final AtomicInteger count = new AtomicInteger(0);

                public void increment() {
                    count.incrementAndGet();
                }
            }

            // ✅ 正确方案2:无状态设计
            @Singleton
            public class StatelessCounter {
                public int increment(int current) {
                    return current + 1;
                }
            }
            ---
    b.性能与资源权衡
        a.性能对比
            Singleton性能最优,Prototype和RequestScope会频繁创建实例,需要权衡性能和资源占用。
        b.资源使用示例
            ---
            // 性能测试
            import io.micronaut.context.BeanContext;

            public class ScopePerformanceTest {
                public static void main(String[] args) {
                    BeanContext context = BeanContext.run();

                    // 测试1:Singleton
                    long start1 = System.nanoTime();
                    for (int i = 0; i < 100000; i++) {
                        SingletonBean bean = context.getBean(SingletonBean.class);
                    }
                    long duration1 = System.nanoTime() - start1;
                    System.out.println("Singleton获取10万次: " +
                                     duration1 / 1_000_000 + "ms");

                    // 测试2:Prototype
                    long start2 = System.nanoTime();
                    for (int i = 0; i < 100000; i++) {
                        PrototypeBean bean = context.getBean(PrototypeBean.class);
                    }
                    long duration2 = System.nanoTime() - start2;
                    System.out.println("Prototype创建10万次: " +
                                     duration2 / 1_000_000 + "ms");

                    context.close();
                }
            }

            // 测试结果
            // Singleton获取10万次: 12ms(缓存查找)
            // Prototype创建10万次: 850ms(每次创建新实例)

            // 内存占用对比
            @Singleton
            public class HeavyService {
                private final byte[] data = new byte[1024 * 1024];  // 1MB
                // 整个应用只占用1MB
            }

            @Prototype
            public class HeavyPrototype {
                private final byte[] data = new byte[1024 * 1024];  // 1MB
                // 每次创建占用1MB,需要注意内存泄漏
            }

            // 使用建议
            // ✅ 大对象、重量级资源 → 使用Singleton
            // ✅ 频繁创建的轻量对象 → 使用Prototype
            // ✅ 请求级别的小对象 → 使用RequestScope
            // ❌ 避免大对象使用Prototype(内存占用高)
            // ❌ 避免频繁创建重量级对象(性能问题)
            ---

07.作用域陷阱
    a.作用域不匹配
        a.依赖作用域问题
            Singleton Bean不应依赖Prototype或RequestScope Bean,否则会导致作用域泄漏,需要使用Provider延迟获取。
        b.作用域陷阱示例
            ---
            // ❌ 错误:Singleton依赖Prototype
            @Prototype
            public class TaskHandler {
                private String taskId = UUID.randomUUID().toString();

                public void handle() {
                    System.out.println("处理任务: " + taskId);
                }
            }

            @Singleton
            public class TaskManager {
                private final TaskHandler taskHandler;

                public TaskManager(TaskHandler taskHandler) {
                    // ⚠️ 问题:Singleton在创建时注入一个Prototype实例
                    // 之后TaskManager一直使用这个实例,Prototype失去意义
                    this.taskHandler = taskHandler;
                }

                public void executeTask() {
                    // 总是使用同一个TaskHandler实例
                    taskHandler.handle();  // taskId永远相同!
                }
            }

            // ✅ 正确:使用Provider
            import jakarta.inject.Provider;

            @Singleton
            public class CorrectTaskManager {
                private final Provider<TaskHandler> taskHandlerProvider;

                public CorrectTaskManager(Provider<TaskHandler> taskHandlerProvider) {
                    this.taskHandlerProvider = taskHandlerProvider;
                }

                public void executeTask() {
                    // 每次调用时获取新的Prototype实例
                    TaskHandler handler = taskHandlerProvider.get();
                    handler.handle();  // taskId每次不同
                }
            }

            // ❌ 错误:Singleton依赖RequestScope
            @RequestScope
            public class CurrentUser {
                private User user;
                // 每个请求独立实例
            }

            @Singleton
            public class UserAuditService {
                private final CurrentUser currentUser;

                public UserAuditService(CurrentUser currentUser) {
                    // ⚠️ 问题:Singleton创建时注入第一个请求的CurrentUser
                    // 后续所有请求都使用这个实例,导致错误
                    this.currentUser = currentUser;
                }
            }

            // ✅ 正确:使用Provider
            @Singleton
            public class CorrectUserAuditService {
                private final Provider<CurrentUser> currentUserProvider;

                public CorrectUserAuditService(Provider<CurrentUser> currentUserProvider) {
                    this.currentUserProvider = currentUserProvider;
                }

                public void audit(String action) {
                    // 每次调用时获取当前请求的CurrentUser
                    CurrentUser user = currentUserProvider.get();
                    log(user, action);
                }

                private void log(CurrentUser user, String action) {
                    // 记录审计日志
                }
            }
            ---
    b.作用域混合最佳实践
        a.依赖规则
            遵循作用域依赖规则,长生命周期Bean可以依赖短生命周期Bean,但需要通过Provider获取,确保每次获取最新实例。
        b.最佳实践示例
            ---
            // 作用域依赖规则
            // ✅ 允许:窄作用域 → 宽作用域
            @RequestScope
            public class RequestBean {
                private final SingletonBean singletonBean;  // OK
            }

            // ❌ 禁止:宽作用域 → 窄作用域(直接依赖)
            @Singleton
            public class SingletonBean {
                private final RequestBean requestBean;  // 错误!
            }

            // ✅ 允许:宽作用域 → 窄作用域(通过Provider)
            @Singleton
            public class CorrectSingletonBean {
                private final Provider<RequestBean> requestBeanProvider;  // OK
            }

            // 完整示例:电商系统
            // 1. Singleton:配置服务
            @Singleton
            public class AppConfig {
                public String getAppName() {
                    return "ECommerce";
                }
            }

            // 2. RequestScope:当前用户
            @RequestScope
            public class CurrentUserContext {
                private Long userId;
                private String username;

                public void setUser(Long userId, String username) {
                    this.userId = userId;
                    this.username = username;
                }

                public Long getUserId() { return userId; }
                public String getUsername() { return username; }
            }

            // 3. Prototype:订单处理器
            @Prototype
            public class OrderProcessor {
                private final String processorId = UUID.randomUUID().toString();

                public Order process(OrderRequest request) {
                    System.out.println("处理器[" + processorId + "]处理订单");
                    return new Order(request);
                }
            }

            // 4. Singleton服务混合使用
            @Singleton
            public class OrderService {
                private final AppConfig appConfig;                          // Singleton
                private final Provider<CurrentUserContext> userProvider;    // RequestScope
                private final Provider<OrderProcessor> processorProvider;   // Prototype

                public OrderService(
                    AppConfig appConfig,
                    Provider<CurrentUserContext> userProvider,
                    Provider<OrderProcessor> processorProvider) {

                    this.appConfig = appConfig;
                    this.userProvider = userProvider;
                    this.processorProvider = processorProvider;
                }

                public Order createOrder(OrderRequest request) {
                    // 访问Singleton(直接使用)
                    System.out.println("应用: " + appConfig.getAppName());

                    // 访问RequestScope(通过Provider)
                    CurrentUserContext user = userProvider.get();
                    System.out.println("当前用户: " + user.getUsername());

                    // 访问Prototype(通过Provider,每次获取新实例)
                    OrderProcessor processor = processorProvider.get();
                    return processor.process(request);
                }
            }

            // 作用域总结
            // @Singleton      → 无状态服务、配置、工具类
            // @Prototype      → 有状态对象、需要隔离的对象
            // @RequestScope   → 请求级上下文、用户会话
            // @ThreadLocal    → 线程级上下文、事务管理
            // @Refreshable    → 动态配置、特性开关
            // 自定义作用域    → 多租户、特殊生命周期需求
            ---

3.5 条件化Bean

01.@Requires注解
    a.条件创建Bean
        a.基本条件判断
            @Requires注解允许根据配置、环境、类存在等条件决定是否创建Bean,实现灵活的组件装配。
        b.基础条件示例
            ---
            import io.micronaut.context.annotation.Requires;
            import jakarta.inject.Singleton;

            // 示例1:根据配置属性决定是否创建
            @Singleton
            @Requires(property = "redis.enabled", value = "true")
            public class RedisCache implements CacheService {
                public RedisCache() {
                    System.out.println("Redis缓存已启用");
                }

                @Override
                public void put(String key, Object value) {
                    // Redis缓存实现
                }

                @Override
                public Object get(String key) {
                    return null;
                }
            }

            // 示例2:配置不存在时创建(默认实现)
            @Singleton
            @Requires(property = "redis.enabled", value = "false", defaultValue = "false")
            public class InMemoryCache implements CacheService {
                private final Map<String, Object> cache = new ConcurrentHashMap<>();

                public InMemoryCache() {
                    System.out.println("内存缓存已启用");
                }

                @Override
                public void put(String key, Object value) {
                    cache.put(key, value);
                }

                @Override
                public Object get(String key) {
                    return cache.get(key);
                }
            }

            // application.yml场景1
            // redis:
            //   enabled: true
            // 结果:创建RedisCache

            // application.yml场景2
            // redis:
            //   enabled: false
            // 结果:创建InMemoryCache

            // application.yml场景3(未配置redis.enabled)
            // 结果:创建InMemoryCache(defaultValue="false")
            ---
    b.配置条件
        a.属性匹配
            @Requires支持多种配置条件,包括属性存在、属性值匹配、属性不存在等。
        b.配置条件示例
            ---
            import io.micronaut.context.annotation.Requires;

            // 条件1:属性存在
            @Singleton
            @Requires(property = "database.url")
            public class DatabaseService {
                // 仅当database.url配置存在时创建
            }

            // 条件2:属性值匹配
            @Singleton
            @Requires(property = "app.mode", value = "production")
            public class ProductionMonitor {
                // 仅在生产环境创建
            }

            // 条件3:属性值不匹配
            @Singleton
            @Requires(property = "app.mode", notEquals = "production")
            public class DevelopmentDebugger {
                // 非生产环境创建
            }

            // 条件4:属性不存在
            @Singleton
            @Requires(missingProperty = "external.service.url")
            public class MockExternalService implements ExternalService {
                // 外部服务未配置时使用Mock
                @Override
                public String call() {
                    return "Mock Response";
                }
            }

            // 条件5:多个属性条件(AND关系)
            @Singleton
            @Requires(property = "oauth.enabled", value = "true")
            @Requires(property = "oauth.provider", value = "google")
            public class GoogleOAuthService {
                // 同时满足:oauth启用 且 provider为google
            }

            // 条件6:属性值模式匹配
            @Singleton
            @Requires(property = "storage.type", pattern = "s3|oss|obs")
            public class CloudStorageService {
                private final String storageType;

                public CloudStorageService(@Value("${storage.type}") String storageType) {
                    this.storageType = storageType;
                    System.out.println("云存储类型: " + storageType);
                }
            }

            // 配置示例
            // application-dev.yml
            // app:
            //   mode: development
            // 结果:创建DevelopmentDebugger

            // application-prod.yml
            // app:
            //   mode: production
            // oauth:
            //   enabled: true
            //   provider: google
            // storage:
            //   type: s3
            // 结果:创建ProductionMonitor, GoogleOAuthService, CloudStorageService
            ---

02.环境条件
    a.@Requires(env)
        a.环境判断
            根据当前激活的环境(dev、test、prod等)决定是否创建Bean,实现环境特定的组件配置。
        b.环境条件示例
            ---
            import io.micronaut.context.annotation.Requires;
            import io.micronaut.context.env.Environment;

            // 示例1:仅在开发环境创建
            @Singleton
            @Requires(env = Environment.DEVELOPMENT)
            public class H2DatabaseInitializer {
                @PostConstruct
                public void init() {
                    System.out.println("初始化H2内存数据库(开发环境)");
                    // 创建测试数据
                    createTestData();
                }

                private void createTestData() {
                    // 插入测试数据
                }
            }

            // 示例2:仅在生产环境创建
            @Singleton
            @Requires(env = Environment.PRODUCTION)
            public class ProductionDataSource implements DataSource {
                public ProductionDataSource() {
                    System.out.println("连接生产数据库");
                }

                @Override
                public Connection getConnection() throws SQLException {
                    return DriverManager.getConnection(
                        "jdbc:mysql://prod-db:3306/mydb");
                }
            }

            // 示例3:多环境条件
            @Singleton
            @Requires(env = {Environment.DEVELOPMENT, Environment.TEST})
            public class MockEmailService implements EmailService {
                @Override
                public void send(String to, String subject, String body) {
                    // 开发和测试环境不发送真实邮件
                    System.out.println("模拟发送邮件到: " + to);
                    System.out.println("主题: " + subject);
                }
            }

            // 示例4:排除特定环境
            @Singleton
            @Requires(notEnv = Environment.TEST)
            public class RealPaymentGateway implements PaymentGateway {
                // 非测试环境使用真实支付网关
                @Override
                public PaymentResult charge(BigDecimal amount) {
                    System.out.println("调用真实支付接口");
                    return new PaymentResult(true);
                }
            }

            @Singleton
            @Requires(env = Environment.TEST)
            public class MockPaymentGateway implements PaymentGateway {
                // 测试环境使用Mock支付
                @Override
                public PaymentResult charge(BigDecimal amount) {
                    System.out.println("Mock支付: " + amount);
                    return new PaymentResult(true);
                }
            }

            // 启动命令与环境
            // java -jar app.jar                        → 默认环境
            // java -jar app.jar -Dmicronaut.environments=dev  → 开发环境
            // java -jar app.jar -Dmicronaut.environments=prod → 生产环境
            // java -jar app.jar -Dmicronaut.environments=test → 测试环境
            ---
    b.自定义环境
        a.环境定义
            可以定义自定义环境名称,根据部署场景创建不同的Bean配置。
        b.自定义环境示例
            ---
            // 定义自定义环境
            // application.yml
            // micronaut:
            //   environments:
            //     - staging
            //     - aws-cn

            // 使用自定义环境
            @Singleton
            @Requires(env = "staging")
            public class StagingMonitor {
                public StagingMonitor() {
                    System.out.println("预发布环境监控已启用");
                }
            }

            @Singleton
            @Requires(env = "aws-cn")
            public class ChinaRegionService {
                public ChinaRegionService() {
                    System.out.println("中国区服务已启用");
                }
            }

            // 多环境组合
            @Singleton
            @Requires(env = {"staging", "production"})
            public class PerformanceMonitor {
                // 在预发布和生产环境启用性能监控
            }

            // 启动应用
            // java -jar app.jar -Dmicronaut.environments=staging
            // 结果:创建StagingMonitor和PerformanceMonitor

            // java -jar app.jar -Dmicronaut.environments=staging,aws-cn
            // 结果:创建StagingMonitor、ChinaRegionService、PerformanceMonitor
            ---

03.类存在条件
    a.@Requires(classes)
        a.依赖类检测
            根据classpath中是否存在特定类来决定是否创建Bean,实现可选依赖的自动配置。
        b.类存在示例
            ---
            import io.micronaut.context.annotation.Requires;

            // 示例1:Redis客户端存在时启用Redis缓存
            @Singleton
            @Requires(classes = {
                io.lettuce.core.RedisClient.class,
                io.micronaut.redis.RedisConfiguration.class
            })
            public class RedisConfiguration {
                public RedisConfiguration() {
                    System.out.println("检测到Redis依赖,启用Redis配置");
                }

                @Bean
                public RedisClient redisClient() {
                    return RedisClient.create("redis://localhost:6379");
                }
            }

            // 示例2:Kafka客户端存在时启用消息队列
            @Singleton
            @Requires(classes = org.apache.kafka.clients.producer.KafkaProducer.class)
            public class KafkaMessagePublisher implements MessagePublisher {
                private final KafkaProducer<String, String> producer;

                public KafkaMessagePublisher() {
                    System.out.println("Kafka客户端可用,启用Kafka发布器");
                    Properties props = new Properties();
                    props.put("bootstrap.servers", "localhost:9092");
                    this.producer = new KafkaProducer<>(props);
                }

                @Override
                public void publish(String topic, String message) {
                    producer.send(new ProducerRecord<>(topic, message));
                }
            }

            // 示例3:类不存在时使用备用方案
            @Singleton
            @Requires(missingClasses = "org.apache.kafka.clients.producer.KafkaProducer")
            public class InMemoryMessagePublisher implements MessagePublisher {
                public InMemoryMessagePublisher() {
                    System.out.println("Kafka不可用,使用内存队列");
                }

                @Override
                public void publish(String topic, String message) {
                    System.out.println("发布消息到内存队列[" + topic + "]: " + message);
                }
            }

            // pom.xml包含Redis依赖时
            // <dependency>
            //     <groupId>io.micronaut.redis</groupId>
            //     <artifactId>micronaut-redis-lettuce</artifactId>
            // </dependency>
            // 结果:创建RedisConfiguration

            // pom.xml包含Kafka依赖时
            // <dependency>
            //     <groupId>org.apache.kafka</groupId>
            //     <artifactId>kafka-clients</artifactId>
            // </dependency>
            // 结果:创建KafkaMessagePublisher

            // pom.xml不包含Kafka依赖时
            // 结果:创建InMemoryMessagePublisher
            ---
    b.Bean存在条件
        a.@Requires(beans)
            根据容器中是否存在特定Bean来决定是否创建当前Bean,实现Bean间的条件依赖。
        b.Bean条件示例
            ---
            // 示例1:依赖DataSource存在
            @Singleton
            @Requires(beans = DataSource.class)
            public class DatabaseHealthIndicator implements HealthIndicator {
                private final DataSource dataSource;

                public DatabaseHealthIndicator(DataSource dataSource) {
                    this.dataSource = dataSource;
                }

                @Override
                public HealthStatus check() {
                    try (Connection conn = dataSource.getConnection()) {
                        return HealthStatus.UP;
                    } catch (SQLException e) {
                        return HealthStatus.DOWN;
                    }
                }
            }

            // 示例2:某Bean不存在时创建备用Bean
            @Singleton
            @Requires(missingBeans = RedisClient.class)
            public class LocalCacheManager implements CacheManager {
                public LocalCacheManager() {
                    System.out.println("Redis客户端不存在,使用本地缓存");
                }
            }

            // 示例3:组合条件
            @Singleton
            @Requires(beans = {DataSource.class, TransactionManager.class})
            @Requires(property = "jpa.enabled", value = "true")
            public class JpaConfiguration {
                // 同时满足:
                // 1. DataSource Bean存在
                // 2. TransactionManager Bean存在
                // 3. jpa.enabled=true
                public JpaConfiguration() {
                    System.out.println("JPA配置已启用");
                }
            }

            // 示例4:条件化@Primary
            @Primary
            @Singleton
            @Requires(beans = RedisClient.class)
            public class RedisCacheManager implements CacheManager {
                // 如果Redis可用,优先使用Redis缓存
            }

            @Singleton
            @Requires(missingBeans = RedisClient.class)
            public class SimpleCacheManager implements CacheManager {
                // Redis不可用时使用简单缓存
            }
            ---

04.SDK版本条件
    a.@Requires(sdk)
        a.JDK版本判断
            根据当前运行的JDK版本决定是否创建Bean,适配不同Java版本的API。
        b.SDK版本示例
            ---
            import io.micronaut.context.annotation.Requires;
            import io.micronaut.core.version.SemanticVersion;

            // 示例1:要求最低JDK版本
            @Singleton
            @Requires(sdk = Requires.Sdk.JAVA, value = "17")
            public class ModernJavaService {
                public ModernJavaService() {
                    System.out.println("使用Java 17+特性");
                }

                public String processWithRecords(String input) {
                    // 使用Java 17 Records
                    record Result(String value, long timestamp) {}

                    Result result = new Result(input, System.currentTimeMillis());
                    return result.value();
                }

                public String usePatternMatching(Object obj) {
                    // 使用Java 17 Pattern Matching
                    if (obj instanceof String s && s.length() > 0) {
                        return s.toUpperCase();
                    }
                    return "";
                }
            }

            // 示例2:特定版本范围
            @Singleton
            @Requires(sdk = Requires.Sdk.JAVA, value = "11", configuration = "11-16")
            public class Java11To16Service {
                // 仅在JDK 11-16版本创建
            }

            // 示例3:JDK 8兼容实现
            @Singleton
            @Requires(sdk = Requires.Sdk.JAVA, value = "1.8")
            public class LegacyJavaService {
                public LegacyJavaService() {
                    System.out.println("使用Java 8兼容实现");
                }

                public String process(String input) {
                    // 避免使用新版本特性
                    return input.toUpperCase();
                }
            }

            // 示例4:GraalVM条件
            @Singleton
            @Requires(condition = GraalVMCondition.class)
            public class NativeImageOptimizedService {
                // 仅在GraalVM Native Image中创建
            }

            import io.micronaut.context.condition.Condition;
            import io.micronaut.context.condition.ConditionContext;

            public class GraalVMCondition implements Condition {
                @Override
                public boolean matches(ConditionContext context) {
                    // 检测是否运行在GraalVM Native Image
                    String vmName = System.getProperty("java.vm.name");
                    return vmName != null && vmName.contains("Substrate VM");
                }
            }
            ---
    b.运行时条件
        a.@Requires(condition)
            通过自定义Condition实现复杂的运行时判断逻辑。
        b.自定义条件示例
            ---
            import io.micronaut.context.condition.Condition;
            import io.micronaut.context.condition.ConditionContext;

            // 条件1:工作日条件
            public class WorkdayCondition implements Condition {
                @Override
                public boolean matches(ConditionContext context) {
                    LocalDate today = LocalDate.now();
                    DayOfWeek day = today.getDayOfWeek();
                    boolean isWorkday = day != DayOfWeek.SATURDAY &&
                                       day != DayOfWeek.SUNDAY;
                    System.out.println("今天是" + (isWorkday ? "工作日" : "周末"));
                    return isWorkday;
                }
            }

            @Singleton
            @Requires(condition = WorkdayCondition.class)
            public class BusinessHoursService {
                // 仅在工作日创建
                public BusinessHoursService() {
                    System.out.println("工作日服务已启动");
                }
            }

            // 条件2:文件存在条件
            public class LicenseFileCondition implements Condition {
                @Override
                public boolean matches(ConditionContext context) {
                    Path licensePath = Paths.get("/etc/app/license.key");
                    boolean exists = Files.exists(licensePath);
                    System.out.println("许可证文件" +
                                     (exists ? "存在" : "不存在"));
                    return exists;
                }
            }

            @Singleton
            @Requires(condition = LicenseFileCondition.class)
            public class EnterpriseFeatures {
                // 仅当许可证文件存在时启用企业功能
                public EnterpriseFeatures() {
                    System.out.println("企业版功能已启用");
                }

                public void advancedAnalytics() {
                    // 高级分析功能
                }
            }

            // 条件3:网络连接条件
            public class InternetConnectivityCondition implements Condition {
                @Override
                public boolean matches(ConditionContext context) {
                    try {
                        URL url = new URL("https://www.google.com");
                        HttpURLConnection conn =
                            (HttpURLConnection) url.openConnection();
                        conn.setRequestMethod("HEAD");
                        conn.setConnectTimeout(2000);
                        int responseCode = conn.getResponseCode();
                        return responseCode == 200;
                    } catch (IOException e) {
                        return false;
                    }
                }
            }

            @Singleton
            @Requires(condition = InternetConnectivityCondition.class)
            public class OnlineUpdateService {
                // 有网络连接时启用在线更新
            }

            @Singleton
            @Requires(condition = OfflineCondition.class)
            public class OfflineFallbackService {
                // 无网络连接时使用离线模式
            }
            ---

05.操作系统条件
    a.@Requires(os)
        a.平台特定Bean
            根据运行的操作系统决定是否创建Bean,实现跨平台适配。
        b.OS条件示例
            ---
            import io.micronaut.context.annotation.Requires;
            import io.micronaut.core.util.OperatingSystem;

            // 示例1:Linux特定实现
            @Singleton
            @Requires(os = Requires.Family.LINUX)
            public class LinuxSystemService implements SystemService {
                public LinuxSystemService() {
                    System.out.println("Linux系统服务已启动");
                }

                @Override
                public String getSystemInfo() {
                    // 使用Linux特定命令
                    return executeCommand("uname -a");
                }

                @Override
                public void optimizePerformance() {
                    // Linux性能优化
                    executeCommand("sysctl -w net.core.somaxconn=1024");
                }

                private String executeCommand(String command) {
                    // 执行shell命令
                    return "";
                }
            }

            // 示例2:Windows特定实现
            @Singleton
            @Requires(os = Requires.Family.WINDOWS)
            public class WindowsSystemService implements SystemService {
                public WindowsSystemService() {
                    System.out.println("Windows系统服务已启动");
                }

                @Override
                public String getSystemInfo() {
                    // 使用Windows特定命令
                    return executeCommand("systeminfo");
                }

                @Override
                public void optimizePerformance() {
                    // Windows性能优化
                    executeCommand("netsh int tcp set global autotuninglevel=normal");
                }

                private String executeCommand(String command) {
                    // 执行cmd命令
                    return "";
                }
            }

            // 示例3:macOS特定实现
            @Singleton
            @Requires(os = Requires.Family.MAC_OS)
            public class MacSystemService implements SystemService {
                public MacSystemService() {
                    System.out.println("macOS系统服务已启动");
                }

                @Override
                public String getSystemInfo() {
                    return executeCommand("sw_vers");
                }

                @Override
                public void optimizePerformance() {
                    // macOS性能优化
                }

                private String executeCommand(String command) {
                    return "";
                }
            }

            // 示例4:多平台支持
            @Singleton
            @Requires(os = {Requires.Family.LINUX, Requires.Family.MAC_OS})
            public class UnixFileWatcher {
                // Linux和macOS都支持inotify/fsevents
                public UnixFileWatcher() {
                    System.out.println("Unix文件监控已启用");
                }
            }

            // 跨平台最佳实践
            // 1. 定义统一接口
            public interface SystemService {
                String getSystemInfo();
                void optimizePerformance();
            }

            // 2. 为每个平台提供实现,使用@Requires(os)
            // 3. 业务代码依赖接口,运行时自动注入对应平台实现
            @Controller("/system")
            public class SystemController {
                private final SystemService systemService;

                public SystemController(SystemService systemService) {
                    // 根据运行平台自动注入对应实现
                    this.systemService = systemService;
                }

                @Get("/info")
                public String getInfo() {
                    return systemService.getSystemInfo();
                }
            }
            ---
    b.云平台条件
        a.@Requires(cloudPlatform)
            根据云平台环境(AWS、GCP、Azure等)决定是否创建Bean。
        b.云平台示例
            ---
            import io.micronaut.context.annotation.Requires;
            import io.micronaut.core.util.CloudPlatform;

            // AWS特定服务
            @Singleton
            @Requires(cloudPlatform = CloudPlatform.AMAZON_EC2)
            public class AwsS3StorageService implements StorageService {
                public AwsS3StorageService() {
                    System.out.println("AWS S3存储服务已启用");
                }

                @Override
                public void upload(String key, byte[] data) {
                    // 使用AWS SDK上传到S3
                    AmazonS3 s3Client = AmazonS3ClientBuilder.defaultClient();
                    s3Client.putObject("my-bucket", key, new ByteArrayInputStream(data));
                }
            }

            // GCP特定服务
            @Singleton
            @Requires(cloudPlatform = CloudPlatform.GOOGLE_COMPUTE)
            public class GcsStorageService implements StorageService {
                public GcsStorageService() {
                    System.out.println("Google Cloud Storage服务已启用");
                }

                @Override
                public void upload(String key, byte[] data) {
                    // 使用GCP SDK上传到GCS
                    Storage storage = StorageOptions.getDefaultInstance().getService();
                    storage.create(BlobInfo.newBuilder("my-bucket", key).build(), data);
                }
            }

            // Azure特定服务
            @Singleton
            @Requires(cloudPlatform = CloudPlatform.AZURE)
            public class AzureBlobStorageService implements StorageService {
                public AzureBlobStorageService() {
                    System.out.println("Azure Blob Storage服务已启用");
                }

                @Override
                public void upload(String key, byte[] data) {
                    // 使用Azure SDK上传到Blob Storage
                }
            }

            // 本地开发环境(无云平台)
            @Singleton
            @Requires(missingProperty = "KUBERNETES_SERVICE_HOST")
            @Requires(notEnv = Environment.CLOUD)
            public class LocalFileStorageService implements StorageService {
                public LocalFileStorageService() {
                    System.out.println("本地文件存储服务已启用");
                }

                @Override
                public void upload(String key, byte[] data) throws IOException {
                    Path path = Paths.get("/tmp/storage", key);
                    Files.createDirectories(path.getParent());
                    Files.write(path, data);
                }
            }

            // 云平台检测原理
            // AWS: 检测EC2元数据服务 http://169.254.169.254
            // GCP: 检测元数据服务器 metadata.google.internal
            // Azure: 检测环境变量 WEBSITE_INSTANCE_ID
            // Kubernetes: 检测环境变量 KUBERNETES_SERVICE_HOST
            ---

06.组合条件
    a.复杂条件组合
        a.AND条件
            多个@Requires注解默认是AND关系,所有条件都满足才创建Bean。
        b.AND条件示例
            ---
            // 示例:企业版功能
            @Singleton
            @Requires(property = "app.edition", value = "enterprise")
            @Requires(property = "license.valid", value = "true")
            @Requires(beans = DatabaseConnectionPool.class)
            @Requires(env = Environment.PRODUCTION)
            public class EnterpriseAnalytics {
                // 必须同时满足:
                // 1. 版本为企业版
                // 2. 许可证有效
                // 3. 数据库连接池存在
                // 4. 生产环境
                public EnterpriseAnalytics() {
                    System.out.println("企业分析功能已启用");
                }

                public Report generateAdvancedReport() {
                    // 高级报表功能
                    return new Report();
                }
            }

            // 示例:安全审计
            @Singleton
            @Requires(property = "security.audit.enabled", value = "true")
            @Requires(beans = {AuditLogger.class, SecurityEventPublisher.class})
            @Requires(classes = "org.springframework.security.core.Authentication")
            public class SecurityAuditService {
                private final AuditLogger auditLogger;
                private final SecurityEventPublisher eventPublisher;

                public SecurityAuditService(AuditLogger auditLogger,
                                          SecurityEventPublisher eventPublisher) {
                    this.auditLogger = auditLogger;
                    this.eventPublisher = eventPublisher;
                    System.out.println("安全审计服务已启用");
                }

                public void auditLogin(String username) {
                    auditLogger.log("用户登录: " + username);
                    eventPublisher.publishLoginEvent(username);
                }
            }
            ---
    b.条件优先级
        a.条件求值顺序
            Micronaut按照特定顺序求值条件,优先检查快速失败的条件以提高性能。
        b.优先级示例
            ---
            // 条件求值顺序
            // 1. 环境条件(env, notEnv)
            // 2. 配置属性条件(property, missingProperty)
            // 3. Bean条件(beans, missingBeans)
            // 4. 类条件(classes, missingClasses)
            // 5. SDK条件(sdk)
            // 6. 自定义条件(condition)

            @Singleton
            @Requires(env = Environment.PRODUCTION)          // 1. 首先检查环境
            @Requires(property = "feature.enabled")          // 2. 然后检查配置
            @Requires(beans = DataSource.class)              // 3. 检查Bean存在
            @Requires(classes = "com.example.AdvancedLib")   // 4. 检查类存在
            @Requires(sdk = Requires.Sdk.JAVA, value = "17") // 5. 检查JDK版本
            @Requires(condition = CustomCondition.class)     // 6. 最后执行自定义条件
            public class ComplexFeature {
                // 按顺序求值,任一条件不满足即停止检查
            }

            // 性能优化建议
            @Singleton
            @Requires(property = "expensive.feature.enabled", value = "true")  // 快速检查
            @Requires(condition = ExpensiveCondition.class)  // 耗时检查放后面
            public class ExpensiveFeature {
                // 如果配置未启用,不会执行ExpensiveCondition
            }

            public class ExpensiveCondition implements Condition {
                @Override
                public boolean matches(ConditionContext context) {
                    // 耗时的条件检查(网络请求、文件扫描等)
                    return checkLicenseServer();
                }

                private boolean checkLicenseServer() {
                    // 网络请求验证许可证
                    return true;
                }
            }
            ---

07.条件化配置
    a.@RequiresConfiguration
        a.配置类条件
            为整个@ConfigurationProperties类添加条件,仅在满足条件时加载配置。
        b.配置条件示例
            ---
            import io.micronaut.context.annotation.ConfigurationProperties;
            import io.micronaut.context.annotation.Requires;

            // 示例1:Redis配置(仅在启用时加载)
            @ConfigurationProperties("redis")
            @Requires(property = "redis.enabled", value = "true")
            public class RedisConfiguration {
                private String host;
                private int port;
                private String password;
                private int database;

                public RedisConfiguration() {
                    System.out.println("加载Redis配置");
                }

                // Getter和Setter
                public String getHost() { return host; }
                public void setHost(String host) { this.host = host; }
                public int getPort() { return port; }
                public void setPort(int port) { this.port = port; }
                public String getPassword() { return password; }
                public void setPassword(String password) { this.password = password; }
                public int getDatabase() { return database; }
                public void setDatabase(int database) { this.database = database; }
            }

            // 示例2:Kafka配置(仅在类存在时加载)
            @ConfigurationProperties("kafka")
            @Requires(classes = "org.apache.kafka.clients.producer.KafkaProducer")
            public class KafkaConfiguration {
                private String bootstrapServers;
                private String groupId;
                private Map<String, Object> producerConfig;
                private Map<String, Object> consumerConfig;

                public KafkaConfiguration() {
                    System.out.println("加载Kafka配置");
                }

                // Getter和Setter省略
            }

            // 示例3:多条件配置
            @ConfigurationProperties("monitoring.prometheus")
            @Requires(property = "monitoring.enabled", value = "true")
            @Requires(property = "monitoring.type", value = "prometheus")
            @Requires(classes = "io.micrometer.prometheus.PrometheusMeterRegistry")
            public class PrometheusConfiguration {
                private int port;
                private String path;
                private boolean enabled;

                public PrometheusConfiguration() {
                    System.out.println("加载Prometheus监控配置");
                }

                // Getter和Setter省略
            }

            // application.yml
            // redis:
            //   enabled: true
            //   host: localhost
            //   port: 6379
            //
            // monitoring:
            //   enabled: true
            //   type: prometheus
            //   prometheus:
            //     port: 9090
            //     path: /metrics

            // 结果:
            // - RedisConfiguration加载(redis.enabled=true)
            // - KafkaConfiguration不加载(类不存在)
            // - PrometheusConfiguration加载(所有条件满足)
            ---
    b.条件化Bean工厂
        a.@Factory方法条件
            @Factory中的@Bean方法也可以使用@Requires,实现条件化Bean创建。
        b.工厂条件示例
            ---
            import io.micronaut.context.annotation.Factory;
            import io.micronaut.context.annotation.Bean;
            import io.micronaut.context.annotation.Requires;

            @Factory
            public class DataSourceFactory {
                // 开发环境:H2内存数据库
                @Bean
                @Singleton
                @Requires(env = Environment.DEVELOPMENT)
                public DataSource h2DataSource() {
                    System.out.println("创建H2内存数据库");
                    return new EmbeddedDatabaseBuilder()
                        .setType(EmbeddedDatabaseType.H2)
                        .build();
                }

                // 测试环境:PostgreSQL测试库
                @Bean
                @Singleton
                @Requires(env = Environment.TEST)
                @Requires(property = "test.db.url")
                public DataSource testDataSource(@Value("${test.db.url}") String url) {
                    System.out.println("连接测试数据库: " + url);
                    HikariConfig config = new HikariConfig();
                    config.setJdbcUrl(url);
                    return new HikariDataSource(config);
                }

                // 生产环境:MySQL主从集群
                @Bean
                @Singleton
                @Requires(env = Environment.PRODUCTION)
                @Requires(property = "datasource.master.url")
                @Requires(property = "datasource.slave.url")
                public DataSource productionDataSource(
                    @Value("${datasource.master.url}") String masterUrl,
                    @Value("${datasource.slave.url}") String slaveUrl) {

                    System.out.println("创建主从数据源");
                    return createMasterSlaveDataSource(masterUrl, slaveUrl);
                }

                private DataSource createMasterSlaveDataSource(
                    String masterUrl, String slaveUrl) {
                    // 创建读写分离数据源
                    return null;
                }
            }

            // 不同环境启动结果
            // 开发环境: 创建H2内存数据库
            // 测试环境: 连接测试数据库: jdbc:postgresql://test-db:5432/testdb
            // 生产环境: 创建主从数据源
            ---

3.6 Bean工厂与Provider

01.@Factory工厂类
    a.工厂模式
        a.Bean工厂定义
            @Factory类用于创建和配置Bean,通过@Bean方法返回Bean实例,适合需要复杂初始化逻辑或第三方类的Bean创建。
        b.基础工厂示例
            ---
            import io.micronaut.context.annotation.Factory;
            import io.micronaut.context.annotation.Bean;
            import jakarta.inject.Singleton;
            import com.zaxxer.hikari.HikariConfig;
            import com.zaxxer.hikari.HikariDataSource;

            @Factory
            public class DataSourceFactory {
                // 创建数据源Bean
                @Bean
                @Singleton
                public DataSource dataSource(
                    @Value("${datasource.url}") String url,
                    @Value("${datasource.username}") String username,
                    @Value("${datasource.password}") String password) {

                    System.out.println("创建数据源: " + url);

                    HikariConfig config = new HikariConfig();
                    config.setJdbcUrl(url);
                    config.setUsername(username);
                    config.setPassword(password);
                    config.setMaximumPoolSize(10);
                    config.setMinimumIdle(2);
                    config.setConnectionTimeout(30000);

                    return new HikariDataSource(config);
                }

                // 创建多个相关Bean
                @Bean
                @Singleton
                public JdbcTemplate jdbcTemplate(DataSource dataSource) {
                    System.out.println("创建JdbcTemplate");
                    return new JdbcTemplate(dataSource);
                }

                @Bean
                @Singleton
                public TransactionManager transactionManager(DataSource dataSource) {
                    System.out.println("创建事务管理器");
                    return new DataSourceTransactionManager(dataSource);
                }
            }

            // 使用工厂创建的Bean
            @Singleton
            public class UserRepository {
                private final JdbcTemplate jdbcTemplate;

                public UserRepository(JdbcTemplate jdbcTemplate) {
                    this.jdbcTemplate = jdbcTemplate;
                }

                public User findById(Long id) {
                    return jdbcTemplate.queryForObject(
                        "SELECT * FROM users WHERE id = ?",
                        new Object[]{id},
                        new UserRowMapper()
                    );
                }
            }

            // Bean创建流程
            // 1. BeanContext扫描到DataSourceFactory
            // 2. 调用dataSource()方法创建DataSource
            // 3. 调用jdbcTemplate()方法,注入DataSource
            // 4. 调用transactionManager()方法,注入DataSource
            // 5. UserRepository注入JdbcTemplate
            ---
    b.工厂方法依赖注入
        a.方法参数注入
            @Factory中的@Bean方法可以声明参数,Micronaut会自动注入所需依赖。
        b.依赖注入示例
            ---
            import io.micronaut.context.annotation.Factory;
            import io.micronaut.context.annotation.Bean;

            @Factory
            public class MessagingFactory {
                // 无参数工厂方法
                @Bean
                @Singleton
                public MessageQueue messageQueue() {
                    System.out.println("创建消息队列");
                    return new InMemoryMessageQueue();
                }

                // 单个依赖
                @Bean
                @Singleton
                public MessageProducer messageProducer(MessageQueue queue) {
                    System.out.println("创建消息生产者");
                    return new DefaultMessageProducer(queue);
                }

                // 多个依赖
                @Bean
                @Singleton
                public MessageConsumer messageConsumer(
                    MessageQueue queue,
                    MessageHandler handler,
                    @Value("${consumer.threads:4}") int threads) {

                    System.out.println("创建消息消费者,线程数: " + threads);
                    return new DefaultMessageConsumer(queue, handler, threads);
                }

                // 可选依赖
                @Bean
                @Singleton
                public MessageRouter messageRouter(
                    MessageQueue queue,
                    @Nullable RetryPolicy retryPolicy,
                    @Nullable DeadLetterQueue deadLetterQueue) {

                    System.out.println("创建消息路由");

                    MessageRouter router = new MessageRouter(queue);

                    if (retryPolicy != null) {
                        router.setRetryPolicy(retryPolicy);
                        System.out.println("  - 重试策略已配置");
                    }

                    if (deadLetterQueue != null) {
                        router.setDeadLetterQueue(deadLetterQueue);
                        System.out.println("  - 死信队列已配置");
                    }

                    return router;
                }
            }

            // Bean创建顺序
            // 1. messageQueue()           → MessageQueue
            // 2. messageProducer(queue)   → MessageProducer(依赖MessageQueue)
            // 3. messageConsumer(...)     → MessageConsumer(依赖多个Bean)
            // 4. messageRouter(...)       → MessageRouter(包含可选依赖)
            ---

02.@Bean方法特性
    a.返回类型与泛型
        a.泛型Bean创建
            @Bean方法可以返回泛型类型,Micronaut会保留完整的泛型信息用于依赖注入。
        b.泛型Bean示例
            ---
            import io.micronaut.context.annotation.Factory;
            import io.micronaut.context.annotation.Bean;

            @Factory
            public class ConverterFactory {
                // 创建String到Integer的转换器
                @Bean
                @Singleton
                @Named("stringToInteger")
                public Converter<String, Integer> stringToIntegerConverter() {
                    return new Converter<String, Integer>() {
                        @Override
                        public Integer convert(String source) {
                            return Integer.parseInt(source);
                        }
                    };
                }

                // 创建String到Date的转换器
                @Bean
                @Singleton
                @Named("stringToDate")
                public Converter<String, Date> stringToDateConverter() {
                    return new Converter<String, Date>() {
                        @Override
                        public Date convert(String source) {
                            return new SimpleDateFormat("yyyy-MM-dd").parse(source);
                        }
                    };
                }

                // 创建泛型集合Bean
                @Bean
                @Singleton
                @Named("userValidators")
                public List<Validator<User>> userValidators() {
                    return Arrays.asList(
                        new EmailValidator(),
                        new PasswordValidator(),
                        new AgeValidator()
                    );
                }

                // 创建泛型Map Bean
                @Bean
                @Singleton
                public Map<String, CommandHandler> commandHandlers(
                    List<CommandHandler> handlers) {

                    Map<String, CommandHandler> map = new HashMap<>();
                    for (CommandHandler handler : handlers) {
                        map.put(handler.getCommandName(), handler);
                    }
                    return map;
                }
            }

            // 注入泛型Bean
            @Singleton
            public class DataProcessor {
                private final Converter<String, Integer> intConverter;
                private final Converter<String, Date> dateConverter;
                private final List<Validator<User>> validators;

                public DataProcessor(
                    @Named("stringToInteger") Converter<String, Integer> intConverter,
                    @Named("stringToDate") Converter<String, Date> dateConverter,
                    @Named("userValidators") List<Validator<User>> validators) {

                    this.intConverter = intConverter;
                    this.dateConverter = dateConverter;
                    this.validators = validators;
                }

                public void process(String input) {
                    Integer number = intConverter.convert(input);
                    System.out.println("转换的数字: " + number);
                }

                public void validateUser(User user) {
                    for (Validator<User> validator : validators) {
                        validator.validate(user);
                    }
                }
            }
            ---
    b.Bean方法作用域
        a.方法级作用域
            @Bean方法可以指定不同的作用域,独立于工厂类的作用域。
        b.作用域组合示例
            ---
            @Factory
            public class MixedScopeFactory {
                // Singleton Bean
                @Bean
                @Singleton
                public CacheService cacheService() {
                    System.out.println("创建单例缓存服务");
                    return new RedisCacheService();
                }

                // Prototype Bean
                @Bean
                @Prototype
                public TaskExecutor taskExecutor() {
                    System.out.println("创建任务执行器实例");
                    return new TaskExecutor(UUID.randomUUID().toString());
                }

                // RequestScope Bean
                @Bean
                @RequestScope
                public RequestLogger requestLogger() {
                    System.out.println("创建请求日志记录器");
                    return new RequestLogger();
                }

                // Refreshable Bean
                @Bean
                @Refreshable
                public FeatureToggle featureToggle(
                    @Value("${features.new-ui:false}") boolean newUI,
                    @Value("${features.beta:false}") boolean beta) {

                    System.out.println("创建特性开关");
                    return new FeatureToggle(newUI, beta);
                }
            }

            // 使用不同作用域的Bean
            @Singleton
            public class ApplicationService {
                private final CacheService cacheService;              // Singleton
                private final Provider<TaskExecutor> executorProvider; // Prototype
                private final Provider<RequestLogger> loggerProvider;  // RequestScope

                public ApplicationService(
                    CacheService cacheService,
                    Provider<TaskExecutor> executorProvider,
                    Provider<RequestLogger> loggerProvider) {

                    this.cacheService = cacheService;
                    this.executorProvider = executorProvider;
                    this.loggerProvider = loggerProvider;
                }

                public void executeTask(String taskData) {
                    // 获取新的Prototype实例
                    TaskExecutor executor = executorProvider.get();
                    executor.execute(taskData);

                    // 获取当前请求的Logger
                    RequestLogger logger = loggerProvider.get();
                    logger.log("Task executed");
                }
            }
            ---

03.Provider模式
    a.jakarta.inject.Provider
        a.延迟获取Bean
            Provider<T>接口提供延迟获取Bean的能力,调用get()方法时才实例化Bean,适合循环依赖和作用域不匹配场景。
        b.Provider基础示例
            ---
            import jakarta.inject.Provider;
            import jakarta.inject.Singleton;

            @Singleton
            public class ReportService {
                private final Provider<ReportGenerator> generatorProvider;

                public ReportService(Provider<ReportGenerator> generatorProvider) {
                    // 构造器执行时不创建ReportGenerator
                    this.generatorProvider = generatorProvider;
                    System.out.println("ReportService创建(ReportGenerator未创建)");
                }

                public Report generateReport(ReportRequest request) {
                    // 调用时才获取ReportGenerator实例
                    ReportGenerator generator = generatorProvider.get();
                    System.out.println("获取ReportGenerator: " +
                                     System.identityHashCode(generator));

                    return generator.generate(request);
                }
            }

            @Prototype
            public class ReportGenerator {
                private final String generatorId = UUID.randomUUID().toString();

                public ReportGenerator() {
                    System.out.println("创建ReportGenerator: " + generatorId);
                }

                public Report generate(ReportRequest request) {
                    System.out.println("生成报告: " + generatorId);
                    return new Report();
                }
            }

            // 使用流程
            // 1. 应用启动:创建ReportService(ReportGenerator未创建)
            // 2. 调用generateReport()
            //    → 调用generatorProvider.get()
            //    → 创建新的ReportGenerator实例
            //    → 生成报告
            // 3. 再次调用generateReport()
            //    → 再次调用generatorProvider.get()
            //    → 创建新的ReportGenerator实例(Prototype作用域)
            ---
    b.Provider解决循环依赖
        a.循环依赖问题
            当两个Bean相互依赖时会形成循环,使用Provider可以打破循环,延迟一方的依赖获取。
        b.循环依赖解决示例
            ---
            // ❌ 错误:循环依赖
            @Singleton
            public class ServiceA {
                private final ServiceB serviceB;

                public ServiceA(ServiceB serviceB) {
                    this.serviceB = serviceB;
                }
            }

            @Singleton
            public class ServiceB {
                private final ServiceA serviceA;

                public ServiceB(ServiceA serviceA) {
                    this.serviceA = serviceA;
                }
            }
            // 错误:BeanInstantiationException: Circular dependency

            // ✅ 解决方案1:使用Provider
            @Singleton
            public class FixedServiceA {
                private final Provider<ServiceB> serviceBProvider;

                public FixedServiceA(Provider<ServiceB> serviceBProvider) {
                    this.serviceBProvider = serviceBProvider;
                    System.out.println("ServiceA创建");
                }

                public void doSomething() {
                    // 使用时才获取ServiceB
                    ServiceB serviceB = serviceBProvider.get();
                    serviceB.process();
                }
            }

            @Singleton
            public class FixedServiceB {
                private final FixedServiceA serviceA;

                public FixedServiceB(FixedServiceA serviceA) {
                    this.serviceA = serviceA;
                    System.out.println("ServiceB创建");
                }

                public void process() {
                    System.out.println("ServiceB处理");
                }
            }

            // 创建顺序
            // 1. 创建ServiceA(注入Provider<ServiceB>,ServiceB未创建)
            // 2. 创建ServiceB(注入ServiceA)
            // 3. 循环打破

            // ✅ 解决方案2:重新设计(推荐)
            // 循环依赖通常表明设计问题,应考虑重构
            @Singleton
            public class ServiceA {
                private final SharedComponent sharedComponent;

                public ServiceA(SharedComponent sharedComponent) {
                    this.sharedComponent = sharedComponent;
                }
            }

            @Singleton
            public class ServiceB {
                private final SharedComponent sharedComponent;

                public ServiceB(SharedComponent sharedComponent) {
                    this.sharedComponent = sharedComponent;
                }
            }

            @Singleton
            public class SharedComponent {
                // 提取公共逻辑,消除循环依赖
            }
            ---

04.高级Provider用法
    a.条件化获取
        a.动态Bean选择
            通过Provider配合运行时条件动态选择Bean实例。
        b.动态选择示例
            ---
            import jakarta.inject.Provider;
            import jakarta.inject.Named;

            @Singleton
            public class StorageService {
                private final Provider<CloudStorage> s3Provider;
                private final Provider<CloudStorage> ossProvider;
                private final Provider<CloudStorage> localProvider;

                public StorageService(
                    @Named("s3") Provider<CloudStorage> s3Provider,
                    @Named("oss") Provider<CloudStorage> ossProvider,
                    @Named("local") Provider<CloudStorage> localProvider) {

                    this.s3Provider = s3Provider;
                    this.ossProvider = ossProvider;
                    this.localProvider = localProvider;
                }

                public void upload(String key, byte[] data, String region) {
                    // 根据区域动态选择存储
                    CloudStorage storage = selectStorage(region);
                    storage.upload(key, data);
                }

                private CloudStorage selectStorage(String region) {
                    switch (region) {
                        case "us":
                        case "eu":
                            return s3Provider.get();  // 使用AWS S3
                        case "cn":
                            return ossProvider.get(); // 使用阿里云OSS
                        default:
                            return localProvider.get(); // 使用本地存储
                    }
                }
            }

            // 定义各个存储实现
            @Singleton
            @Named("s3")
            public class S3Storage implements CloudStorage {
                @Override
                public void upload(String key, byte[] data) {
                    System.out.println("上传到S3: " + key);
                }
            }

            @Singleton
            @Named("oss")
            public class OssStorage implements CloudStorage {
                @Override
                public void upload(String key, byte[] data) {
                    System.out.println("上传到OSS: " + key);
                }
            }

            @Singleton
            @Named("local")
            public class LocalStorage implements CloudStorage {
                @Override
                public void upload(String key, byte[] data) throws IOException {
                    System.out.println("保存到本地: " + key);
                    Files.write(Paths.get("/tmp", key), data);
                }
            }
            ---
    b.懒加载优化
        a.按需创建
            使用Provider延迟创建重量级Bean,减少应用启动时间和内存占用。
        b.懒加载示例
            ---
            @Singleton
            public class ApplicationInitializer {
                private final Provider<HeavyAnalyticsEngine> analyticsProvider;
                private final Provider<MachineLearningModel> mlModelProvider;
                private final Provider<BigDataProcessor> bigDataProvider;

                public ApplicationInitializer(
                    Provider<HeavyAnalyticsEngine> analyticsProvider,
                    Provider<MachineLearningModel> mlModelProvider,
                    Provider<BigDataProcessor> bigDataProvider) {

                    this.analyticsProvider = analyticsProvider;
                    this.mlModelProvider = mlModelProvider;
                    this.bigDataProvider = bigDataProvider;

                    System.out.println("ApplicationInitializer创建完成");
                    System.out.println("重量级组件未初始化,应用快速启动");
                }

                public void runAnalytics(AnalyticsRequest request) {
                    // 首次调用时才创建HeavyAnalyticsEngine
                    HeavyAnalyticsEngine engine = analyticsProvider.get();
                    engine.analyze(request);
                }

                public void runPrediction(PredictionRequest request) {
                    // 首次调用时才加载机器学习模型
                    MachineLearningModel model = mlModelProvider.get();
                    model.predict(request);
                }
            }

            @Singleton
            public class HeavyAnalyticsEngine {
                public HeavyAnalyticsEngine() {
                    System.out.println("初始化分析引擎(耗时3秒)");
                    // 模拟耗时初始化
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {}
                }

                public AnalyticsResult analyze(AnalyticsRequest request) {
                    return new AnalyticsResult();
                }
            }

            @Singleton
            public class MachineLearningModel {
                public MachineLearningModel() {
                    System.out.println("加载机器学习模型(耗时5秒)");
                    // 加载大型模型文件
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {}
                }

                public PredictionResult predict(PredictionRequest request) {
                    return new PredictionResult();
                }
            }

            // 启动时间对比
            // 不使用Provider: 应用启动耗时8秒(3+5)
            // 使用Provider: 应用启动耗时<1秒,按需加载组件
            ---

05.@EachBean动态Bean
    a.基于配置创建多个Bean
        a.@EachBean注解
            @EachBean根据配置中的每个条目创建对应的Bean实例,适合多数据源、多租户等场景。
        b.EachBean示例
            ---
            import io.micronaut.context.annotation.EachBean;
            import io.micronaut.context.annotation.ConfigurationProperties;

            // 1. 定义数据源配置类
            @ConfigurationProperties("datasources")
            public class DataSourceConfiguration {
                private Map<String, DataSourceSettings> datasources;

                public Map<String, DataSourceSettings> getDatasources() {
                    return datasources;
                }

                public void setDatasources(Map<String, DataSourceSettings> datasources) {
                    this.datasources = datasources;
                }

                public static class DataSourceSettings {
                    private String url;
                    private String username;
                    private String password;
                    private int maxPoolSize;

                    // Getter和Setter省略
                }
            }

            // 2. 为每个数据源创建Bean
            @EachBean(DataSourceConfiguration.DataSourceSettings.class)
            public class DynamicDataSource {
                private final String name;
                private final HikariDataSource dataSource;

                public DynamicDataSource(
                    BeanIdentifier identifier,
                    DataSourceConfiguration.DataSourceSettings settings) {

                    this.name = identifier.getName();
                    System.out.println("创建数据源: " + name);

                    HikariConfig config = new HikariConfig();
                    config.setJdbcUrl(settings.getUrl());
                    config.setUsername(settings.getUsername());
                    config.setPassword(settings.getPassword());
                    config.setMaximumPoolSize(settings.getMaxPoolSize());

                    this.dataSource = new HikariDataSource(config);
                }

                public Connection getConnection() throws SQLException {
                    return dataSource.getConnection();
                }

                public String getName() {
                    return name;
                }

                @PreDestroy
                public void close() {
                    System.out.println("关闭数据源: " + name);
                    dataSource.close();
                }
            }

            // application.yml配置
            // datasources:
            //   primary:
            //     url: jdbc:mysql://localhost:3306/main
            //     username: root
            //     password: secret
            //     max-pool-size: 10
            //   secondary:
            //     url: jdbc:mysql://localhost:3306/backup
            //     username: root
            //     password: secret
            //     max-pool-size: 5
            //   analytics:
            //     url: jdbc:postgresql://localhost:5432/analytics
            //     username: analyst
            //     password: secret
            //     max-pool-size: 20

            // 创建结果
            // 创建数据源: primary
            // 创建数据源: secondary
            // 创建数据源: analytics

            // 使用动态创建的数据源
            @Singleton
            public class MultiDataSourceManager {
                private final Map<String, DynamicDataSource> dataSources;

                public MultiDataSourceManager(List<DynamicDataSource> dataSourceList) {
                    this.dataSources = new HashMap<>();
                    for (DynamicDataSource ds : dataSourceList) {
                        dataSources.put(ds.getName(), ds);
                    }
                    System.out.println("管理 " + dataSources.size() + " 个数据源");
                }

                public Connection getConnection(String name) throws SQLException {
                    DynamicDataSource ds = dataSources.get(name);
                    if (ds == null) {
                        throw new IllegalArgumentException("数据源不存在: " + name);
                    }
                    return ds.getConnection();
                }
            }
            ---
    b.@EachProperty详解
        a.配置项遍历
            @EachProperty遍历配置中的每个子项,为每个子项创建Bean实例。
        b.EachProperty示例
            ---
            import io.micronaut.context.annotation.EachProperty;
            import io.micronaut.context.annotation.Parameter;

            // 1. 定义租户配置Bean
            @EachProperty("tenants")
            public class TenantConfiguration {
                private final String tenantId;
                private String name;
                private String database;
                private String schema;
                private boolean enabled;

                public TenantConfiguration(@Parameter String tenantId) {
                    this.tenantId = tenantId;
                    System.out.println("加载租户配置: " + tenantId);
                }

                public String getTenantId() { return tenantId; }
                public String getName() { return name; }
                public void setName(String name) { this.name = name; }
                public String getDatabase() { return database; }
                public void setDatabase(String database) { this.database = database; }
                public String getSchema() { return schema; }
                public void setSchema(String schema) { this.schema = schema; }
                public boolean isEnabled() { return enabled; }
                public void setEnabled(boolean enabled) { this.enabled = enabled; }
            }

            // 2. 为每个租户创建数据源
            @EachBean(TenantConfiguration.class)
            public class TenantDataSource {
                private final TenantConfiguration config;
                private final HikariDataSource dataSource;

                public TenantDataSource(TenantConfiguration config) {
                    this.config = config;

                    if (!config.isEnabled()) {
                        System.out.println("租户未启用: " + config.getTenantId());
                        this.dataSource = null;
                        return;
                    }

                    System.out.println("创建租户数据源: " + config.getTenantId());

                    HikariConfig hikariConfig = new HikariConfig();
                    hikariConfig.setJdbcUrl(config.getDatabase());
                    hikariConfig.setSchema(config.getSchema());
                    this.dataSource = new HikariDataSource(hikariConfig);
                }

                public Connection getConnection() throws SQLException {
                    if (dataSource == null) {
                        throw new IllegalStateException("租户未启用");
                    }
                    return dataSource.getConnection();
                }

                public String getTenantId() {
                    return config.getTenantId();
                }
            }

            // application.yml配置
            // tenants:
            //   tenant-001:
            //     name: "客户A"
            //     database: "jdbc:mysql://localhost:3306/tenant_001"
            //     schema: "public"
            //     enabled: true
            //   tenant-002:
            //     name: "客户B"
            //     database: "jdbc:mysql://localhost:3306/tenant_002"
            //     schema: "public"
            //     enabled: true
            //   tenant-003:
            //     name: "客户C"
            //     database: "jdbc:mysql://localhost:3306/tenant_003"
            //     schema: "public"
            //     enabled: false

            // 创建结果
            // 加载租户配置: tenant-001
            // 创建租户数据源: tenant-001
            // 加载租户配置: tenant-002
            // 创建租户数据源: tenant-002
            // 加载租户配置: tenant-003
            // 租户未启用: tenant-003

            // 3. 使用租户数据源
            @Singleton
            public class MultiTenantService {
                private final Map<String, TenantDataSource> tenantDataSources;

                public MultiTenantService(List<TenantDataSource> dataSourceList) {
                    this.tenantDataSources = new HashMap<>();
                    for (TenantDataSource ds : dataSourceList) {
                        tenantDataSources.put(ds.getTenantId(), ds);
                    }
                    System.out.println("管理 " + tenantDataSources.size() + " 个租户");
                }

                public List<User> getUsersByTenant(String tenantId) throws SQLException {
                    TenantDataSource ds = tenantDataSources.get(tenantId);
                    if (ds == null) {
                        throw new IllegalArgumentException("租户不存在: " + tenantId);
                    }

                    try (Connection conn = ds.getConnection();
                         Statement stmt = conn.createStatement();
                         ResultSet rs = stmt.executeQuery("SELECT * FROM users")) {

                        List<User> users = new ArrayList<>();
                        while (rs.next()) {
                            users.add(mapUser(rs));
                        }
                        return users;
                    }
                }

                private User mapUser(ResultSet rs) throws SQLException {
                    return new User();
                }
            }
            ---

06.Bean替换
    a.@Replaces注解
        a.Bean覆盖
            @Replaces允许新Bean替换已存在的Bean,常用于测试、自定义实现或库的默认Bean覆盖。
        b.Bean替换示例
            ---
            import io.micronaut.context.annotation.Replaces;

            // 原始Bean
            @Singleton
            public class DefaultEmailService implements EmailService {
                public DefaultEmailService() {
                    System.out.println("创建默认邮件服务");
                }

                @Override
                public void send(String to, String subject, String body) {
                    System.out.println("发送邮件到: " + to);
                    // SMTP发送逻辑
                }
            }

            // 测试环境替换为Mock实现
            @Singleton
            @Replaces(DefaultEmailService.class)
            @Requires(env = Environment.TEST)
            public class MockEmailService implements EmailService {
                private final List<Email> sentEmails = new ArrayList<>();

                public MockEmailService() {
                    System.out.println("创建Mock邮件服务(测试环境)");
                }

                @Override
                public void send(String to, String subject, String body) {
                    System.out.println("Mock发送邮件到: " + to);
                    sentEmails.add(new Email(to, subject, body));
                }

                public List<Email> getSentEmails() {
                    return sentEmails;
                }
            }

            // 使用场景
            @Singleton
            public class UserService {
                private final EmailService emailService;

                public UserService(EmailService emailService) {
                    this.emailService = emailService;
                    // 开发/生产环境: 注入DefaultEmailService
                    // 测试环境: 注入MockEmailService
                }

                public void registerUser(User user) {
                    // 保存用户
                    saveUser(user);

                    // 发送欢迎邮件
                    emailService.send(
                        user.getEmail(),
                        "欢迎注册",
                        "欢迎加入我们的平台!"
                    );
                }

                private void saveUser(User user) {
                    // 保存逻辑
                }
            }

            // 测试代码
            @MicronautTest(environments = Environment.TEST)
            class UserServiceTest {
                @Inject
                UserService userService;

                @Inject
                MockEmailService mockEmailService;  // 可以注入Mock服务验证

                @Test
                void testRegisterUser() {
                    User user = new User();
                    user.setEmail("[email protected]");

                    userService.registerUser(user);

                    // 验证邮件已发送
                    List<Email> emails = mockEmailService.getSentEmails();
                    assertEquals(1, emails.size());
                    assertEquals("[email protected]", emails.get(0).getTo());
                }
            }
            ---
    b.@Replaces工厂方法
        a.替换工厂Bean
            可以替换@Factory中的@Bean方法创建的Bean。
        b.工厂替换示例
            ---
            // 原始工厂
            @Factory
            public class DefaultCacheFactory {
                @Bean
                @Singleton
                @Named("userCache")
                public Cache userCache() {
                    System.out.println("创建默认用户缓存(Caffeine)");
                    return Caffeine.newBuilder()
                        .maximumSize(1000)
                        .expireAfterWrite(10, TimeUnit.MINUTES)
                        .build();
                }
            }

            // 生产环境替换为Redis缓存
            @Factory
            @Requires(env = Environment.PRODUCTION)
            public class ProductionCacheFactory {
                @Bean
                @Singleton
                @Named("userCache")
                @Replaces(bean = Cache.class, named = "userCache")
                public Cache redisUserCache(RedisClient redisClient) {
                    System.out.println("创建Redis用户缓存(生产环境)");
                    return new RedisCache(redisClient, "users");
                }
            }

            // 使用Bean
            @Singleton
            public class UserService {
                private final Cache userCache;

                public UserService(@Named("userCache") Cache userCache) {
                    this.userCache = userCache;
                    // 开发环境: Caffeine缓存
                    // 生产环境: Redis缓存
                }

                public User findUser(Long userId) {
                    // 从缓存获取
                    User user = userCache.getIfPresent(userId);
                    if (user != null) {
                        return user;
                    }

                    // 从数据库查询
                    user = userRepository.findById(userId);
                    userCache.put(userId, user);
                    return user;
                }
            }
            ---

07.工厂与Provider最佳实践
    a.使用场景选择
        a.选择指南
            @Factory适合第三方类、复杂初始化、多Bean创建,Provider适合循环依赖、懒加载、作用域不匹配。
        b.场景对比
            ---
            // 场景1:第三方类 → 使用@Factory
            @Factory
            public class ThirdPartyFactory {
                @Bean
                @Singleton
                public ObjectMapper objectMapper() {
                    ObjectMapper mapper = new ObjectMapper();
                    mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
                    mapper.registerModule(new JavaTimeModule());
                    return mapper;
                }
            }

            // 场景2:循环依赖 → 使用Provider
            @Singleton
            public class ServiceWithCircular {
                private final Provider<DependentService> dependentProvider;

                public ServiceWithCircular(Provider<DependentService> dependentProvider) {
                    this.dependentProvider = dependentProvider;
                }
            }

            // 场景3:Prototype懒加载 → 使用Provider
            @Singleton
            public class TaskManager {
                private final Provider<TaskHandler> handlerProvider;

                public TaskManager(Provider<TaskHandler> handlerProvider) {
                    this.handlerProvider = handlerProvider;
                }

                public void handleTask() {
                    TaskHandler handler = handlerProvider.get();  // 每次新实例
                    handler.handle();
                }
            }

            // 场景4:条件化创建 → 使用@Requires + @Factory
            @Factory
            public class ConditionalBeanFactory {
                @Bean
                @Singleton
                @Requires(property = "cache.type", value = "redis")
                public CacheService redisCache() {
                    return new RedisCacheService();
                }

                @Bean
                @Singleton
                @Requires(property = "cache.type", value = "memcached")
                public CacheService memcachedCache() {
                    return new MemcachedCacheService();
                }
            }

            // 场景5:多实例管理 → 使用@EachBean
            @EachProperty("services")
            public class ServiceConfiguration {
                private String endpoint;
                private int timeout;
                // 配置省略
            }

            @EachBean(ServiceConfiguration.class)
            public class ExternalServiceClient {
                // 为每个配置项创建客户端
            }
            ---
    b.性能考虑
        a.工厂方法性能
            @Factory方法在Bean首次创建时执行,Singleton Bean只执行一次,性能影响可忽略。
        b.Provider性能
            ---
            // Provider性能测试
            @Singleton
            public class ProviderPerformanceTest {
                private final SingletonBean singletonBean;
                private final Provider<SingletonBean> singletonProvider;
                private final Provider<PrototypeBean> prototypeProvider;

                public ProviderPerformanceTest(
                    SingletonBean singletonBean,
                    Provider<SingletonBean> singletonProvider,
                    Provider<PrototypeBean> prototypeProvider) {

                    this.singletonBean = singletonBean;
                    this.singletonProvider = singletonProvider;
                    this.prototypeProvider = prototypeProvider;
                }

                public void testPerformance() {
                    // 测试1:直接访问Singleton
                    long start1 = System.nanoTime();
                    for (int i = 0; i < 1_000_000; i++) {
                        singletonBean.doSomething();
                    }
                    long duration1 = System.nanoTime() - start1;
                    System.out.println("直接访问: " + duration1 / 1_000_000 + "ms");

                    // 测试2:通过Provider访问Singleton
                    long start2 = System.nanoTime();
                    for (int i = 0; i < 1_000_000; i++) {
                        singletonProvider.get().doSomething();
                    }
                    long duration2 = System.nanoTime() - start2;
                    System.out.println("Provider访问Singleton: " +
                                     duration2 / 1_000_000 + "ms");

                    // 测试3:通过Provider创建Prototype
                    long start3 = System.nanoTime();
                    for (int i = 0; i < 10000; i++) {
                        PrototypeBean bean = prototypeProvider.get();
                        bean.doSomething();
                    }
                    long duration3 = System.nanoTime() - start3;
                    System.out.println("Provider创建Prototype: " +
                                     duration3 / 1_000_000 + "ms");
                }
            }

            // 测试结果
            // 直接访问: 15ms
            // Provider访问Singleton: 18ms(略慢,因为多一次方法调用)
            // Provider创建Prototype: 580ms(每次创建实例)

            // 性能建议
            // ✅ Singleton直接依赖性能最优
            // ✅ Provider<Singleton>开销很小,可以使用
            // ⚠️ Provider<Prototype>频繁调用会影响性能
            // ❌ 避免在循环中频繁调用prototypeProvider.get()
            ---

08.工厂最佳实践
    a.工厂设计原则
        a.单一职责
            每个@Factory类应该只负责创建相关的一组Bean,遵循单一职责原则。
        b.工厂组织示例
            ---
            // ✅ 推荐:按功能组织工厂
            @Factory
            public class DatabaseFactory {
                @Bean
                @Singleton
                public DataSource dataSource() { return null; }

                @Bean
                @Singleton
                public JdbcTemplate jdbcTemplate(DataSource ds) { return null; }

                @Bean
                @Singleton
                public TransactionManager transactionManager(DataSource ds) { return null; }
            }

            @Factory
            public class CacheFactory {
                @Bean
                @Singleton
                public CacheManager cacheManager() { return null; }

                @Bean
                @Singleton
                public Cache userCache() { return null; }

                @Bean
                @Singleton
                public Cache productCache() { return null; }
            }

            // ❌ 不推荐:混合不相关的Bean
            @Factory
            public class MixedFactory {
                @Bean public DataSource dataSource() { return null; }
                @Bean public EmailService emailService() { return null; }
                @Bean public FileStorage fileStorage() { return null; }
                @Bean public MessageQueue messageQueue() { return null; }
                // 职责混乱,难以维护
            }
            ---
    b.资源管理
        a.PreDestroy处理
            @Factory创建的Bean应该正确处理资源释放,通过@PreDestroy或实现Closeable接口。
        b.资源管理示例
            ---
            @Factory
            public class ResourceFactory {
                // 方案1:返回实现Closeable的Bean
                @Bean
                @Singleton
                public CloseableHttpClient httpClient() {
                    System.out.println("创建HTTP客户端");
                    return HttpClients.custom()
                        .setMaxConnTotal(100)
                        .setMaxConnPerRoute(20)
                        .build();
                    // BeanContext关闭时自动调用close()
                }

                // 方案2:创建包装类处理清理
                @Bean
                @Singleton
                public ExecutorServiceWrapper executorService() {
                    System.out.println("创建线程池");
                    ExecutorService executor = Executors.newFixedThreadPool(10);
                    return new ExecutorServiceWrapper(executor);
                }
            }

            public class ExecutorServiceWrapper implements Closeable {
                private final ExecutorService executor;

                public ExecutorServiceWrapper(ExecutorService executor) {
                    this.executor = executor;
                }

                public void execute(Runnable task) {
                    executor.execute(task);
                }

                @Override
                public void close() throws IOException {
                    System.out.println("关闭线程池");
                    executor.shutdown();
                    try {
                        if (!executor.awaitTermination(30, TimeUnit.SECONDS)) {
                            executor.shutdownNow();
                        }
                    } catch (InterruptedException e) {
                        executor.shutdownNow();
                    }
                }
            }

            // 方案3:使用@PreDestroy方法
            @Factory
            public class ConnectionFactory {
                private Connection connection;

                @Bean
                @Singleton
                public Connection databaseConnection() throws SQLException {
                    System.out.println("创建数据库连接");
                    this.connection = DriverManager.getConnection("jdbc:...");
                    return connection;
                }

                @PreDestroy
                public void cleanup() throws SQLException {
                    if (connection != null && !connection.isClosed()) {
                        System.out.println("关闭数据库连接");
                        connection.close();
                    }
                }
            }
            ---

09.总结与对比
    a.工厂vs构造器
        a.使用场景
            构造器注入适合自有类,@Factory适合第三方类、需要复杂配置或条件化创建的Bean。
        b.对比示例
            ---
            // 场景1:自有类 → 直接使用@Singleton
            @Singleton
            public class UserService {
                private final UserRepository repository;

                public UserService(UserRepository repository) {
                    this.repository = repository;
                }
            }

            // 场景2:第三方类 → 使用@Factory
            @Factory
            public class JacksonFactory {
                @Bean
                @Singleton
                public ObjectMapper objectMapper() {
                    ObjectMapper mapper = new ObjectMapper();
                    // 无法在第三方类上添加@Singleton
                    mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
                    return mapper;
                }
            }

            // 场景3:复杂初始化 → 使用@Factory
            @Factory
            public class SecurityFactory {
                @Bean
                @Singleton
                public SecurityManager securityManager() {
                    SecurityManager manager = new SecurityManager();

                    // 复杂配置
                    manager.setRealm(new JdbcRealm());
                    manager.setSessionManager(new DefaultSessionManager());
                    manager.setCacheManager(new RedisCacheManager());

                    // 初始化
                    manager.init();

                    return manager;
                }
            }

            // 场景4:条件化创建 → 使用@Factory + @Requires
            @Factory
            public class StorageFactory {
                @Bean
                @Singleton
                @Requires(property = "storage.type", value = "s3")
                public Storage s3Storage() {
                    return new S3Storage();
                }

                @Bean
                @Singleton
                @Requires(property = "storage.type", value = "local")
                public Storage localStorage() {
                    return new LocalStorage();
                }
            }
            ---
    b.Provider最佳实践
        a.使用时机
            仅在确实需要延迟获取或解决循环依赖时使用Provider,过度使用会降低代码可读性。
        b.Provider建议
            ---
            // ✅ 推荐:解决循环依赖
            @Singleton
            public class ServiceA {
                private final Provider<ServiceB> serviceBProvider;

                public ServiceA(Provider<ServiceB> serviceBProvider) {
                    this.serviceBProvider = serviceBProvider;
                }
            }

            // ✅ 推荐:Singleton依赖Prototype
            @Singleton
            public class TaskManager {
                private final Provider<TaskHandler> handlerProvider;

                public TaskManager(Provider<TaskHandler> handlerProvider) {
                    this.handlerProvider = handlerProvider;
                }

                public void executeTask() {
                    TaskHandler handler = handlerProvider.get();  // 每次新实例
                    handler.handle();
                }
            }

            // ✅ 推荐:懒加载重量级Bean
            @Singleton
            public class Application {
                private final Provider<HeavyEngine> engineProvider;

                public Application(Provider<HeavyEngine> engineProvider) {
                    this.engineProvider = engineProvider;
                }

                public void startEngine() {
                    HeavyEngine engine = engineProvider.get();  // 仅在需要时创建
                    engine.start();
                }
            }

            // ❌ 不推荐:Singleton依赖Singleton使用Provider
            @Singleton
            public class ServiceX {
                private final Provider<ServiceY> serviceYProvider;  // 不必要

                public ServiceX(Provider<ServiceY> serviceYProvider) {
                    this.serviceYProvider = serviceYProvider;
                }

                public void doSomething() {
                    ServiceY serviceY = serviceYProvider.get();  // 多余的间接访问
                    serviceY.process();
                }
            }

            // ✅ 推荐:Singleton直接依赖Singleton
            @Singleton
            public class ImprovedServiceX {
                private final ServiceY serviceY;  // 直接注入

                public ImprovedServiceX(ServiceY serviceY) {
                    this.serviceY = serviceY;
                }

                public void doSomething() {
                    serviceY.process();  // 直接访问
                }
            }

            // 总结
            // Provider使用场景:
            // ✅ 解决循环依赖
            // ✅ 长生命周期依赖短生命周期(Singleton → Prototype/RequestScope)
            // ✅ 懒加载优化
            // ✅ 运行时动态选择Bean
            // ❌ 避免无意义的Provider使用
            ---

4 HTTP服务开发

4.1 @Controller控制器

01.控制器基础
    a.@Controller注解
        a.控制器定义
            @Controller注解将类标记为HTTP端点处理器,通过路径映射接收HTTP请求并返回响应,是构建REST API的核心组件。
        b.基础控制器示例
            ---
            import io.micronaut.http.annotation.*;
            import io.micronaut.http.HttpStatus;
            import jakarta.inject.Singleton;

            @Controller("/api/users")
            public class UserController {
                private final UserService userService;

                public UserController(UserService userService) {
                    this.userService = userService;
                }

                // GET请求
                @Get("/{id}")
                public User getUser(Long id) {
                    System.out.println("GET /api/users/" + id);
                    return userService.findById(id);
                }

                // POST请求
                @Post
                public User createUser(@Body User user) {
                    System.out.println("POST /api/users");
                    return userService.save(user);
                }

                // PUT请求
                @Put("/{id}")
                public User updateUser(Long id, @Body User user) {
                    System.out.println("PUT /api/users/" + id);
                    user.setId(id);
                    return userService.update(user);
                }

                // DELETE请求
                @Delete("/{id}")
                @Status(HttpStatus.NO_CONTENT)
                public void deleteUser(Long id) {
                    System.out.println("DELETE /api/users/" + id);
                    userService.delete(id);
                }

                // 列表查询
                @Get
                public List<User> listUsers(
                    @QueryValue(defaultValue = "0") int page,
                    @QueryValue(defaultValue = "20") int size) {

                    System.out.println("GET /api/users?page=" + page + "&size=" + size);
                    return userService.findAll(page, size);
                }
            }

            // URL映射示例
            // GET    /api/users/123         → getUser(123)
            // POST   /api/users             → createUser(user)
            // PUT    /api/users/123         → updateUser(123, user)
            // DELETE /api/users/123         → deleteUser(123)
            // GET    /api/users?page=0&size=10 → listUsers(0, 10)
            ---
    b.路径变量
        a.@PathVariable映射
            通过{}语法在路径中定义变量,方法参数自动接收路径中对应位置的值。
        b.路径变量示例
            ---
            @Controller("/api")
            public class ResourceController {
                // 单个路径变量
                @Get("/users/{userId}")
                public User getUser(Long userId) {
                    // userId自动从路径提取
                    return userService.findById(userId);
                }

                // 多个路径变量
                @Get("/users/{userId}/orders/{orderId}")
                public Order getUserOrder(Long userId, Long orderId) {
                    return orderService.findByUserAndOrder(userId, orderId);
                }

                // 字符串路径变量
                @Get("/categories/{category}/products/{productCode}")
                public Product getProduct(String category, String productCode) {
                    System.out.println("分类: " + category + ", 产品代码: " + productCode);
                    return productService.findByCode(category, productCode);
                }

                // 可选路径变量
                @Get("/search{/keyword}")
                public List<Product> search(@Nullable String keyword) {
                    if (keyword == null) {
                        // GET /api/search → 返回全部
                        return productService.findAll();
                    } else {
                        // GET /api/search/手机 → 搜索"手机"
                        return productService.search(keyword);
                    }
                }

                // 正则表达式约束
                @Get("/products/{id:[0-9]+}")
                public Product getProductById(Long id) {
                    // id必须是数字
                    return productService.findById(id);
                }

                @Get("/users/{username:[a-zA-Z0-9_]+}")
                public User getUserByUsername(String username) {
                    // username只能包含字母数字下划线
                    return userService.findByUsername(username);
                }

                // 路径变量类型转换
                @Get("/orders/{date}")
                public List<Order> getOrdersByDate(
                    @Format("yyyy-MM-dd") LocalDate date) {
                    // 自动将字符串转换为LocalDate
                    System.out.println("查询日期: " + date);
                    return orderService.findByDate(date);
                }
            }

            // URL示例
            // GET /api/users/123 → userId=123
            // GET /api/users/123/orders/456 → userId=123, orderId=456
            // GET /api/categories/electronics/products/P001 → category="electronics", productCode="P001"
            // GET /api/search → keyword=null
            // GET /api/search/手机 → keyword="手机"
            // GET /api/orders/2024-01-15 → date=LocalDate(2024-01-15)
            ---

02.请求方法映射
    a.HTTP方法注解
        a.RESTful方法
            Micronaut提供@Get、@Post、@Put、@Delete、@Patch、@Head、@Options等注解对应HTTP方法。
        b.方法注解示例
            ---
            @Controller("/api/products")
            public class ProductController {
                // GET: 查询单个资源
                @Get("/{id}")
                public Product getProduct(Long id) {
                    return productService.findById(id);
                }

                // GET: 查询资源列表
                @Get
                public List<Product> listProducts() {
                    return productService.findAll();
                }

                // POST: 创建资源
                @Post
                @Status(HttpStatus.CREATED)
                public Product createProduct(@Body Product product) {
                    return productService.create(product);
                }

                // PUT: 完整更新资源
                @Put("/{id}")
                public Product updateProduct(Long id, @Body Product product) {
                    product.setId(id);
                    return productService.update(product);
                }

                // PATCH: 部分更新资源
                @Patch("/{id}")
                public Product patchProduct(Long id, @Body Map<String, Object> updates) {
                    return productService.partialUpdate(id, updates);
                }

                // DELETE: 删除资源
                @Delete("/{id}")
                @Status(HttpStatus.NO_CONTENT)
                public void deleteProduct(Long id) {
                    productService.delete(id);
                }

                // HEAD: 检查资源是否存在
                @Head("/{id}")
                public HttpResponse<?> checkProduct(Long id) {
                    boolean exists = productService.exists(id);
                    return exists ?
                        HttpResponse.ok() :
                        HttpResponse.notFound();
                }

                // OPTIONS: 获取支持的HTTP方法
                @Options("/{id}")
                public HttpResponse<?> options() {
                    return HttpResponse.ok()
                        .header("Allow", "GET, PUT, PATCH, DELETE, HEAD, OPTIONS");
                }
            }

            // RESTful API设计
            // GET    /api/products          → 列表查询
            // GET    /api/products/123      → 查询单个
            // POST   /api/products          → 创建
            // PUT    /api/products/123      → 完整更新
            // PATCH  /api/products/123      → 部分更新
            // DELETE /api/products/123      → 删除
            // HEAD   /api/products/123      → 检查存在
            // OPTIONS /api/products/123     → 查询支持的方法
            ---
    b.自定义HTTP方法
        a.@CustomHttpMethod
            支持自定义HTTP方法,用于扩展标准HTTP方法集。
        b.自定义方法示例
            ---
            import io.micronaut.http.annotation.CustomHttpMethod;
            import io.micronaut.http.HttpMethod;

            @Controller("/api/cache")
            public class CacheController {
                private final CacheService cacheService;

                public CacheController(CacheService cacheService) {
                    this.cacheService = cacheService;
                }

                // 自定义PURGE方法(清除缓存)
                @CustomHttpMethod(method = "PURGE")
                @Status(HttpStatus.NO_CONTENT)
                public void purgeCache(@QueryValue String key) {
                    System.out.println("PURGE /api/cache?key=" + key);
                    cacheService.invalidate(key);
                }

                // 自定义LOCK方法(锁定资源)
                @CustomHttpMethod(method = "LOCK", value = "/{resource}")
                public LockResponse lockResource(String resource) {
                    System.out.println("LOCK /api/cache/" + resource);
                    String lockToken = cacheService.lock(resource);
                    return new LockResponse(lockToken);
                }

                // 自定义UNLOCK方法(解锁资源)
                @CustomHttpMethod(method = "UNLOCK", value = "/{resource}")
                @Status(HttpStatus.NO_CONTENT)
                public void unlockResource(
                    String resource,
                    @Header("Lock-Token") String lockToken) {

                    System.out.println("UNLOCK /api/cache/" + resource);
                    cacheService.unlock(resource, lockToken);
                }
            }

            // 使用示例
            // PURGE /api/cache?key=user:123
            // LOCK /api/cache/report-123
            // UNLOCK /api/cache/report-123 (Header: Lock-Token: xxx)
            ---

03.请求参数绑定
    a.查询参数
        a.@QueryValue注解
            通过@QueryValue绑定URL查询参数,支持默认值、类型转换和可选参数。
        b.查询参数示例
            ---
            @Controller("/api/search")
            public class SearchController {
                // 必需参数
                @Get
                public List<Product> search(@QueryValue String keyword) {
                    // GET /api/search?keyword=手机
                    System.out.println("搜索: " + keyword);
                    return productService.search(keyword);
                }

                // 可选参数
                @Get("/advanced")
                public List<Product> advancedSearch(
                    @QueryValue @Nullable String keyword,
                    @QueryValue @Nullable String category,
                    @QueryValue @Nullable BigDecimal minPrice,
                    @QueryValue @Nullable BigDecimal maxPrice) {

                    System.out.println("高级搜索:");
                    System.out.println("  关键词: " + keyword);
                    System.out.println("  分类: " + category);
                    System.out.println("  价格区间: " + minPrice + " - " + maxPrice);

                    return productService.advancedSearch(
                        keyword, category, minPrice, maxPrice);
                }

                // 默认值
                @Get("/list")
                public List<Product> listProducts(
                    @QueryValue(defaultValue = "0") int page,
                    @QueryValue(defaultValue = "20") int size,
                    @QueryValue(defaultValue = "id") String sortBy,
                    @QueryValue(defaultValue = "asc") String order) {

                    System.out.println("分页查询: page=" + page +
                                     ", size=" + size +
                                     ", sortBy=" + sortBy +
                                     ", order=" + order);

                    return productService.findAll(page, size, sortBy, order);
                }

                // 数组参数
                @Get("/filter")
                public List<Product> filterProducts(
                    @QueryValue("tag") List<String> tags,
                    @QueryValue("status") List<String> statuses) {

                    System.out.println("标签: " + tags);
                    System.out.println("状态: " + statuses);

                    return productService.filter(tags, statuses);
                }

                // 日期参数
                @Get("/orders")
                public List<Order> getOrders(
                    @QueryValue @Format("yyyy-MM-dd") LocalDate startDate,
                    @QueryValue @Format("yyyy-MM-dd") LocalDate endDate) {

                    System.out.println("查询订单: " + startDate + " 至 " + endDate);
                    return orderService.findByDateRange(startDate, endDate);
                }

                // Boolean参数
                @Get("/products")
                public List<Product> getProducts(
                    @QueryValue(defaultValue = "false") boolean includeDeleted,
                    @QueryValue(defaultValue = "true") boolean inStock) {

                    return productService.find(includeDeleted, inStock);
                }
            }

            // URL示例
            // GET /api/search?keyword=手机
            // GET /api/search/advanced?keyword=手机&category=电子&minPrice=1000&maxPrice=5000
            // GET /api/search/list (使用默认值: page=0, size=20, sortBy=id, order=asc)
            // GET /api/search/list?page=1&size=50&sortBy=price&order=desc
            // GET /api/search/filter?tag=hot&tag=new&status=active&status=promoted
            // GET /api/search/orders?startDate=2024-01-01&endDate=2024-12-31
            ---
    b.请求头参数
        a.@Header注解
            通过@Header绑定HTTP请求头,获取认证token、客户端信息等元数据。
        b.请求头示例
            ---
            @Controller("/api")
            public class SecureController {
                // 必需请求头
                @Get("/profile")
                public UserProfile getProfile(@Header String authorization) {
                    System.out.println("Authorization: " + authorization);

                    // 解析token
                    String token = authorization.replace("Bearer ", "");
                    Long userId = jwtService.getUserIdFromToken(token);

                    return userService.getProfile(userId);
                }

                // 可选请求头
                @Get("/content")
                public String getContent(
                    @Header("Accept-Language") @Nullable String language,
                    @Header("User-Agent") @Nullable String userAgent) {

                    System.out.println("语言: " + (language != null ? language : "default"));
                    System.out.println("客户端: " + userAgent);

                    return contentService.getContent(language);
                }

                // 自定义请求头
                @Post("/upload")
                public UploadResponse upload(
                    @Body byte[] data,
                    @Header("X-File-Name") String fileName,
                    @Header("X-File-Type") String fileType,
                    @Header(value = "X-Checksum", defaultValue = "") String checksum) {

                    System.out.println("上传文件: " + fileName);
                    System.out.println("文件类型: " + fileType);
                    System.out.println("校验和: " + checksum);

                    return fileService.upload(fileName, fileType, data, checksum);
                }

                // 多个请求头
                @Get("/api-call")
                public ApiResponse callApi(
                    @Header("X-API-Key") String apiKey,
                    @Header("X-Request-Id") String requestId,
                    @Header("X-Tenant-Id") String tenantId) {

                    System.out.println("API密钥: " + apiKey);
                    System.out.println("请求ID: " + requestId);
                    System.out.println("租户ID: " + tenantId);

                    return apiService.call(apiKey, requestId, tenantId);
                }

                // HttpHeaders对象(获取所有请求头)
                @Get("/headers")
                public Map<String, String> getAllHeaders(HttpHeaders headers) {
                    Map<String, String> result = new HashMap<>();

                    for (String name : headers.names()) {
                        result.put(name, headers.get(name));
                    }

                    System.out.println("接收到 " + result.size() + " 个请求头");
                    return result;
                }
            }

            // 请求示例
            // curl -H "Authorization: Bearer eyJhbGc..." http://localhost:8080/api/profile
            // curl -H "Accept-Language: zh-CN" http://localhost:8080/api/content
            // curl -X POST -H "X-File-Name: doc.pdf" -H "X-File-Type: application/pdf" \
            //      --data-binary @doc.pdf http://localhost:8080/api/upload
            ---

04.请求体处理
    a.@Body注解
        a.请求体绑定
            @Body注解将HTTP请求体自动反序列化为Java对象,支持JSON、XML等格式。
        b.请求体示例
            ---
            @Controller("/api/users")
            public class UserManagementController {
                // JSON请求体
                @Post
                public User createUser(@Body User user) {
                    System.out.println("创建用户: " + user.getUsername());
                    return userService.save(user);
                }

                // 嵌套对象
                @Post("/register")
                public RegistrationResponse register(@Body RegistrationRequest request) {
                    System.out.println("注册用户: " + request.getUsername());
                    System.out.println("邮箱: " + request.getEmail());
                    System.out.println("密码长度: " + request.getPassword().length());

                    User user = userService.register(request);
                    return new RegistrationResponse(user.getId(), "注册成功");
                }

                // 泛型请求体
                @Post("/batch")
                public BatchResponse<User> batchCreate(@Body List<User> users) {
                    System.out.println("批量创建 " + users.size() + " 个用户");

                    List<User> created = new ArrayList<>();
                    for (User user : users) {
                        created.add(userService.save(user));
                    }

                    return new BatchResponse<>(created.size(), created);
                }

                // Map请求体
                @Patch("/{id}")
                public User partialUpdate(Long id, @Body Map<String, Object> updates) {
                    System.out.println("更新用户 " + id + ": " + updates);

                    User user = userService.findById(id);
                    // 应用部分更新
                    if (updates.containsKey("email")) {
                        user.setEmail((String) updates.get("email"));
                    }
                    if (updates.containsKey("phone")) {
                        user.setPhone((String) updates.get("phone"));
                    }

                    return userService.update(user);
                }

                // 可选请求体
                @Post("/search")
                public List<User> search(@Body @Nullable SearchCriteria criteria) {
                    if (criteria == null) {
                        // 无请求体,返回所有用户
                        return userService.findAll();
                    }

                    return userService.search(criteria);
                }
            }

            // 请求体类定义
            public class RegistrationRequest {
                private String username;
                private String email;
                private String password;
                private UserProfile profile;

                // Getter和Setter省略
            }

            public class UserProfile {
                private String firstName;
                private String lastName;
                private LocalDate birthDate;

                // Getter和Setter省略
            }

            // JSON请求示例
            // POST /api/users
            // Content-Type: application/json
            // {
            //   "username": "john",
            //   "email": "[email protected]",
            //   "phone": "13800138000"
            // }

            // POST /api/users/register
            // {
            //   "username": "john",
            //   "email": "[email protected]",
            //   "password": "secret123",
            //   "profile": {
            //     "firstName": "John",
            //     "lastName": "Doe",
            //     "birthDate": "1990-01-15"
            //   }
            // }

            // PATCH /api/users/123
            // {
            //   "email": "[email protected]",
            //   "phone": "13900139000"
            // }
            ---
    b.内容类型协商
        a.@Consumes和@Produces
            通过@Consumes指定接受的请求类型,@Produces指定返回的响应类型。
        b.内容类型示例
            ---
            import io.micronaut.http.annotation.Consumes;
            import io.micronaut.http.annotation.Produces;
            import io.micronaut.http.MediaType;

            @Controller("/api/data")
            public class DataController {
                // 接受JSON,返回JSON(默认)
                @Post("/json")
                @Consumes(MediaType.APPLICATION_JSON)
                @Produces(MediaType.APPLICATION_JSON)
                public DataResponse processJson(@Body DataRequest request) {
                    return new DataResponse(request.getData());
                }

                // 接受XML,返回XML
                @Post("/xml")
                @Consumes(MediaType.APPLICATION_XML)
                @Produces(MediaType.APPLICATION_XML)
                public DataResponse processXml(@Body DataRequest request) {
                    return new DataResponse(request.getData());
                }

                // 接受表单数据
                @Post("/form")
                @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
                public String processForm(
                    @Body("username") String username,
                    @Body("email") String email) {

                    System.out.println("用户名: " + username);
                    System.out.println("邮箱: " + email);
                    return "表单已提交";
                }

                // 文件上传
                @Post("/upload")
                @Consumes(MediaType.MULTIPART_FORM_DATA)
                public UploadResponse uploadFile(
                    @Part("file") CompletedFileUpload file,
                    @Part("description") @Nullable String description) throws IOException {

                    System.out.println("文件名: " + file.getFilename());
                    System.out.println("大小: " + file.getSize() + " bytes");
                    System.out.println("描述: " + description);

                    byte[] bytes = file.getBytes();
                    String fileId = fileService.save(file.getFilename(), bytes);

                    return new UploadResponse(fileId, file.getFilename(), file.getSize());
                }

                // 返回纯文本
                @Get("/text")
                @Produces(MediaType.TEXT_PLAIN)
                public String getText() {
                    return "这是纯文本响应";
                }

                // 返回HTML
                @Get("/page")
                @Produces(MediaType.TEXT_HTML)
                public String getPage() {
                    return "<html><body><h1>Hello Micronaut</h1></body></html>";
                }

                // 返回二进制数据
                @Get("/download/{fileId}")
                @Produces(MediaType.APPLICATION_OCTET_STREAM)
                public byte[] downloadFile(String fileId) {
                    return fileService.load(fileId);
                }
            }

            // 请求示例
            // POST /api/data/json
            // Content-Type: application/json
            // {"data": "test"}

            // POST /api/data/form
            // Content-Type: application/x-www-form-urlencoded
            // username=john&[email protected]

            // POST /api/data/upload
            // Content-Type: multipart/form-data
            // [email protected]
            // description=重要文档
            ---

05.响应处理
    a.返回类型
        a.多种返回方式
            控制器方法可以返回对象、HttpResponse、CompletableFuture等多种类型。
        b.返回类型示例
            ---
            import io.micronaut.http.HttpResponse;
            import io.micronaut.http.MutableHttpResponse;

            @Controller("/api/responses")
            public class ResponseController {
                // 1. 返回对象(自动序列化为JSON)
                @Get("/user/{id}")
                public User getUser(Long id) {
                    return userService.findById(id);
                }

                // 2. 返回HttpResponse(自定义状态码和头)
                @Post("/users")
                public HttpResponse<User> createUser(@Body User user) {
                    User created = userService.save(user);

                    return HttpResponse.created(created)
                        .header("X-User-Id", created.getId().toString())
                        .header("Location", "/api/users/" + created.getId());
                }

                // 3. 返回MutableHttpResponse(构建响应)
                @Get("/download/{fileId}")
                public MutableHttpResponse<byte[]> downloadFile(String fileId) {
                    byte[] data = fileService.load(fileId);
                    String fileName = fileService.getFileName(fileId);

                    return HttpResponse.ok(data)
                        .contentType(MediaType.APPLICATION_OCTET_STREAM)
                        .header("Content-Disposition",
                               "attachment; filename=\"" + fileName + "\"");
                }

                // 4. 返回Optional(404处理)
                @Get("/optional/{id}")
                public Optional<User> getUserOptional(Long id) {
                    // 返回Optional.empty()时自动返回404
                    return userService.findByIdOptional(id);
                }

                // 5. 返回CompletableFuture(异步响应)
                @Get("/async/{id}")
                public CompletableFuture<User> getUserAsync(Long id) {
                    return CompletableFuture.supplyAsync(() ->
                        userService.findById(id));
                }

                // 6. 返回void(204 No Content)
                @Delete("/{id}")
                public void deleteUser(Long id) {
                    userService.delete(id);
                    // 自动返回204 No Content
                }

                // 7. 返回String(纯文本)
                @Get("/hello")
                @Produces(MediaType.TEXT_PLAIN)
                public String hello() {
                    return "Hello World";
                }

                // 8. 返回流式数据
                @Get("/stream")
                @Produces(MediaType.APPLICATION_JSON_STREAM)
                public Publisher<Product> streamProducts() {
                    return productService.streamAll();
                }
            }

            // 响应示例
            // GET /api/responses/user/123
            // 200 OK
            // Content-Type: application/json
            // {"id": 123, "username": "john"}

            // POST /api/responses/users
            // 201 Created
            // X-User-Id: 456
            // Location: /api/users/456
            // {"id": 456, "username": "jane"}

            // GET /api/responses/optional/999 (不存在)
            // 404 Not Found
            ---
    b.状态码控制
        a.@Status注解
            通过@Status注解指定成功响应的HTTP状态码。
        b.状态码示例
            ---
            @Controller("/api/resources")
            public class ResourceController {
                // 201 Created
                @Post
                @Status(HttpStatus.CREATED)
                public Resource createResource(@Body Resource resource) {
                    return resourceService.create(resource);
                }

                // 202 Accepted(异步处理)
                @Post("/async")
                @Status(HttpStatus.ACCEPTED)
                public TaskResponse submitTask(@Body Task task) {
                    String taskId = taskService.submitAsync(task);
                    return new TaskResponse(taskId, "任务已提交");
                }

                // 204 No Content
                @Put("/{id}")
                @Status(HttpStatus.NO_CONTENT)
                public void updateResource(Long id, @Body Resource resource) {
                    resourceService.update(id, resource);
                }

                // 206 Partial Content
                @Get("/{id}/partial")
                @Status(HttpStatus.PARTIAL_CONTENT)
                public PartialData getPartialData(
                    Long id,
                    @Header("Range") String range) {

                    return resourceService.getPartial(id, range);
                }

                // 动态状态码
                @Get("/{id}")
                public HttpResponse<Resource> getResource(Long id) {
                    Optional<Resource> resource = resourceService.findById(id);

                    if (resource.isPresent()) {
                        return HttpResponse.ok(resource.get());  // 200
                    } else {
                        return HttpResponse.notFound();  // 404
                    }
                }

                // 条件化状态码
                @Delete("/{id}")
                public HttpResponse<?> deleteResource(Long id) {
                    boolean deleted = resourceService.delete(id);

                    if (deleted) {
                        return HttpResponse.noContent();  // 204
                    } else {
                        return HttpResponse.notFound();  // 404
                    }
                }
            }
            ---

06.异常处理
    a.@Error注解
        a.异常映射
            通过@Error注解捕获特定异常,返回自定义错误响应。
        b.异常处理示例
            ---
            import io.micronaut.http.annotation.Error;
            import io.micronaut.http.HttpRequest;
            import io.micronaut.http.HttpResponse;

            @Controller("/api/products")
            public class ProductController {
                private final ProductService productService;

                public ProductController(ProductService productService) {
                    this.productService = productService;
                }

                @Get("/{id}")
                public Product getProduct(Long id) {
                    // 可能抛出ProductNotFoundException
                    return productService.findById(id);
                }

                // 处理特定异常
                @Error(exception = ProductNotFoundException.class)
                public HttpResponse<ErrorResponse> handleNotFound(
                    HttpRequest request,
                    ProductNotFoundException ex) {

                    System.out.println("产品未找到: " + ex.getMessage());

                    ErrorResponse error = new ErrorResponse(
                        "PRODUCT_NOT_FOUND",
                        ex.getMessage(),
                        request.getPath()
                    );

                    return HttpResponse.notFound(error);
                }

                // 处理验证异常
                @Error(exception = ValidationException.class)
                public HttpResponse<ErrorResponse> handleValidation(
                    HttpRequest request,
                    ValidationException ex) {

                    System.out.println("验证失败: " + ex.getErrors());

                    ErrorResponse error = new ErrorResponse(
                        "VALIDATION_ERROR",
                        "请求数据验证失败",
                        ex.getErrors()
                    );

                    return HttpResponse.badRequest(error);
                }

                // 处理所有异常
                @Error
                public HttpResponse<ErrorResponse> handleGenericError(
                    HttpRequest request,
                    Throwable ex) {

                    System.err.println("未处理的异常: " + ex.getMessage());
                    ex.printStackTrace();

                    ErrorResponse error = new ErrorResponse(
                        "INTERNAL_ERROR",
                        "服务器内部错误",
                        request.getPath()
                    );

                    return HttpResponse.serverError(error);
                }
            }

            // 错误响应类
            public class ErrorResponse {
                private String code;
                private String message;
                private String path;
                private Object details;
                private long timestamp;

                public ErrorResponse(String code, String message, String path) {
                    this.code = code;
                    this.message = message;
                    this.path = path;
                    this.timestamp = System.currentTimeMillis();
                }

                public ErrorResponse(String code, String message, Object details) {
                    this.code = code;
                    this.message = message;
                    this.details = details;
                    this.timestamp = System.currentTimeMillis();
                }

                // Getter省略
            }

            // 错误响应示例
            // GET /api/products/999 (不存在)
            // 404 Not Found
            // {
            //   "code": "PRODUCT_NOT_FOUND",
            //   "message": "产品不存在: 999",
            //   "path": "/api/products/999",
            //   "timestamp": 1704096000000
            // }
            ---
    b.全局异常处理
        a.@ServerFilter异常处理
            通过全局异常处理器统一处理所有控制器的异常。
        b.全局处理器示例
            ---
            import io.micronaut.http.annotation.ServerFilter;
            import io.micronaut.http.filter.HttpServerFilter;
            import io.micronaut.http.filter.ServerFilterChain;
            import org.reactivestreams.Publisher;

            @Singleton
            public class GlobalExceptionHandler implements ExceptionHandler<Exception, HttpResponse<?>> {
                private static final Logger log =
                    LoggerFactory.getLogger(GlobalExceptionHandler.class);

                @Override
                public HttpResponse<?> handle(HttpRequest request, Exception exception) {
                    log.error("全局异常处理", exception);

                    // 业务异常
                    if (exception instanceof BusinessException) {
                        BusinessException bex = (BusinessException) exception;
                        return HttpResponse.badRequest(new ErrorResponse(
                            bex.getCode(),
                            bex.getMessage()
                        ));
                    }

                    // 认证异常
                    if (exception instanceof UnauthorizedException) {
                        return HttpResponse.unauthorized();
                    }

                    // 权限异常
                    if (exception instanceof ForbiddenException) {
                        return HttpResponse.forbidden();
                    }

                    // 资源未找到
                    if (exception instanceof ResourceNotFoundException) {
                        return HttpResponse.notFound(new ErrorResponse(
                            "NOT_FOUND",
                            exception.getMessage()
                        ));
                    }

                    // 其他异常
                    return HttpResponse.serverError(new ErrorResponse(
                        "INTERNAL_ERROR",
                        "服务器内部错误"
                    ));
                }
            }
            ---

4.2 路由与请求映射

01.路由配置
    a.路由规则
        a.路径匹配机制
            Micronaut使用URI模板语法定义路由规则,支持静态路径、路径变量、可选路径段和正则表达式约束,实现灵活的URL映射。路径匹配采用前缀匹配和精确匹配相结合的方式,确保请求正确路由到对应的处理器方法。
        b.路由规则示例
            ---
            import io.micronaut.http.annotation.*;

            @Controller("/api")
            public class RouteController {
                // 静态路径 - 精确匹配
                @Get("/products")
                public List<Product> getAllProducts() {
                    System.out.println("匹配: /api/products");
                    return productService.findAll();
                }

                // 路径变量 - 动态匹配
                @Get("/products/{id}")
                public Product getProduct(Long id) {
                    System.out.println("匹配: /api/products/" + id);
                    return productService.findById(id);
                }

                // 多级路径变量
                @Get("/categories/{category}/products/{id}")
                public Product getProductByCategory(String category, Long id) {
                    System.out.println("匹配: /api/categories/" + category + "/products/" + id);
                    return productService.findByCategoryAndId(category, id);
                }

                // 可选路径段 - {/variable} 语法
                @Get("/search{/keyword}")
                public List<Product> search(@Nullable String keyword) {
                    if (keyword == null) {
                        System.out.println("匹配: /api/search (无关键词)");
                        return productService.findAll();
                    }
                    System.out.println("匹配: /api/search/" + keyword);
                    return productService.search(keyword);
                }

                // 正则表达式约束 - 只匹配数字ID
                @Get("/orders/{orderId:[0-9]+}")
                public Order getOrder(Long orderId) {
                    System.out.println("匹配: /api/orders/" + orderId + " (数字ID)");
                    return orderService.findById(orderId);
                }

                // 正则表达式约束 - 匹配用户名格式
                @Get("/users/{username:[a-zA-Z0-9_]{3,20}}")
                public User getUserByUsername(String username) {
                    System.out.println("匹配: /api/users/" + username + " (用户名格式)");
                    return userService.findByUsername(username);
                }
            }

            // URL匹配示例
            // GET /api/products              → getAllProducts()
            // GET /api/products/123          → getProduct(123)
            // GET /api/categories/electronics/products/456 → getProductByCategory("electronics", 456)
            // GET /api/search                → search(null)
            // GET /api/search/手机            → search("手机")
            // GET /api/orders/789            → getOrder(789) ✓
            // GET /api/orders/abc            → 404 (不匹配正则) ✗
            // GET /api/users/john_doe        → getUserByUsername("john_doe") ✓
            // GET /api/users/ab              → 404 (用户名太短) ✗
            ---
    b.路由优先级
        a.匹配优先级规则
            当多个路由规则匹配同一请求时,Micronaut按照路径具体程度、HTTP方法、参数数量等因素确定优先级。优先级从高到低依次为:静态路径>带约束的路径变量>普通路径变量>通配符,具体匹配>泛型匹配,确保最精确的路由被选中执行。
        b.优先级示例
            ---
            @Controller("/api")
            public class PriorityController {
                // 优先级1: 静态路径 (最高优先级)
                @Get("/products/featured")
                public List<Product> getFeaturedProducts() {
                    System.out.println("路由1: 静态路径 /products/featured");
                    return productService.findFeatured();
                }

                // 优先级2: 带正则约束的路径变量
                @Get("/products/{id:[0-9]+}")
                public Product getProductById(Long id) {
                    System.out.println("路由2: 数字ID /products/" + id);
                    return productService.findById(id);
                }

                // 优先级3: 普通路径变量 (最低优先级)
                @Get("/products/{slug}")
                public Product getProductBySlug(String slug) {
                    System.out.println("路由3: 文字标识符 /products/" + slug);
                    return productService.findBySlug(slug);
                }

                // HTTP方法优先级: 具体方法>泛型方法
                @Get("/users/{id}")
                public User getUser(Long id) {
                    System.out.println("GET /users/" + id);
                    return userService.findById(id);
                }

                @Post("/users/{id}")
                public User updateUser(Long id, @Body User user) {
                    System.out.println("POST /users/" + id);
                    return userService.update(id, user);
                }

                // 参数数量影响优先级
                @Get("/search")
                public List<Product> searchAll() {
                    System.out.println("搜索: 无参数");
                    return productService.findAll();
                }

                @Get("/search")
                public List<Product> searchWithKeyword(
                    @QueryValue String keyword) {
                    System.out.println("搜索: 关键词=" + keyword);
                    return productService.search(keyword);
                }
            }

            // 路由选择示例
            // GET /api/products/featured    → 路由1 (静态路径优先)
            // GET /api/products/123         → 路由2 (数字匹配正则约束)
            // GET /api/products/gaming-mouse → 路由3 (字符串作为slug)
            // GET /api/users/456            → getUser(456)
            // POST /api/users/456           → updateUser(456, user)
            // GET /api/search               → searchAll() (无参数版本)
            // GET /api/search?keyword=手机   → searchWithKeyword("手机")
            ---

02.URI模板高级特性
    a.多路径映射
        a.路径别名
            单个方法可以映射多个路径,通过在注解中使用数组定义多个路径字符串,实现路径别名和版本兼容。这对于API版本演进、保持向后兼容性、提供简写路径等场景非常有用。
        b.多路��示例
            ---
            @Controller("/api")
            public class MultiPathController {
                // 多个路径映射到同一方法
                @Get({"/products", "/items"})
                public List<Product> getProducts() {
                    System.out.println("访问产品列表 (支持两个路径)");
                    return productService.findAll();
                }

                // API版本兼容
                @Get({"/v1/users/{id}", "/v2/users/{id}"})
                public User getUser(Long id) {
                    System.out.println("获取用户 (v1和v2都支持)");
                    return userService.findById(id);
                }

                // 简写路径和完整路径
                @Post({"/register", "/users/register"})
                public User register(@Body RegistrationRequest request) {
                    System.out.println("用户注册 (支持简写和完整路径)");
                    return userService.register(request);
                }

                // 国际化路径
                @Get({"/profile", "/zh/个人资料", "/en/profile"})
                public UserProfile getProfile(
                    @Header("Authorization") String token) {
                    System.out.println("获取个人资料 (支持多语言路径)");
                    Long userId = authService.getUserIdFromToken(token);
                    return userService.getProfile(userId);
                }

                // 移动端和Web端路径统一
                @Post({"/mobile/orders", "/web/orders", "/orders"})
                public Order createOrder(@Body OrderRequest request) {
                    System.out.println("创建订单 (移动/Web/通用路径)");
                    return orderService.create(request);
                }
            }

            // 路由映射示例
            // GET /api/products    → getProducts() ✓
            // GET /api/items       → getProducts() ✓
            // GET /api/v1/users/1  → getUser(1) ✓
            // GET /api/v2/users/1  → getUser(1) ✓
            // POST /api/register   → register(...) ✓
            // POST /api/users/register → register(...) ✓
            ---
    b.路径前缀与组合
        a.控制器级前缀
            @Controller注解的value参数定义所有方法的公共路径前缀,方法级注解的路径与控制器级路径拼接形成完整请求路径,实现路径的层次化管理和逻辑分组。
        b.路径组合示例
            ---
            // 控制器级前缀: /api/v1
            @Controller("/api/v1")
            public class UserManagementController {
                // 完整路径: /api/v1/users
                @Get("/users")
                public List<User> listUsers() {
                    System.out.println("GET /api/v1/users");
                    return userService.findAll();
                }

                // 完整路径: /api/v1/users/{id}
                @Get("/users/{id}")
                public User getUser(Long id) {
                    System.out.println("GET /api/v1/users/" + id);
                    return userService.findById(id);
                }

                // 完整路径: /api/v1/users
                @Post("/users")
                public User createUser(@Body User user) {
                    System.out.println("POST /api/v1/users");
                    return userService.create(user);
                }

                // 空路径 - 完整路径: /api/v1
                @Get
                public ApiInfo getApiInfo() {
                    System.out.println("GET /api/v1 (API信息)");
                    return new ApiInfo("User API", "v1");
                }
            }

            // 嵌套资源路径
            @Controller("/api/users/{userId}")
            public class UserOrderController {
                // 完整路径: /api/users/{userId}/orders
                @Get("/orders")
                public List<Order> getUserOrders(Long userId) {
                    System.out.println("GET /api/users/" + userId + "/orders");
                    return orderService.findByUserId(userId);
                }

                // 完整路径: /api/users/{userId}/orders/{orderId}
                @Get("/orders/{orderId}")
                public Order getUserOrder(Long userId, Long orderId) {
                    System.out.println("GET /api/users/" + userId + "/orders/" + orderId);
                    return orderService.findByUserAndOrder(userId, orderId);
                }

                // 完整路径: /api/users/{userId}/orders
                @Post("/orders")
                public Order createUserOrder(
                    Long userId,
                    @Body OrderRequest request) {
                    System.out.println("POST /api/users/" + userId + "/orders");
                    request.setUserId(userId);
                    return orderService.create(request);
                }
            }

            // 路由示例
            // GET  /api/v1                     → getApiInfo()
            // GET  /api/v1/users               → listUsers()
            // GET  /api/v1/users/123           → getUser(123)
            // POST /api/v1/users               → createUser(user)
            // GET  /api/users/123/orders       → getUserOrders(123)
            // GET  /api/users/123/orders/456   → getUserOrder(123, 456)
            // POST /api/users/123/orders       → createUserOrder(123, request)
            ---

03.HTTP方法路由
    a.标准HTTP方法
        a.RESTful方法映射
            Micronaut提供@Get、@Post、@Put、@Delete、@Patch、@Head、@Options、@Trace等注解对应HTTP标准方法,实现完整的RESTful API支持。每个方法有明确的语义:GET查询资源、POST创建资源、PUT完整更新、PATCH部分更新、DELETE删除资源。
        b.方法路由示例
            ---
            @Controller("/api/articles")
            public class ArticleController {
                private final ArticleService articleService;

                public ArticleController(ArticleService articleService) {
                    this.articleService = articleService;
                }

                // GET: 查询单个资源
                @Get("/{id}")
                public Article getArticle(Long id) {
                    System.out.println("GET /api/articles/" + id);
                    return articleService.findById(id);
                }

                // GET: 查询资源列表
                @Get
                public List<Article> listArticles(
                    @QueryValue(defaultValue = "0") int page,
                    @QueryValue(defaultValue = "10") int size) {
                    System.out.println("GET /api/articles?page=" + page + "&size=" + size);
                    return articleService.findAll(page, size);
                }

                // POST: 创建新资源
                @Post
                @Status(HttpStatus.CREATED)
                public Article createArticle(@Body ArticleRequest request) {
                    System.out.println("POST /api/articles - 标题: " + request.getTitle());
                    return articleService.create(request);
                }

                // PUT: 完整更新资源 (替换所有字段)
                @Put("/{id}")
                public Article updateArticle(Long id, @Body ArticleRequest request) {
                    System.out.println("PUT /api/articles/" + id + " - 完整更新");
                    return articleService.update(id, request);
                }

                // PATCH: 部分更新资源 (只更新提供的字段)
                @Patch("/{id}")
                public Article patchArticle(Long id, @Body Map<String, Object> updates) {
                    System.out.println("PATCH /api/articles/" + id + " - 部分更新: " + updates.keySet());
                    return articleService.partialUpdate(id, updates);
                }

                // DELETE: 删除资源
                @Delete("/{id}")
                @Status(HttpStatus.NO_CONTENT)
                public void deleteArticle(Long id) {
                    System.out.println("DELETE /api/articles/" + id);
                    articleService.delete(id);
                }

                // HEAD: 检查资源是否存在 (不返回响应体)
                @Head("/{id}")
                public HttpResponse<?> checkArticleExists(Long id) {
                    System.out.println("HEAD /api/articles/" + id);
                    boolean exists = articleService.exists(id);
                    return exists ? HttpResponse.ok() : HttpResponse.notFound();
                }

                // OPTIONS: 返回支持的HTTP方法
                @Options("/{id}")
                public HttpResponse<?> getOptions() {
                    System.out.println("OPTIONS /api/articles/{id}");
                    return HttpResponse.ok()
                        .header("Allow", "GET, PUT, PATCH, DELETE, HEAD, OPTIONS");
                }
            }

            // RESTful API示例
            // GET    /api/articles           → 列表查询
            // GET    /api/articles/123       → 查询单个文章
            // POST   /api/articles           → 创建文章 (201 Created)
            // PUT    /api/articles/123       → 完整更新文章
            // PATCH  /api/articles/123       → 部分更新文章
            // DELETE /api/articles/123       → 删除文章 (204 No Content)
            // HEAD   /api/articles/123       → 检查文章是否存在
            // OPTIONS /api/articles/123      → 获取支持的HTTP方法
            ---
    b.自定义HTTP方法
        a.扩展HTTP方法
            通过@CustomHttpMethod注解支持自定义HTTP方法,用于实现WebDAV协议、缓存清除、资源锁定等扩展功能,突破标准HTTP方法的限制。
        b.自定义方法示例
            ---
            import io.micronaut.http.annotation.CustomHttpMethod;

            @Controller("/api/cache")
            public class CacheManagementController {
                private final CacheService cacheService;

                public CacheManagementController(CacheService cacheService) {
                    this.cacheService = cacheService;
                }

                // 自定义PURGE方法 - 清除缓存
                @CustomHttpMethod(method = "PURGE")
                @Status(HttpStatus.NO_CONTENT)
                public void purgeCache(
                    @QueryValue String key,
                    @QueryValue(defaultValue = "false") boolean pattern) {
                    if (pattern) {
                        System.out.println("PURGE /api/cache?key=" + key + "&pattern=true (模式匹配)");
                        cacheService.invalidatePattern(key);
                    } else {
                        System.out.println("PURGE /api/cache?key=" + key + " (精确匹配)");
                        cacheService.invalidate(key);
                    }
                }

                // 自定义LOCK方法 - 锁定资源
                @CustomHttpMethod(method = "LOCK", value = "/{resource}")
                public LockResponse lockResource(
                    String resource,
                    @Body LockRequest request) {
                    System.out.println("LOCK /api/cache/" + resource +
                                     " - 超时: " + request.getTimeout() + "秒");
                    String lockToken = cacheService.acquireLock(
                        resource,
                        request.getTimeout()
                    );
                    return new LockResponse(lockToken, resource, request.getTimeout());
                }

                // 自定义UNLOCK方法 - 解锁资源
                @CustomHttpMethod(method = "UNLOCK", value = "/{resource}")
                @Status(HttpStatus.NO_CONTENT)
                public void unlockResource(
                    String resource,
                    @Header("Lock-Token") String lockToken) {
                    System.out.println("UNLOCK /api/cache/" + resource +
                                     " - Token: " + lockToken);
                    boolean released = cacheService.releaseLock(resource, lockToken);
                    if (!released) {
                        throw new IllegalStateException("无效的锁令牌");
                    }
                }

                // 自定义REFRESH方法 - 刷新缓存
                @CustomHttpMethod(method = "REFRESH", value = "/{key}")
                public RefreshResponse refreshCache(String key) {
                    System.out.println("REFRESH /api/cache/" + key);
                    Object value = cacheService.refresh(key);
                    return new RefreshResponse(key, value != null,
                                              value != null ? "刷新成功" : "缓存未命中");
                }
            }

            // 锁请求对象
            public class LockRequest {
                private int timeout = 30; // 默认30秒
                private String owner;

                // Getter和Setter
                public int getTimeout() { return timeout; }
                public void setTimeout(int timeout) { this.timeout = timeout; }
                public String getOwner() { return owner; }
                public void setOwner(String owner) { this.owner = owner; }
            }

            // 锁响应对象
            public class LockResponse {
                private String token;
                private String resource;
                private int timeout;
                private long expiresAt;

                public LockResponse(String token, String resource, int timeout) {
                    this.token = token;
                    this.resource = resource;
                    this.timeout = timeout;
                    this.expiresAt = System.currentTimeMillis() + timeout * 1000;
                }

                // Getter省略
            }

            // 刷新响应对象
            public class RefreshResponse {
                private String key;
                private boolean success;
                private String message;

                public RefreshResponse(String key, boolean success, String message) {
                    this.key = key;
                    this.success = success;
                    this.message = message;
                }

                // Getter省略
            }

            // 使用示例
            // PURGE /api/cache?key=user:123
            // PURGE /api/cache?key=user:*&pattern=true
            // LOCK /api/cache/report-2024 (Body: {"timeout": 60, "owner": "job-123"})
            // UNLOCK /api/cache/report-2024 (Header: Lock-Token: abc123def456)
            // REFRESH /api/cache/statistics
            ---

04.路由版本控制
    a.URI路径版本
        a.版本路径设计
            在URI路径中包含版本号,如/api/v1/users、/api/v2/users,通过不同的控制器类或方法处理不同版本的API请求,实现版本隔离和独立演进。
        b.版本路径示例
            ---
            // V1版本 - 原始用户API
            @Controller("/api/v1/users")
            public class UserControllerV1 {
                private final UserService userService;

                public UserControllerV1(UserService userService) {
                    this.userService = userService;
                }

                @Get("/{id}")
                public UserV1Response getUser(Long id) {
                    System.out.println("API v1: GET /api/v1/users/" + id);
                    User user = userService.findById(id);
                    // V1响应格式: 简单字段
                    return new UserV1Response(
                        user.getId(),
                        user.getUsername(),
                        user.getEmail()
                    );
                }

                @Post
                public UserV1Response createUser(@Body UserV1Request request) {
                    System.out.println("API v1: POST /api/v1/users");
                    User user = userService.create(request);
                    return new UserV1Response(
                        user.getId(),
                        user.getUsername(),
                        user.getEmail()
                    );
                }
            }

            // V2版本 - 增强的用户API
            @Controller("/api/v2/users")
            public class UserControllerV2 {
                private final UserService userService;

                public UserControllerV2(UserService userService) {
                    this.userService = userService;
                }

                @Get("/{id}")
                public UserV2Response getUser(
                    Long id,
                    @QueryValue(defaultValue = "false") boolean includeProfile) {
                    System.out.println("API v2: GET /api/v2/users/" + id +
                                     " - includeProfile=" + includeProfile);
                    User user = userService.findById(id);
                    // V2响应格式: 增强字段和可选信息
                    UserV2Response response = new UserV2Response(
                        user.getId(),
                        user.getUsername(),
                        user.getEmail(),
                        user.getCreatedAt(),
                        user.getStatus()
                    );
                    if (includeProfile) {
                        response.setProfile(user.getProfile());
                    }
                    return response;
                }

                @Post
                public UserV2Response createUser(@Body UserV2Request request) {
                    System.out.println("API v2: POST /api/v2/users (支持更多字段)");
                    // V2请求支持额外字段: profile, preferences
                    User user = userService.createWithProfile(request);
                    return new UserV2Response(
                        user.getId(),
                        user.getUsername(),
                        user.getEmail(),
                        user.getCreatedAt(),
                        user.getStatus()
                    );
                }

                // V2新增功能: 批量操作
                @Post("/batch")
                public BatchResponse<UserV2Response> batchCreate(
                    @Body List<UserV2Request> requests) {
                    System.out.println("API v2: POST /api/v2/users/batch - " +
                                     requests.size() + "个用户");
                    List<User> users = userService.batchCreate(requests);
                    List<UserV2Response> responses = users.stream()
                        .map(u -> new UserV2Response(
                            u.getId(), u.getUsername(), u.getEmail(),
                            u.getCreatedAt(), u.getStatus()))
                        .collect(Collectors.toList());
                    return new BatchResponse<>(responses.size(), responses);
                }
            }

            // API版本对比
            // V1: GET /api/v1/users/123 → 返回基本信息(id, username, email)
            // V2: GET /api/v2/users/123 → 返回增强信息(id, username, email, createdAt, status)
            // V2: GET /api/v2/users/123?includeProfile=true → 返回完整信息(包含profile)
            // V2: POST /api/v2/users/batch → 批量创建(V1不支持)
            ---
    b.请求头版本控制
        a.版本协商
            通过自定义请求头(如Accept-Version或X-API-Version)传递版本信息,服务端根据版本号路由到对应的处理逻辑,保持URL统一。
        b.版本头示例
            ---
            import io.micronaut.http.annotation.Header;

            @Controller("/api/products")
            public class VersionedProductController {
                private final ProductService productService;

                public VersionedProductController(ProductService productService) {
                    this.productService = productService;
                }

                // 默认版本(无版本头或版本1)
                @Get("/{id}")
                public HttpResponse<?> getProduct(
                    Long id,
                    @Header(value = "Accept-Version", defaultValue = "1") String version) {

                    System.out.println("GET /api/products/" + id + " - 版本: " + version);

                    Product product = productService.findById(id);

                    switch (version) {
                        case "1":
                            // V1: 基本产品信息
                            return HttpResponse.ok(new ProductV1Response(
                                product.getId(),
                                product.getName(),
                                product.getPrice()
                            ));

                        case "2":
                            // V2: 增加库存和描述
                            return HttpResponse.ok(new ProductV2Response(
                                product.getId(),
                                product.getName(),
                                product.getPrice(),
                                product.getStock(),
                                product.getDescription()
                            ));

                        case "3":
                            // V3: 增加评分和图片
                            return HttpResponse.ok(new ProductV3Response(
                                product.getId(),
                                product.getName(),
                                product.getPrice(),
                                product.getStock(),
                                product.getDescription(),
                                product.getRating(),
                                product.getImages()
                            ));

                        default:
                            return HttpResponse.badRequest(
                                new ErrorResponse("UNSUPPORTED_VERSION",
                                                "不支持的API版本: " + version)
                            );
                    }
                }

                // 创建产品 - 根据版本接受不同的请求格式
                @Post
                public HttpResponse<?> createProduct(
                    @Header(value = "Accept-Version", defaultValue = "1") String version,
                    @Body String body) {

                    System.out.println("POST /api/products - 版本: " + version);

                    try {
                        switch (version) {
                            case "1":
                                ProductV1Request reqV1 =
                                    objectMapper.readValue(body, ProductV1Request.class);
                                Product p1 = productService.create(reqV1);
                                return HttpResponse.created(new ProductV1Response(
                                    p1.getId(), p1.getName(), p1.getPrice()
                                ));

                            case "2":
                                ProductV2Request reqV2 =
                                    objectMapper.readValue(body, ProductV2Request.class);
                                Product p2 = productService.createWithDetails(reqV2);
                                return HttpResponse.created(new ProductV2Response(
                                    p2.getId(), p2.getName(), p2.getPrice(),
                                    p2.getStock(), p2.getDescription()
                                ));

                            case "3":
                                ProductV3Request reqV3 =
                                    objectMapper.readValue(body, ProductV3Request.class);
                                Product p3 = productService.createWithMedia(reqV3);
                                return HttpResponse.created(new ProductV3Response(
                                    p3.getId(), p3.getName(), p3.getPrice(),
                                    p3.getStock(), p3.getDescription(),
                                    p3.getRating(), p3.getImages()
                                ));

                            default:
                                return HttpResponse.badRequest(
                                    new ErrorResponse("UNSUPPORTED_VERSION",
                                                    "不支持的API版本: " + version)
                                );
                        }
                    } catch (Exception e) {
                        return HttpResponse.serverError(
                            new ErrorResponse("PARSE_ERROR", e.getMessage())
                        );
                    }
                }
            }

            // 使用示例
            // curl -H "Accept-Version: 1" http://localhost:8080/api/products/123
            // 返回: {"id": 123, "name": "商品名", "price": 99.99}

            // curl -H "Accept-Version: 2" http://localhost:8080/api/products/123
            // 返回: {"id": 123, "name": "商品名", "price": 99.99, "stock": 100, "description": "..."}

            // curl -H "Accept-Version: 3" http://localhost:8080/api/products/123
            // 返回: {"id": 123, "name": "商品名", "price": 99.99, "stock": 100,
            //       "description": "...", "rating": 4.5, "images": ["url1", "url2"]}

            // 无版本头或默认版本1
            // curl http://localhost:8080/api/products/123
            // 返回: {"id": 123, "name": "商品名", "price": 99.99}
            ---

4.3 参数绑定

01.查询参数绑定
    a.@QueryValue基础
        a.查询参数映射
            @QueryValue注解将URL查询参数绑定到方法参数,支持基本类型、包装类型、字符串、日期等多种类型的自动转换。框架会自动解析URL中?后的参数,按名称匹配到方法参数,并进行类型转换和验证。
        b.基础查询参数示例
            ---
            import io.micronaut.http.annotation.*;
            import io.micronaut.core.annotation.Nullable;

            @Controller("/api/search")
            public class SearchController {
                private final ProductService productService;

                public SearchController(ProductService productService) {
                    this.productService = productService;
                }

                // 必需查询参数
                @Get
                public List<Product> search(@QueryValue String keyword) {
                    // GET /api/search?keyword=手机
                    System.out.println("搜索关键词: " + keyword);
                    return productService.search(keyword);
                }

                // 可选查询参数 - 使用@Nullable
                @Get("/optional")
                public List<Product> searchOptional(
                    @QueryValue @Nullable String keyword,
                    @QueryValue @Nullable String category) {
                    // GET /api/search/optional?keyword=手机
                    // GET /api/search/optional?keyword=手机&category=电子
                    // GET /api/search/optional (两个参数都是null)

                    System.out.println("关键词: " + (keyword != null ? keyword : "全部"));
                    System.out.println("分类: " + (category != null ? category : "全部"));

                    if (keyword == null && category == null) {
                        return productService.findAll();
                    } else if (keyword != null && category != null) {
                        return productService.searchByKeywordAndCategory(keyword, category);
                    } else if (keyword != null) {
                        return productService.search(keyword);
                    } else {
                        return productService.findByCategory(category);
                    }
                }

                // 带默认值的查询参数
                @Get("/paginated")
                public List<Product> searchPaginated(
                    @QueryValue(defaultValue = "") String keyword,
                    @QueryValue(defaultValue = "0") int page,
                    @QueryValue(defaultValue = "20") int size,
                    @QueryValue(defaultValue = "id") String sortBy,
                    @QueryValue(defaultValue = "asc") String order) {

                    // GET /api/search/paginated?keyword=手机
                    // 使用默认值: page=0, size=20, sortBy=id, order=asc

                    System.out.println("搜索参数:");
                    System.out.println("  关键词: " + keyword);
                    System.out.println("  页码: " + page);
                    System.out.println("  每页: " + size);
                    System.out.println("  排序: " + sortBy + " " + order);

                    return productService.search(keyword, page, size, sortBy, order);
                }

                // 重命名查询参数 - 参数名与方法参数名不同
                @Get("/renamed")
                public List<Product> searchRenamed(
                    @QueryValue("q") String keyword,
                    @QueryValue("cat") @Nullable String category,
                    @QueryValue("p") int page) {

                    // GET /api/search/renamed?q=手机&cat=电子&p=1
                    System.out.println("q=" + keyword + ", cat=" + category + ", p=" + page);
                    return productService.search(keyword, category, page);
                }
            }

            // URL示例
            // GET /api/search?keyword=手机
            // GET /api/search/optional (返回全部)
            // GET /api/search/optional?keyword=手机
            // GET /api/search/paginated?keyword=手机&page=2&size=50
            // GET /api/search/renamed?q=laptop&cat=electronics&p=0
            ---
    b.复杂类型查询参数
        a.集合参数绑定
            使用List或数组接收同名的多个查询参数值,实现多选过滤、标签筛选等功能。框架自动将所有同名参数聚合为集合类型,便于处理批量条件。
        b.复杂类型示例
            ---
            import java.time.LocalDate;
            import java.time.LocalDateTime;
            import java.math.BigDecimal;
            import io.micronaut.core.convert.format.Format;

            @Controller("/api/products")
            public class ProductQueryController {
                private final ProductService productService;

                public ProductQueryController(ProductService productService) {
                    this.productService = productService;
                }

                // 多值参数 - List接收
                @Get("/filter")
                public List<Product> filterByTags(
                    @QueryValue("tag") List<String> tags,
                    @QueryValue("status") List<String> statuses) {

                    // GET /api/products/filter?tag=hot&tag=new&tag=featured&status=active&status=promoted
                    System.out.println("标签: " + tags);  // [hot, new, featured]
                    System.out.println("状态: " + statuses);  // [active, promoted]

                    return productService.filterByTagsAndStatuses(tags, statuses);
                }

                // 日期参数 - 使用@Format指定格式
                @Get("/by-date")
                public List<Product> findByDate(
                    @QueryValue @Format("yyyy-MM-dd") LocalDate startDate,
                    @QueryValue @Format("yyyy-MM-dd") LocalDate endDate) {

                    // GET /api/products/by-date?startDate=2024-01-01&endDate=2024-12-31
                    System.out.println("日期范围: " + startDate + " 至 " + endDate);
                    return productService.findByDateRange(startDate, endDate);
                }

                // 日期时间参数 - ISO 8601格式
                @Get("/by-datetime")
                public List<Product> findByDateTime(
                    @QueryValue @Format("yyyy-MM-dd'T'HH:mm:ss") LocalDateTime start,
                    @QueryValue @Format("yyyy-MM-dd'T'HH:mm:ss") LocalDateTime end) {

                    // GET /api/products/by-datetime?start=2024-01-01T00:00:00&end=2024-12-31T23:59:59
                    System.out.println("时间范围: " + start + " 至 " + end);
                    return productService.findByDateTimeRange(start, end);
                }

                // 数值范围参数 - BigDecimal精确计算
                @Get("/by-price")
                public List<Product> findByPriceRange(
                    @QueryValue @Nullable BigDecimal minPrice,
                    @QueryValue @Nullable BigDecimal maxPrice) {

                    // GET /api/products/by-price?minPrice=100.00&maxPrice=999.99
                    System.out.println("价格范围: " + minPrice + " - " + maxPrice);

                    if (minPrice != null && maxPrice != null) {
                        return productService.findByPriceRange(minPrice, maxPrice);
                    } else if (minPrice != null) {
                        return productService.findByMinPrice(minPrice);
                    } else if (maxPrice != null) {
                        return productService.findByMaxPrice(maxPrice);
                    } else {
                        return productService.findAll();
                    }
                }

                // 枚举参数 - 自动转换
                @Get("/by-status")
                public List<Product> findByStatus(
                    @QueryValue ProductStatus status,
                    @QueryValue(defaultValue = "false") boolean includeDeleted) {

                    // GET /api/products/by-status?status=ACTIVE&includeDeleted=true
                    System.out.println("状态: " + status);  // ACTIVE枚举值
                    System.out.println("包含已删除: " + includeDeleted);

                    return productService.findByStatus(status, includeDeleted);
                }

                // Boolean参数 - 多种格式支持
                @Get("/flags")
                public List<Product> findWithFlags(
                    @QueryValue(defaultValue = "false") boolean inStock,
                    @QueryValue(defaultValue = "false") boolean onSale,
                    @QueryValue(defaultValue = "true") boolean published) {

                    // GET /api/products/flags?inStock=true&onSale=1&published=yes
                    // 支持: true/false, 1/0, yes/no, on/off
                    System.out.println("有货: " + inStock);
                    System.out.println("促销: " + onSale);
                    System.out.println("已发布: " + published);

                    return productService.findWithFlags(inStock, onSale, published);
                }

                // 高级搜索 - 组合多种类型
                @Get("/advanced-search")
                public List<Product> advancedSearch(
                    @QueryValue @Nullable String keyword,
                    @QueryValue("category") @Nullable List<String> categories,
                    @QueryValue @Nullable BigDecimal minPrice,
                    @QueryValue @Nullable BigDecimal maxPrice,
                    @QueryValue @Format("yyyy-MM-dd") @Nullable LocalDate startDate,
                    @QueryValue @Format("yyyy-MM-dd") @Nullable LocalDate endDate,
                    @QueryValue("tag") @Nullable List<String> tags,
                    @QueryValue(defaultValue = "ACTIVE") ProductStatus status,
                    @QueryValue(defaultValue = "0") int page,
                    @QueryValue(defaultValue = "20") int size) {

                    System.out.println("=== 高级搜索参数 ===");
                    System.out.println("关键词: " + keyword);
                    System.out.println("分类: " + categories);
                    System.out.println("价格区间: " + minPrice + " - " + maxPrice);
                    System.out.println("日期区间: " + startDate + " - " + endDate);
                    System.out.println("标签: " + tags);
                    System.out.println("状态: " + status);
                    System.out.println("分页: page=" + page + ", size=" + size);

                    SearchCriteria criteria = new SearchCriteria();
                    criteria.setKeyword(keyword);
                    criteria.setCategories(categories);
                    criteria.setMinPrice(minPrice);
                    criteria.setMaxPrice(maxPrice);
                    criteria.setStartDate(startDate);
                    criteria.setEndDate(endDate);
                    criteria.setTags(tags);
                    criteria.setStatus(status);

                    return productService.advancedSearch(criteria, page, size);
                }
            }

            // 枚举定义
            public enum ProductStatus {
                DRAFT,      // 草稿
                ACTIVE,     // 激活
                INACTIVE,   // 未激活
                DELETED     // 已删除
            }

            // URL示例
            // GET /api/products/filter?tag=hot&tag=new&status=active&status=promoted
            // GET /api/products/by-date?startDate=2024-01-01&endDate=2024-12-31
            // GET /api/products/by-price?minPrice=99.99&maxPrice=999.99
            // GET /api/products/by-status?status=ACTIVE&includeDeleted=false
            // GET /api/products/advanced-search?keyword=手机&category=电子&category=数码&minPrice=1000&tag=5G&tag=旗舰
            ---

02.路径参数绑定
    a.路径变量提取
        a.路径参数映射
            路径中{}定义的变量自动绑定到同名方法参数,框架负责类型转换和验证。支持基本类型、包装类型、字符串、UUID等类型,转换失败时返回400 Bad Request错误。
        b.路径参数示例
            ---
            import java.util.UUID;

            @Controller("/api")
            public class PathVariableController {
                private final ResourceService resourceService;

                public PathVariableController(ResourceService resourceService) {
                    this.resourceService = resourceService;
                }

                // Long类型路径参数
                @Get("/users/{id}")
                public User getUser(Long id) {
                    // GET /api/users/123
                    System.out.println("用户ID: " + id);
                    return resourceService.findUserById(id);
                }

                // String类型路径参数
                @Get("/users/username/{username}")
                public User getUserByUsername(String username) {
                    // GET /api/users/username/john_doe
                    System.out.println("用户名: " + username);
                    return resourceService.findUserByUsername(username);
                }

                // UUID类型路径参数
                @Get("/orders/{orderId}")
                public Order getOrder(UUID orderId) {
                    // GET /api/orders/550e8400-e29b-41d4-a716-446655440000
                    System.out.println("订单UUID: " + orderId);
                    return resourceService.findOrderByUUID(orderId);
                }

                // 多个路径参数
                @Get("/users/{userId}/posts/{postId}")
                public Post getUserPost(Long userId, Long postId) {
                    // GET /api/users/123/posts/456
                    System.out.println("用户ID: " + userId + ", 文章ID: " + postId);
                    return resourceService.findPostByUserAndId(userId, postId);
                }

                // 路径参数 + 查询参数组合
                @Get("/categories/{category}/products/{productId}")
                public Product getProduct(
                    String category,
                    Long productId,
                    @QueryValue(defaultValue = "false") boolean includeReviews) {

                    // GET /api/categories/electronics/products/789?includeReviews=true
                    System.out.println("分类: " + category);
                    System.out.println("产品ID: " + productId);
                    System.out.println("包含评论: " + includeReviews);

                    Product product = resourceService.findProduct(category, productId);
                    if (includeReviews) {
                        product.setReviews(resourceService.getProductReviews(productId));
                    }
                    return product;
                }

                // 正则表达式约束的路径参数
                @Get("/posts/{slug:[a-z0-9-]+}")
                public Post getPostBySlug(String slug) {
                    // GET /api/posts/my-first-blog-post
                    // 只匹配小写字母、数字、连字符
                    System.out.println("文章标识: " + slug);
                    return resourceService.findPostBySlug(slug);
                }

                // 日期格式路径参数
                @Get("/reports/{date}")
                public Report getReport(
                    @Format("yyyy-MM-dd") LocalDate date) {

                    // GET /api/reports/2024-01-15
                    System.out.println("报表日期: " + date);
                    return resourceService.generateReport(date);
                }

                // 可选路径段
                @Get("/search{/keyword}")
                public List<Article> search(@Nullable String keyword) {
                    // GET /api/search → keyword=null
                    // GET /api/search/java → keyword="java"

                    if (keyword == null) {
                        System.out.println("搜索: 全部文章");
                        return resourceService.findAllArticles();
                    } else {
                        System.out.println("搜索关键词: " + keyword);
                        return resourceService.searchArticles(keyword);
                    }
                }
            }

            // URL示例
            // GET /api/users/123
            // GET /api/users/username/alice
            // GET /api/orders/550e8400-e29b-41d4-a716-446655440000
            // GET /api/users/100/posts/500
            // GET /api/categories/books/products/999?includeReviews=true
            // GET /api/posts/hello-world
            // GET /api/reports/2024-12-25
            // GET /api/search
            // GET /api/search/spring-boot
            ---
    b.路径参数验证
        a.类型转换与约束
            路径参数自动进行类型转换,转换失败返回400错误。可以使用正则表达式约束路径格式,在路由层面实现输入验证,提前拦截非法请求,减轻业务层压力。
        b.参数验证示例
            ---
            import jakarta.validation.constraints.*;

            @Controller("/api/validated")
            public class ValidatedPathController {
                private final ValidationService validationService;

                public ValidatedPathController(ValidationService validationService) {
                    this.validationService = validationService;
                }

                // 正则约束 - 只接受数字ID
                @Get("/users/{id:[0-9]+}")
                public User getUserById(Long id) {
                    // GET /api/validated/users/123 ✓
                    // GET /api/validated/users/abc → 404 Not Found
                    System.out.println("数字ID: " + id);
                    return validationService.findUser(id);
                }

                // 正则约束 - 用户名格式
                @Get("/users/{username:[a-zA-Z0-9_]{3,20}}")
                public User getUserByUsername(String username) {
                    // 用户名: 3-20个字符,只能包含字母、数字、下划线
                    // GET /api/validated/users/john_doe ✓
                    // GET /api/validated/users/ab → 404 (太短)
                    // GET /api/validated/users/user@123 → 404 (包含非法字符)
                    System.out.println("合法用户名: " + username);
                    return validationService.findUserByUsername(username);
                }

                // 正则约束 - 邮箱格式
                @Get("/verify/{email:.+@.+\\..+}")
                public VerificationResult verifyEmail(String email) {
                    // GET /api/validated/verify/[email protected] ✓
                    // GET /api/validated/verify/invalid-email → 404
                    System.out.println("邮箱: " + email);
                    return validationService.verifyEmail(email);
                }

                // 正则约束 - 日期格式 YYYY-MM-DD
                @Get("/orders/{date:\\d{4}-\\d{2}-\\d{2}}")
                public List<Order> getOrdersByDate(
                    @Format("yyyy-MM-dd") LocalDate date) {

                    // GET /api/validated/orders/2024-01-15 ✓
                    // GET /api/validated/orders/2024-1-5 → 404 (格式不对)
                    System.out.println("订单日期: " + date);
                    return validationService.findOrdersByDate(date);
                }

                // 正则约束 - 手机号格式
                @Get("/sms/{phone:1[3-9]\\d{9}}")
                public SmsResult sendSms(String phone) {
                    // 中国手机号: 1开头,第二位3-9,共11位
                    // GET /api/validated/sms/13812345678 ✓
                    // GET /api/validated/sms/12812345678 → 404 (第二位不对)
                    // GET /api/validated/sms/138123456 → 404 (位数不够)
                    System.out.println("手机号: " + phone);
                    return validationService.sendSms(phone);
                }

                // 正则约束 - 产品代码格式
                @Get("/products/{code:[A-Z]{2}\\d{6}}")
                public Product getProductByCode(String code) {
                    // 产品代码: 2个大写字母 + 6个数字
                    // GET /api/validated/products/AB123456 ✓
                    // GET /api/validated/products/ab123456 → 404 (小写)
                    // GET /api/validated/products/ABC12345 → 404 (格式不对)
                    System.out.println("产品代码: " + code);
                    return validationService.findProductByCode(code);
                }

                // 多路径参数组合验证
                @Get("/transactions/{year:\\d{4}}/{month:0[1-9]|1[0-2]}/{id:[0-9]+}")
                public Transaction getTransaction(int year, int month, Long id) {
                    // year: 4位数字
                    // month: 01-12
                    // id: 纯数字
                    // GET /api/validated/transactions/2024/03/12345 ✓
                    // GET /api/validated/transactions/2024/13/12345 → 404 (月份超范围)
                    System.out.println("交易: " + year + "年" + month + "月, ID=" + id);
                    return validationService.findTransaction(year, month, id);
                }
            }

            // 路由匹配示例
            // ✓ GET /api/validated/users/123
            // ✗ GET /api/validated/users/abc (404 - 不是数字)
            // ✓ GET /api/validated/users/john_doe
            // ✗ GET /api/validated/users/ab (404 - 太短)
            // ✓ GET /api/validated/verify/[email protected]
            // ✗ GET /api/validated/verify/notanemail (404 - 不是邮箱格式)
            // ✓ GET /api/validated/orders/2024-01-15
            // ✗ GET /api/validated/orders/2024-1-5 (404 - 日期格式错误)
            // ✓ GET /api/validated/sms/13812345678
            // ✗ GET /api/validated/sms/12345678901 (404 - 不是合法手机号)
            ---

03.请求头绑定
    a.@Header注解
        a.请求头访问
            @Header注解绑定HTTP请求头到方法参数,用于获取认证信息、客户端元数据、自定义业务参数等。支持必需请求头和可选请求头,可以设置默认值。
        b.请求头示例
            ---
            @Controller("/api/secure")
            public class HeaderBindingController {
                private final AuthService authService;
                private final ContentService contentService;

                public HeaderBindingController(AuthService authService,
                                              ContentService contentService) {
                    this.authService = authService;
                    this.contentService = contentService;
                }

                // 必需请求头 - Authorization
                @Get("/profile")
                public UserProfile getProfile(@Header String authorization) {
                    // curl -H "Authorization: Bearer eyJhbGc..." http://localhost:8080/api/secure/profile
                    System.out.println("Authorization: " + authorization);

                    // 解析Bearer Token
                    String token = authorization.replace("Bearer ", "");
                    Long userId = authService.getUserIdFromToken(token);

                    return contentService.getUserProfile(userId);
                }

                // 可选请求头 - Accept-Language
                @Get("/content")
                public Content getContent(
                    @Header("Accept-Language") @Nullable String language,
                    @Header("User-Agent") @Nullable String userAgent) {

                    // curl -H "Accept-Language: zh-CN" -H "User-Agent: Mozilla/5.0..." \
                    //      http://localhost:8080/api/secure/content

                    String lang = language != null ? language : "en";
                    System.out.println("语言: " + lang);
                    System.out.println("客户端: " + userAgent);

                    return contentService.getLocalizedContent(lang);
                }

                // 带默认值的请求头
                @Get("/api-call")
                public ApiResponse callApi(
                    @Header("X-API-Key") String apiKey,
                    @Header(value = "X-Request-Id", defaultValue = "") String requestId,
                    @Header(value = "X-Trace-Id", defaultValue = "none") String traceId) {

                    // curl -H "X-API-Key: abc123" -H "X-Request-Id: req-001" \
                    //      http://localhost:8080/api/secure/api-call

                    System.out.println("API密钥: " + apiKey);
                    System.out.println("请求ID: " + requestId);
                    System.out.println("追踪ID: " + traceId);

                    return contentService.performApiCall(apiKey, requestId, traceId);
                }

                // 自定义业务请求头
                @Post("/upload")
                public UploadResponse upload(
                    @Body byte[] data,
                    @Header("X-File-Name") String fileName,
                    @Header("X-File-Type") String fileType,
                    @Header("X-File-Size") long fileSize,
                    @Header(value = "X-Checksum", defaultValue = "") String checksum) {

                    // curl -X POST -H "X-File-Name: document.pdf" \
                    //      -H "X-File-Type: application/pdf" \
                    //      -H "X-File-Size: 1024000" \
                    //      -H "X-Checksum: md5hash..." \
                    //      --data-binary @document.pdf \
                    //      http://localhost:8080/api/secure/upload

                    System.out.println("文件名: " + fileName);
                    System.out.println("文件类型: " + fileType);
                    System.out.println("文件大小: " + fileSize + " bytes");
                    System.out.println("校验和: " + checksum);

                    // 验证校验和
                    if (!checksum.isEmpty()) {
                        String actualChecksum = contentService.calculateChecksum(data);
                        if (!actualChecksum.equals(checksum)) {
                            throw new IllegalArgumentException("文件校验和不匹配");
                        }
                    }

                    String fileId = contentService.saveFile(fileName, fileType, data);
                    return new UploadResponse(fileId, fileName, fileSize);
                }

                // 多租户请求头
                @Get("/tenant-data")
                public TenantData getTenantData(
                    @Header("X-Tenant-Id") String tenantId,
                    @Header("X-User-Id") Long userId,
                    @Header(value = "X-Org-Id", defaultValue = "default") String orgId) {

                    // curl -H "X-Tenant-Id: tenant-123" \
                    //      -H "X-User-Id: 456" \
                    //      -H "X-Org-Id: org-789" \
                    //      http://localhost:8080/api/secure/tenant-data

                    System.out.println("租户ID: " + tenantId);
                    System.out.println("用户ID: " + userId);
                    System.out.println("组织ID: " + orgId);

                    return contentService.getTenantData(tenantId, userId, orgId);
                }

                // 访问所有请求头 - HttpHeaders对象
                @Get("/all-headers")
                public Map<String, String> getAllHeaders(HttpHeaders headers) {
                    Map<String, String> result = new LinkedHashMap<>();

                    for (String name : headers.names()) {
                        result.put(name, headers.get(name));
                    }

                    System.out.println("接收到 " + result.size() + " 个请求头");
                    for (Map.Entry<String, String> entry : result.entrySet()) {
                        System.out.println("  " + entry.getKey() + ": " + entry.getValue());
                    }

                    return result;
                }

                // 条件化处理 - 根据请求头选择处理逻辑
                @Get("/content-negotiation")
                public HttpResponse<?> getContentNegotiation(
                    @Header("Accept") String accept,
                    @Header(value = "Accept-Encoding", defaultValue = "identity") String encoding) {

                    // curl -H "Accept: application/json" http://localhost:8080/api/secure/content-negotiation
                    // curl -H "Accept: application/xml" http://localhost:8080/api/secure/content-negotiation

                    System.out.println("Accept: " + accept);
                    System.out.println("Accept-Encoding: " + encoding);

                    Object data = contentService.getData();

                    if (accept.contains("application/json")) {
                        return HttpResponse.ok(data)
                            .contentType(MediaType.APPLICATION_JSON);
                    } else if (accept.contains("application/xml")) {
                        String xml = contentService.toXml(data);
                        return HttpResponse.ok(xml)
                            .contentType(MediaType.APPLICATION_XML);
                    } else if (accept.contains("text/plain")) {
                        String text = data.toString();
                        return HttpResponse.ok(text)
                            .contentType(MediaType.TEXT_PLAIN);
                    } else {
                        return HttpResponse.notAcceptable();
                    }
                }
            }

            // curl示例
            // curl -H "Authorization: Bearer token123" http://localhost:8080/api/secure/profile
            // curl -H "Accept-Language: zh-CN" http://localhost:8080/api/secure/content
            // curl -H "X-API-Key: key123" -H "X-Request-Id: req-001" http://localhost:8080/api/secure/api-call
            // curl -X POST -H "X-File-Name: doc.pdf" -H "X-File-Type: application/pdf" \
            //      --data-binary @doc.pdf http://localhost:8080/api/secure/upload
            ---

04.请求体绑定
    a.@Body对象绑定
        a.JSON反序列化
            @Body注解将请求体JSON自动反序列化为Java对象,支持简单对象、嵌套对象、泛型对象、集合类型的绑定。框架使用Jackson进行反序列化,自动处理日期格式、命名转换等。
        b.请求体绑定示例
            ---
            @Controller("/api/users")
            public class RequestBodyController {
                private final UserService userService;

                public RequestBodyController(UserService userService) {
                    this.userService = userService;
                }

                // 简单对象绑定
                @Post
                public User createUser(@Body User user) {
                    // POST /api/users
                    // Content-Type: application/json
                    // {"username": "john", "email": "[email protected]", "age": 30}

                    System.out.println("创建用户:");
                    System.out.println("  用户名: " + user.getUsername());
                    System.out.println("  邮箱: " + user.getEmail());
                    System.out.println("  年龄: " + user.getAge());

                    return userService.create(user);
                }

                // 嵌套对象绑定
                @Post("/register")
                public RegistrationResponse register(@Body RegistrationRequest request) {
                    // POST /api/users/register
                    // {
                    //   "username": "john",
                    //   "email": "[email protected]",
                    //   "password": "secret123",
                    //   "profile": {
                    //     "firstName": "John",
                    //     "lastName": "Doe",
                    //     "birthDate": "1990-01-15",
                    //     "address": {
                    //       "street": "123 Main St",
                    //       "city": "New York",
                    //       "zipCode": "10001"
                    //     }
                    //   },
                    //   "preferences": {
                    //     "language": "en",
                    //     "timezone": "America/New_York",
                    //     "notifications": true
                    //   }
                    // }

                    System.out.println("注册用户:");
                    System.out.println("  用户名: " + request.getUsername());
                    System.out.println("  邮箱: " + request.getEmail());
                    System.out.println("  姓名: " + request.getProfile().getFirstName() +
                                     " " + request.getProfile().getLastName());
                    System.out.println("  地址: " + request.getProfile().getAddress().getCity());
                    System.out.println("  语言: " + request.getPreferences().getLanguage());

                    User user = userService.register(request);
                    return new RegistrationResponse(user.getId(), "注册成功");
                }

                // 集合类型绑定 - List
                @Post("/batch")
                public BatchResponse<User> batchCreate(@Body List<User> users) {
                    // POST /api/users/batch
                    // [
                    //   {"username": "user1", "email": "[email protected]"},
                    //   {"username": "user2", "email": "[email protected]"},
                    //   {"username": "user3", "email": "[email protected]"}
                    // ]

                    System.out.println("批量创建 " + users.size() + " 个用户");
                    for (int i = 0; i < users.size(); i++) {
                        System.out.println("  用户" + (i+1) + ": " + users.get(i).getUsername());
                    }

                    List<User> created = userService.batchCreate(users);
                    return new BatchResponse<>(created.size(), created);
                }

                // Map类型绑定 - 动态字段
                @Patch("/{id}")
                public User partialUpdate(Long id, @Body Map<String, Object> updates) {
                    // PATCH /api/users/123
                    // {
                    //   "email": "[email protected]",
                    //   "phone": "13900139000",
                    //   "profile.city": "Beijing"
                    // }

                    System.out.println("部分更新用户 " + id);
                    System.out.println("更新字段: " + updates.keySet());

                    User user = userService.findById(id);

                    // 应用更新
                    if (updates.containsKey("email")) {
                        user.setEmail((String) updates.get("email"));
                    }
                    if (updates.containsKey("phone")) {
                        user.setPhone((String) updates.get("phone"));
                    }
                    if (updates.containsKey("age")) {
                        user.setAge(((Number) updates.get("age")).intValue());
                    }

                    return userService.update(user);
                }

                // 泛型请求体绑定
                @Post("/action")
                public ActionResponse<User> performAction(@Body ActionRequest<User> request) {
                    // POST /api/users/action
                    // {
                    //   "action": "update",
                    //   "data": {"username": "john", "email": "[email protected]"},
                    //   "options": {"notify": true, "async": false}
                    // }

                    System.out.println("执行操作: " + request.getAction());
                    System.out.println("数据: " + request.getData().getUsername());
                    System.out.println("选项: " + request.getOptions());

                    User result = userService.performAction(request.getAction(), request.getData());
                    return new ActionResponse<>(request.getAction(), result, "操作成功");
                }

                // 可选请求体
                @Post("/search")
                public List<User> search(@Body @Nullable SearchCriteria criteria) {
                    // POST /api/users/search
                    // 可以不传请求体,或传递搜索条件

                    if (criteria == null) {
                        System.out.println("搜索: 返回所有用户");
                        return userService.findAll();
                    }

                    System.out.println("搜索条件:");
                    System.out.println("  关键词: " + criteria.getKeyword());
                    System.out.println("  状态: " + criteria.getStatus());

                    return userService.search(criteria);
                }
            }

            // 请求对象定义
            public class RegistrationRequest {
                private String username;
                private String email;
                private String password;
                private UserProfile profile;
                private UserPreferences preferences;

                // Getter和Setter省略
            }

            public class UserProfile {
                private String firstName;
                private String lastName;
                private LocalDate birthDate;
                private Address address;

                // Getter和Setter省略
            }

            public class Address {
                private String street;
                private String city;
                private String zipCode;

                // Getter和Setter省略
            }

            public class UserPreferences {
                private String language;
                private String timezone;
                private boolean notifications;

                // Getter和Setter省略
            }

            public class ActionRequest<T> {
                private String action;
                private T data;
                private Map<String, Object> options;

                // Getter和Setter省略
            }

            public class ActionResponse<T> {
                private String action;
                private T result;
                private String message;

                public ActionResponse(String action, T result, String message) {
                    this.action = action;
                    this.result = result;
                    this.message = message;
                }

                // Getter省略
            }

            // curl示例
            // curl -X POST -H "Content-Type: application/json" \
            //      -d '{"username":"john","email":"[email protected]","age":30}' \
            //      http://localhost:8080/api/users

            // curl -X PATCH -H "Content-Type: application/json" \
            //      -d '{"email":"[email protected]","phone":"13900139000"}' \
            //      http://localhost:8080/api/users/123
            ---

05.Cookie和表单绑定
    a.Cookie绑定
        a.@CookieValue注解
            @CookieValue注解绑定HTTP Cookie到方法参数,用于读取会话标识、用户偏好、记住登录状态等存储在Cookie中的数据。支持必需Cookie和可选Cookie,可以设置默认值。
        b.Cookie绑定示例
            ---
            import io.micronaut.http.annotation.CookieValue;
            import io.micronaut.http.cookie.Cookie;

            @Controller("/api")
            public class CookieController {
                private final SessionService sessionService;

                public CookieController(SessionService sessionService) {
                    this.sessionService = sessionService;
                }

                // 必需Cookie
                @Get("/session")
                public SessionInfo getSession(@CookieValue("SESSIONID") String sessionId) {
                    // Cookie: SESSIONID=abc123def456
                    System.out.println("会话ID: " + sessionId);
                    return sessionService.getSessionInfo(sessionId);
                }

                // 可选Cookie
                @Get("/preferences")
                public UserPreferences getPreferences(
                    @CookieValue("theme") @Nullable String theme,
                    @CookieValue("language") @Nullable String language) {

                    // Cookie: theme=dark; language=zh-CN
                    String userTheme = theme != null ? theme : "light";
                    String userLang = language != null ? language : "en";

                    System.out.println("主题: " + userTheme);
                    System.out.println("语言: " + userLang);

                    return new UserPreferences(userTheme, userLang);
                }

                // 带默认值的Cookie
                @Get("/settings")
                public Settings getSettings(
                    @CookieValue(value = "fontSize", defaultValue = "14") int fontSize,
                    @CookieValue(value = "autoSave", defaultValue = "true") boolean autoSave) {

                    System.out.println("字体大小: " + fontSize);
                    System.out.println("自动保存: " + autoSave);

                    return new Settings(fontSize, autoSave);
                }

                // 设置Cookie - 返回HttpResponse
                @Post("/login")
                public HttpResponse<LoginResponse> login(@Body LoginRequest request) {
                    String sessionId = sessionService.createSession(request.getUsername());

                    Cookie sessionCookie = Cookie.of("SESSIONID", sessionId)
                        .maxAge(Duration.ofHours(24))
                        .path("/")
                        .httpOnly(true)
                        .secure(true);

                    Cookie rememberMeCookie = Cookie.of("remember-me", "true")
                        .maxAge(Duration.ofDays(30))
                        .path("/");

                    return HttpResponse.ok(new LoginResponse("登录成功"))
                        .cookie(sessionCookie)
                        .cookie(rememberMeCookie);
                }

                // 删除Cookie
                @Post("/logout")
                public HttpResponse<Void> logout() {
                    // 设置maxAge为0删除Cookie
                    Cookie deleteCookie = Cookie.of("SESSIONID", "")
                        .maxAge(Duration.ZERO)
                        .path("/");

                    return HttpResponse.noContent()
                        .cookie(deleteCookie);
                }
            }

            // curl示例
            // curl -b "SESSIONID=abc123" http://localhost:8080/api/session
            // curl -b "theme=dark; language=zh-CN" http://localhost:8080/api/preferences
            // curl -X POST -H "Content-Type: application/json" \
            //      -d '{"username":"john","password":"secret"}' \
            //      http://localhost:8080/api/login
            ---
    b.表单数据绑定
        a.@Body表单绑定
            通过@Body绑定application/x-www-form-urlencoded格式的表单数据,自动将表单字段映射到对象属性或方法参数。支持嵌套对象和集合属性的表单提交。
        b.表单绑定示例
            ---
            import io.micronaut.http.annotation.Part;
            import io.micronaut.http.multipart.CompletedFileUpload;

            @Controller("/api/forms")
            public class FormController {
                private final FormService formService;

                public FormController(FormService formService) {
                    this.formService = formService;
                }

                // 表单字段绑定到对象
                @Post("/submit")
                @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
                public FormResponse submitForm(@Body ContactForm form) {
                    // POST /api/forms/submit
                    // Content-Type: application/x-www-form-urlencoded
                    // name=John+Doe&email=john%40example.com&message=Hello&subscribe=true

                    System.out.println("表单提交:");
                    System.out.println("  姓名: " + form.getName());
                    System.out.println("  邮箱: " + form.getEmail());
                    System.out.println("  消息: " + form.getMessage());
                    System.out.println("  订阅: " + form.isSubscribe());

                    formService.processContact(form);
                    return new FormResponse("表单已提交");
                }

                // 单文件上传
                @Post("/upload")
                @Consumes(MediaType.MULTIPART_FORM_DATA)
                public UploadResponse uploadFile(
                    @Part("file") CompletedFileUpload file,
                    @Part("description") @Nullable String description) throws IOException {

                    // POST /api/forms/upload
                    // Content-Type: multipart/form-data
                    // [email protected]
                    // description=重要文档

                    System.out.println("文件上传:");
                    System.out.println("  文件名: " + file.getFilename());
                    System.out.println("  大小: " + file.getSize() + " bytes");
                    System.out.println("  类型: " + file.getContentType().orElse("unknown"));
                    System.out.println("  描述: " + description);

                    byte[] bytes = file.getBytes();
                    String fileId = formService.saveFile(file.getFilename(), bytes);

                    return new UploadResponse(fileId, file.getFilename(), file.getSize());
                }

                // 多文件上传
                @Post("/upload-multiple")
                @Consumes(MediaType.MULTIPART_FORM_DATA)
                public BatchUploadResponse uploadMultipleFiles(
                    @Part("files") List<CompletedFileUpload> files,
                    @Part("category") String category) throws IOException {

                    System.out.println("批量上传 " + files.size() + " 个文件, 分类: " + category);

                    List<String> fileIds = new ArrayList<>();
                    for (CompletedFileUpload file : files) {
                        System.out.println("  文件: " + file.getFilename() +
                                         " (" + file.getSize() + " bytes)");
                        byte[] bytes = file.getBytes();
                        String fileId = formService.saveFile(file.getFilename(), bytes);
                        fileIds.add(fileId);
                    }

                    return new BatchUploadResponse(fileIds.size(), fileIds);
                }

                // 混合表单数据和文件
                @Post("/submit-with-file")
                @Consumes(MediaType.MULTIPART_FORM_DATA)
                public SubmitResponse submitWithFile(
                    @Part("title") String title,
                    @Part("content") String content,
                    @Part("tags") List<String> tags,
                    @Part("attachment") @Nullable CompletedFileUpload attachment) throws IOException {

                    System.out.println("提交文章:");
                    System.out.println("  标题: " + title);
                    System.out.println("  内容: " + content);
                    System.out.println("  标签: " + tags);

                    String attachmentId = null;
                    if (attachment != null) {
                        System.out.println("  附件: " + attachment.getFilename());
                        byte[] bytes = attachment.getBytes();
                        attachmentId = formService.saveFile(attachment.getFilename(), bytes);
                    }

                    Long articleId = formService.createArticle(title, content, tags, attachmentId);
                    return new SubmitResponse(articleId, "文章已创建");
                }
            }

            // 表单对象定义
            public class ContactForm {
                private String name;
                private String email;
                private String message;
                private boolean subscribe;

                // Getter和Setter省略
            }

            // curl示例
            // curl -X POST -H "Content-Type: application/x-www-form-urlencoded" \
            //      -d "name=John Doe&[email protected]&message=Hello&subscribe=true" \
            //      http://localhost:8080/api/forms/submit

            // curl -X POST -F "[email protected]" -F "description=重要文档" \
            //      http://localhost:8080/api/forms/upload

            // curl -X POST -F "[email protected]" -F "[email protected]" -F "category=documents" \
            //      http://localhost:8080/api/forms/upload-multiple

            // curl -X POST -F "title=文章标题" -F "content=文章内容" \
            //      -F "tags=java" -F "tags=micronaut" -F "[email protected]" \
            //      http://localhost:8080/api/forms/submit-with-file
            ---

4.4 响应处理

01.响应类型
    a.直接返回对象
        a.自动序列化
            控制器方法直接返回Java对象时,框架自动将对象序列化为JSON格式响应,Content-Type默认为application/json。支持返回POJO、集合、Map等类型,使用Jackson或配置的序列化器进行转换。
        b.对象返回示例
            ---
            import io.micronaut.http.annotation.*;
            import java.util.*;

            @Controller("/api/data")
            public class DataResponseController {
                private final DataService dataService;

                public DataResponseController(DataService dataService) {
                    this.dataService = dataService;
                }

                // 返回单个对象
                @Get("/user/{id}")
                public User getUser(Long id) {
                    // GET /api/data/user/123
                    // 响应: {"id": 123, "username": "john", "email": "[email protected]"}
                    System.out.println("查询用户: " + id);
                    return dataService.findUserById(id);
                }

                // 返回List集合
                @Get("/users")
                public List<User> getUsers() {
                    // GET /api/data/users
                    // 响应: [{"id": 1, "username": "john"}, {"id": 2, "username": "jane"}]
                    System.out.println("查询所有用户");
                    return dataService.findAllUsers();
                }

                // 返回Map
                @Get("/statistics")
                public Map<String, Object> getStatistics() {
                    // GET /api/data/statistics
                    // 响应: {"total": 100, "active": 85, "inactive": 15, "ratio": 0.85}
                    Map<String, Object> stats = new HashMap<>();
                    stats.put("total", 100);
                    stats.put("active", 85);
                    stats.put("inactive", 15);
                    stats.put("ratio", 0.85);
                    return stats;
                }

                // 返回嵌套对象
                @Get("/order/{id}")
                public Order getOrder(Long id) {
                    // GET /api/data/order/456
                    // 响应包含嵌套的用户、商品、地址对象
                    System.out.println("查询订单: " + id);
                    return dataService.findOrderById(id);
                }

                // 返回分页对象
                @Get("/products")
                public Page<Product> getProducts(
                    @QueryValue(defaultValue = "0") int page,
                    @QueryValue(defaultValue = "20") int size) {
                    // GET /api/data/products?page=0&size=20
                    // 响应: {
                    //   "content": [...],
                    //   "page": 0,
                    //   "size": 20,
                    //   "totalElements": 150,
                    //   "totalPages": 8
                    // }
                    return dataService.findProducts(page, size);
                }
            }

            // 分页对象定义
            public class Page<T> {
                private List<T> content;
                private int page;
                private int size;
                private long totalElements;
                private int totalPages;

                public Page(List<T> content, int page, int size, long totalElements) {
                    this.content = content;
                    this.page = page;
                    this.size = size;
                    this.totalElements = totalElements;
                    this.totalPages = (int) Math.ceil((double) totalElements / size);
                }

                // Getter省略
            }
            ---
    b.HttpResponse返回
        a.完全控制响应
            返回HttpResponse对象可以完全控制响应内容、状态码、响应头、Cookie等,提供最灵活的响应定制能力。使用工厂方法快速构建标准HTTP响应。
        b.HttpResponse示例
            ---
            import io.micronaut.http.HttpResponse;
            import io.micronaut.http.MutableHttpResponse;
            import io.micronaut.http.MediaType;

            @Controller("/api/responses")
            public class HttpResponseController {
                private final ResponseService responseService;

                public HttpResponseController(ResponseService responseService) {
                    this.responseService = responseService;
                }

                // 200 OK响应
                @Get("/ok")
                public HttpResponse<Message> ok() {
                    Message message = new Message("操作成功");
                    return HttpResponse.ok(message);
                }

                // 201 Created响应 + Location头
                @Post("/users")
                public HttpResponse<User> createUser(@Body User user) {
                    User created = responseService.createUser(user);

                    return HttpResponse.created(created)
                        .header("Location", "/api/responses/users/" + created.getId())
                        .header("X-User-Id", created.getId().toString());
                }

                // 204 No Content响应
                @Delete("/users/{id}")
                public HttpResponse<Void> deleteUser(Long id) {
                    responseService.deleteUser(id);
                    // 返回204,没有响应体
                    return HttpResponse.noContent();
                }

                // 202 Accepted响应 - 异步任务
                @Post("/tasks")
                public HttpResponse<TaskResponse> submitTask(@Body TaskRequest request) {
                    String taskId = responseService.submitAsyncTask(request);

                    TaskResponse response = new TaskResponse(taskId, "任务已提交");
                    return HttpResponse.accepted()
                        .body(response)
                        .header("X-Task-Id", taskId)
                        .header("Location", "/api/responses/tasks/" + taskId);
                }

                // 404 Not Found响应
                @Get("/users/{id}")
                public HttpResponse<User> getUser(Long id) {
                    Optional<User> user = responseService.findUserById(id);

                    if (user.isPresent()) {
                        return HttpResponse.ok(user.get());
                    } else {
                        return HttpResponse.notFound();
                    }
                }

                // 400 Bad Request响应
                @Post("/validate")
                public HttpResponse<?> validate(@Body ValidationRequest request) {
                    List<String> errors = responseService.validate(request);

                    if (errors.isEmpty()) {
                        return HttpResponse.ok(new Message("验证通过"));
                    } else {
                        ErrorResponse error = new ErrorResponse(
                            "VALIDATION_ERROR",
                            "请求数据验证失败",
                            errors
                        );
                        return HttpResponse.badRequest(error);
                    }
                }

                // 自定义状态码
                @Get("/custom")
                public HttpResponse<Message> customStatus() {
                    return HttpResponse.status(HttpStatus.I_AM_A_TEAPOT)
                        .body(new Message("我是茶壶"));
                }

                // 构建复杂响应
                @Get("/download/{fileId}")
                public MutableHttpResponse<byte[]> downloadFile(String fileId) {
                    byte[] data = responseService.getFileData(fileId);
                    String fileName = responseService.getFileName(fileId);

                    return HttpResponse.ok(data)
                        .contentType(MediaType.APPLICATION_OCTET_STREAM)
                        .header("Content-Disposition",
                               "attachment; filename=\"" + fileName + "\"")
                        .header("Content-Length", String.valueOf(data.length))
                        .header("X-File-Id", fileId);
                }

                // 重定向响应
                @Get("/redirect")
                public HttpResponse<?> redirect() {
                    // 302临时重定向
                    return HttpResponse.redirect(URI.create("/api/responses/ok"));
                }

                @Get("/permanent-redirect")
                public HttpResponse<?> permanentRedirect() {
                    // 301永久重定向
                    return HttpResponse.permanentRedirect(URI.create("/api/responses/ok"));
                }
            }

            // 响应对象定义
            public class Message {
                private String message;
                private long timestamp;

                public Message(String message) {
                    this.message = message;
                    this.timestamp = System.currentTimeMillis();
                }

                // Getter省略
            }

            public class TaskResponse {
                private String taskId;
                private String message;
                private String status;

                public TaskResponse(String taskId, String message) {
                    this.taskId = taskId;
                    this.message = message;
                    this.status = "PENDING";
                }

                // Getter省略
            }

            public class ErrorResponse {
                private String code;
                private String message;
                private Object details;
                private long timestamp;

                public ErrorResponse(String code, String message, Object details) {
                    this.code = code;
                    this.message = message;
                    this.details = details;
                    this.timestamp = System.currentTimeMillis();
                }

                // Getter省略
            }
            ---
    c.响应式返���
        a.异步响应
            返回CompletableFuture、Publisher、Flux、Mono等响应式类型,支持流式响应和异步处理,提升高并发场景的性能,控制器方法立即返回。
        b.响应式示例
            ---
            import java.util.concurrent.CompletableFuture;
            import reactor.core.publisher.Flux;
            import reactor.core.publisher.Mono;
            import org.reactivestreams.Publisher;

            @Controller("/api/reactive")
            public class ReactiveResponseController {
                private final ReactiveService reactiveService;

                public ReactiveResponseController(ReactiveService reactiveService) {
                    this.reactiveService = reactiveService;
                }

                // CompletableFuture - 异步单个对象
                @Get("/user/{id}")
                public CompletableFuture<User> getUserAsync(Long id) {
                    // 异步查询用户,立即返回Future
                    System.out.println("异步查询用户: " + id);

                    return CompletableFuture.supplyAsync(() -> {
                        // 在后台线程执行
                        return reactiveService.findUserById(id);
                    });
                }

                // Mono - 单个元素的响应式流
                @Get("/order/{id}")
                public Mono<Order> getOrderMono(Long id) {
                    System.out.println("Mono查询订单: " + id);
                    return reactiveService.findOrderByIdMono(id);
                }

                // Flux - 多个元素的响应式流
                @Get("/products")
                @Produces(MediaType.APPLICATION_JSON_STREAM)
                public Flux<Product> streamProducts() {
                    // 流式返回产品列表,逐个发送
                    System.out.println("流式传输产品列表");
                    return reactiveService.streamAllProducts();
                }

                // Publisher - 标准响应式流接口
                @Get("/events")
                @Produces(MediaType.TEXT_EVENT_STREAM)
                public Publisher<ServerSentEvent<String>> streamEvents() {
                    // Server-Sent Events流式推送
                    System.out.println("开始推送事件流");

                    return Flux.interval(Duration.ofSeconds(1))
                        .map(seq -> ServerSentEvent.<String>builder()
                            .id(String.valueOf(seq))
                            .data("事件 " + seq)
                            .comment("序列号: " + seq)
                            .build());
                }

                // 异步处理后返回
                @Post("/process")
                public CompletableFuture<ProcessResult> processAsync(@Body ProcessRequest request) {
                    System.out.println("提交异步处理任务");

                    return CompletableFuture.supplyAsync(() -> {
                        // 模拟耗时处理
                        try {
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        }

                        ProcessResult result = new ProcessResult();
                        result.setStatus("完成");
                        result.setData(request.getData());
                        result.setProcessedAt(LocalDateTime.now());
                        return result;
                    });
                }

                // 异步流式处理
                @Post("/batch-process")
                @Produces(MediaType.APPLICATION_JSON_STREAM)
                public Flux<BatchResult> processBatch(@Body List<String> items) {
                    System.out.println("批量处理 " + items.size() + " 项");

                    return Flux.fromIterable(items)
                        .flatMap(item -> reactiveService.processItem(item))
                        .map(result -> new BatchResult(result.getId(), result.getStatus()));
                }
            }

            // Server-Sent Event类
            import io.micronaut.http.sse.Event;

            public class ServerSentEvent<T> implements Event<T> {
                private String id;
                private T data;
                private String comment;

                public static <T> Builder<T> builder() {
                    return new Builder<>();
                }

                public static class Builder<T> {
                    private String id;
                    private T data;
                    private String comment;

                    public Builder<T> id(String id) {
                        this.id = id;
                        return this;
                    }

                    public Builder<T> data(T data) {
                        this.data = data;
                        return this;
                    }

                    public Builder<T> comment(String comment) {
                        this.comment = comment;
                        return this;
                    }

                    public ServerSentEvent<T> build() {
                        ServerSentEvent<T> event = new ServerSentEvent<>();
                        event.id = this.id;
                        event.data = this.data;
                        event.comment = this.comment;
                        return event;
                    }
                }

                // Getter省略
            }

            // 处理结果对象
            public class ProcessResult {
                private String status;
                private Object data;
                private LocalDateTime processedAt;

                // Getter和Setter省略
            }

            public class BatchResult {
                private Long id;
                private String status;

                public BatchResult(Long id, String status) {
                    this.id = id;
                    this.status = status;
                }

                // Getter省略
            }
            ---

02.状态码控制
    a.@Status注解
        a.固定状态码
            通过@Status注解指定方法成功响应的HTTP状态码,简化状态码设置。常用状态码:200 OK、201 Created、204 No Content、202 Accepted。
        b.Status注解示例
            ---
            @Controller("/api/resources")
            public class StatusCodeController {
                private final ResourceService resourceService;

                public StatusCodeController(ResourceService resourceService) {
                    this.resourceService = resourceService;
                }

                // 201 Created - 创建成功
                @Post
                @Status(HttpStatus.CREATED)
                public Resource createResource(@Body ResourceRequest request) {
                    System.out.println("创建资源: " + request.getName());
                    return resourceService.create(request);
                }

                // 204 No Content - 更新成功无返回
                @Put("/{id}")
                @Status(HttpStatus.NO_CONTENT)
                public void updateResource(Long id, @Body ResourceRequest request) {
                    System.out.println("更新资源: " + id);
                    resourceService.update(id, request);
                    // 返回void,响应204 No Content
                }

                // 202 Accepted - 异步任务已接受
                @Post("/async")
                @Status(HttpStatus.ACCEPTED)
                public TaskInfo submitAsyncTask(@Body TaskRequest request) {
                    System.out.println("提交异步任务");
                    String taskId = resourceService.submitTask(request);
                    return new TaskInfo(taskId, "任务已接受");
                }

                // 206 Partial Content - 部分内容
                @Get("/{id}/partial")
                @Status(HttpStatus.PARTIAL_CONTENT)
                public PartialData getPartialData(
                    Long id,
                    @Header("Range") String range) {
                    System.out.println("获取部分数据: " + id + ", 范围: " + range);
                    return resourceService.getPartialData(id, range);
                }

                // 默认200 OK - 无需显式指定
                @Get("/{id}")
                public Resource getResource(Long id) {
                    System.out.println("查询资源: " + id);
                    return resourceService.findById(id);
                }
            }

            // 任务信息对象
            public class TaskInfo {
                private String taskId;
                private String message;
                private String status;
                private long timestamp;

                public TaskInfo(String taskId, String message) {
                    this.taskId = taskId;
                    this.message = message;
                    this.status = "ACCEPTED";
                    this.timestamp = System.currentTimeMillis();
                }

                // Getter省略
            }

            // 部分数据对象
            public class PartialData {
                private String range;
                private byte[] data;
                private long totalSize;

                public PartialData(String range, byte[] data, long totalSize) {
                    this.range = range;
                    this.data = data;
                    this.totalSize = totalSize;
                }

                // Getter省略
            }
            ---
    b.动态状态码
        a.条件响应
            根据业务逻辑动态选择状态码,使用HttpResponse构建不同状态的响应。常见场景:资源是否存在、验证是否通过、权限检查等。
        b.动态状态码示例
            ---
            @Controller("/api/dynamic")
            public class DynamicStatusController {
                private final DynamicService dynamicService;

                public DynamicStatusController(DynamicService dynamicService) {
                    this.dynamicService = dynamicService;
                }

                // 根据资源是否存在返回不同状态
                @Get("/resource/{id}")
                public HttpResponse<Resource> getResource(Long id) {
                    Optional<Resource> resource = dynamicService.findById(id);

                    if (resource.isPresent()) {
                        return HttpResponse.ok(resource.get());  // 200 OK
                    } else {
                        return HttpResponse.notFound();  // 404 Not Found
                    }
                }

                // 根据删除结果返回不同状态
                @Delete("/resource/{id}")
                public HttpResponse<Void> deleteResource(Long id) {
                    boolean deleted = dynamicService.delete(id);

                    if (deleted) {
                        return HttpResponse.noContent();  // 204 No Content
                    } else {
                        return HttpResponse.notFound();  // 404 Not Found
                    }
                }

                // 根据验证结果返回不同状态
                @Post("/submit")
                public HttpResponse<?> submitData(@Body DataRequest request) {
                    ValidationResult validation = dynamicService.validate(request);

                    if (validation.isValid()) {
                        Data data = dynamicService.save(request);
                        return HttpResponse.created(data);  // 201 Created
                    } else {
                        ErrorResponse error = new ErrorResponse(
                            "VALIDATION_ERROR",
                            "数据验证失败",
                            validation.getErrors()
                        );
                        return HttpResponse.badRequest(error);  // 400 Bad Request
                    }
                }

                // 根据权限返回不同状态
                @Get("/protected/{id}")
                public HttpResponse<?> getProtectedResource(
                    Long id,
                    @Header("Authorization") @Nullable String authorization) {

                    if (authorization == null) {
                        // 未提供认证信息
                        return HttpResponse.unauthorized();  // 401 Unauthorized
                    }

                    boolean authenticated = dynamicService.verifyToken(authorization);
                    if (!authenticated) {
                        return HttpResponse.unauthorized();  // 401 Unauthorized
                    }

                    boolean hasPermission = dynamicService.checkPermission(authorization, id);
                    if (!hasPermission) {
                        // 已认证但无权限
                        ErrorResponse error = new ErrorResponse(
                            "FORBIDDEN",
                            "您没有权限访问此资源",
                            null
                        );
                        return HttpResponse.status(HttpStatus.FORBIDDEN)
                            .body(error);  // 403 Forbidden
                    }

                    Resource resource = dynamicService.getResource(id);
                    return HttpResponse.ok(resource);  // 200 OK
                }

                // 根据资源状态返回不同响应
                @Put("/resource/{id}/status")
                public HttpResponse<?> updateStatus(
                    Long id,
                    @Body StatusUpdate update) {

                    try {
                        ResourceState result = dynamicService.updateStatus(id, update.getStatus());

                        switch (result) {
                            case UPDATED:
                                return HttpResponse.ok(new Message("状态已更新"));  // 200 OK
                            case NOT_FOUND:
                                return HttpResponse.notFound();  // 404 Not Found
                            case CONFLICT:
                                ErrorResponse conflict = new ErrorResponse(
                                    "CONFLICT",
                                    "状态冲突,资源已被修改",
                                    null
                                );
                                return HttpResponse.status(HttpStatus.CONFLICT)
                                    .body(conflict);  // 409 Conflict
                            case PRECONDITION_FAILED:
                                ErrorResponse precondition = new ErrorResponse(
                                    "PRECONDITION_FAILED",
                                    "前置条件不满足",
                                    null
                                );
                                return HttpResponse.status(HttpStatus.PRECONDITION_FAILED)
                                    .body(precondition);  // 412 Precondition Failed
                            default:
                                return HttpResponse.serverError();  // 500 Internal Server Error
                        }
                    } catch (Exception e) {
                        ErrorResponse error = new ErrorResponse(
                            "INTERNAL_ERROR",
                            "服务器内部错误",
                            e.getMessage()
                        );
                        return HttpResponse.serverError(error);  // 500 Internal Server Error
                    }
                }
            }

            // 资源状态枚举
            public enum ResourceState {
                UPDATED,
                NOT_FOUND,
                CONFLICT,
                PRECONDITION_FAILED
            }

            // 状态更新请求
            public class StatusUpdate {
                private String status;
                private String reason;

                // Getter和Setter省略
            }

            // 验证结果对象
            public class ValidationResult {
                private boolean valid;
                private List<String> errors;

                public ValidationResult(boolean valid, List<String> errors) {
                    this.valid = valid;
                    this.errors = errors;
                }

                public boolean isValid() { return valid; }
                public List<String> getErrors() { return errors; }
            }
            ---

03.响应头设置
    a.固定响应头
        a.@Header方法级注解
            在方法上使用@Header注解添加固定响应头,如CORS头、缓存控制头、API版本头等。适用于添加固定的响应头,简化响应头配置。
        b.固定响应头示例
            ---
            @Controller("/api/headers")
            public class ResponseHeaderController {
                private final HeaderService headerService;

                public ResponseHeaderController(HeaderService headerService) {
                    this.headerService = headerService;
                }

                // 单个固定响应头
                @Get("/version")
                @Header(name = "X-API-Version", value = "1.0")
                public ApiInfo getVersion() {
                    return new ApiInfo("API", "1.0");
                }

                // 多个固定响应头
                @Get("/cors-enabled")
                @Header(name = "Access-Control-Allow-Origin", value = "*")
                @Header(name = "Access-Control-Allow-Methods", value = "GET, POST, PUT, DELETE")
                @Header(name = "Access-Control-Max-Age", value = "3600")
                public Message getCorsEnabled() {
                    return new Message("支持CORS跨域访问");
                }

                // 缓存控制头
                @Get("/cacheable")
                @Header(name = "Cache-Control", value = "public, max-age=3600")
                @Header(name = "ETag", value = "v1.0")
                public CacheableData getCacheableData() {
                    return headerService.getCacheableData();
                }

                // 自定义业务响应头
                @Get("/business")
                @Header(name = "X-Request-Id", value = "generated-id")
                @Header(name = "X-Tenant-Id", value = "default")
                @Header(name = "X-Response-Time", value = "50ms")
                public BusinessData getBusinessData() {
                    return headerService.getBusinessData();
                }
            }

            // API信息对象
            public class ApiInfo {
                private String name;
                private String version;

                public ApiInfo(String name, String version) {
                    this.name = name;
                    this.version = version;
                }

                // Getter省略
            }

            // 可缓存数据对象
            public class CacheableData {
                private String data;
                private long timestamp;
                private String etag;

                // Getter和Setter省略
            }

            // 业务数据对象
            public class BusinessData {
                private String content;
                private Map<String, Object> metadata;

                // Getter和Setter省略
            }
            ---
    b.动态响应头
        a.HttpResponse响应头
            通过HttpResponse.header()方法动态添加响应头,根据请求内容或业务逻辑设置不同的响应头值。支持链式调用,设置多个响应头。
        b.动态响应头示例
            ---
            @Controller("/api/dynamic-headers")
            public class DynamicHeaderController {
                private final DynamicHeaderService headerService;

                public DynamicHeaderController(DynamicHeaderService headerService) {
                    this.headerService = headerService;
                }

                // 动态设置Content-Type
                @Get("/content/{format}")
                public HttpResponse<?> getContent(String format) {
                    Object data = headerService.getData();

                    switch (format.toLowerCase()) {
                        case "json":
                            return HttpResponse.ok(data)
                                .contentType(MediaType.APPLICATION_JSON);
                        case "xml":
                            String xml = headerService.toXml(data);
                            return HttpResponse.ok(xml)
                                .contentType(MediaType.APPLICATION_XML);
                        case "text":
                            String text = data.toString();
                            return HttpResponse.ok(text)
                                .contentType(MediaType.TEXT_PLAIN);
                        default:
                            return HttpResponse.badRequest();
                    }
                }

                // 动态设置缓存头
                @Get("/cache/{resource}")
                public HttpResponse<Resource> getCachedResource(String resource) {
                    Resource data = headerService.getResource(resource);
                    String etag = headerService.calculateETag(data);
                    boolean cacheable = headerService.isCacheable(resource);

                    MutableHttpResponse<Resource> response = HttpResponse.ok(data)
                        .header("ETag", etag);

                    if (cacheable) {
                        response.header("Cache-Control", "public, max-age=3600");
                    } else {
                        response.header("Cache-Control", "no-cache, no-store, must-revalidate");
                    }

                    return response;
                }

                // 动态设置Location头
                @Post("/items")
                public HttpResponse<Item> createItem(@Body ItemRequest request) {
                    Item item = headerService.createItem(request);
                    String location = "/api/dynamic-headers/items/" + item.getId();

                    return HttpResponse.created(item)
                        .header("Location", location)
                        .header("X-Item-Id", item.getId().toString())
                        .header("X-Created-At", item.getCreatedAt().toString());
                }

                // 根据请求动态设置响应头
                @Get("/conditional")
                public HttpResponse<ConditionalData> getConditional(
                    @Header("Accept-Language") @Nullable String language,
                    @Header("Accept-Encoding") @Nullable String encoding) {

                    String lang = language != null ? language : "en";
                    ConditionalData data = headerService.getLocalizedData(lang);

                    MutableHttpResponse<ConditionalData> response = HttpResponse.ok(data)
                        .header("Content-Language", lang)
                        .header("X-Data-Version", data.getVersion());

                    // 根据Accept-Encoding设置压缩
                    if (encoding != null && encoding.contains("gzip")) {
                        response.header("Content-Encoding", "gzip");
                    }

                    return response;
                }

                // 设置多个自定义头
                @Get("/tracking/{id}")
                public HttpResponse<TrackingInfo> getTracking(Long id) {
                    TrackingInfo info = headerService.getTrackingInfo(id);
                    String requestId = UUID.randomUUID().toString();
                    String correlationId = headerService.getCorrelationId();

                    return HttpResponse.ok(info)
                        .header("X-Request-Id", requestId)
                        .header("X-Correlation-Id", correlationId)
                        .header("X-Processing-Time", info.getProcessingTime() + "ms")
                        .header("X-Cache-Status", info.isCached() ? "HIT" : "MISS")
                        .header("X-Server-Region", "us-west-1");
                }

                // 文件下载响应头
                @Get("/download/{fileId}")
                public HttpResponse<byte[]> downloadFile(String fileId) {
                    byte[] data = headerService.getFileData(fileId);
                    String fileName = headerService.getFileName(fileId);
                    String contentType = headerService.getContentType(fileId);
                    String checksum = headerService.calculateChecksum(data);

                    return HttpResponse.ok(data)
                        .contentType(contentType)
                        .header("Content-Disposition",
                               "attachment; filename=\"" + fileName + "\"")
                        .header("Content-Length", String.valueOf(data.length))
                        .header("X-File-Id", fileId)
                        .header("X-Checksum", checksum)
                        .header("X-Downloaded-At", LocalDateTime.now().toString());
                }
            }

            // 条件数据对象
            public class ConditionalData {
                private String content;
                private String version;
                private String language;

                // Getter和Setter省略
            }

            // 跟踪信息对象
            public class TrackingInfo {
                private Long id;
                private String status;
                private long processingTime;
                private boolean cached;

                // Getter和Setter省略
            }
            ---

04.内容协商与流式响应
    a.内容协商
        a.@Produces注解
            @Produces注解指定方法返回的内容类型,支持同一资源返回多种格式。根据客户端Accept请求头自动选择响应格式,实现内容协商。
        b.内容协商示例
            ---
            @Controller("/api/content")
            public class ContentNegotiationController {
                private final ContentService contentService;

                public ContentNegotiationController(ContentService contentService) {
                    this.contentService = contentService;
                }

                // 返回JSON格式(默认)
                @Get("/data")
                @Produces(MediaType.APPLICATION_JSON)
                public DataObject getDataJson() {
                    System.out.println("返回JSON格式");
                    return contentService.getData();
                }

                // 返回XML格式
                @Get("/data")
                @Produces(MediaType.APPLICATION_XML)
                public String getDataXml() {
                    System.out.println("返回XML格式");
                    DataObject data = contentService.getData();
                    return contentService.toXml(data);
                }

                // 返回纯文本
                @Get("/data")
                @Produces(MediaType.TEXT_PLAIN)
                public String getDataText() {
                    System.out.println("返回纯文本格式");
                    DataObject data = contentService.getData();
                    return data.toString();
                }

                // 返回HTML
                @Get("/page")
                @Produces(MediaType.TEXT_HTML)
                public String getHtmlPage() {
                    return "<html><body><h1>Hello Micronaut</h1></body></html>";
                }

                // 手动内容协商
                @Get("/manual")
                public HttpResponse<?> manualContentNegotiation(
                    @Header("Accept") String accept) {

                    DataObject data = contentService.getData();

                    if (accept.contains("application/json")) {
                        return HttpResponse.ok(data)
                            .contentType(MediaType.APPLICATION_JSON);
                    } else if (accept.contains("application/xml")) {
                        String xml = contentService.toXml(data);
                        return HttpResponse.ok(xml)
                            .contentType(MediaType.APPLICATION_XML);
                    } else if (accept.contains("text/plain")) {
                        return HttpResponse.ok(data.toString())
                            .contentType(MediaType.TEXT_PLAIN);
                    } else {
                        // 不支持的格式
                        return HttpResponse.status(HttpStatus.NOT_ACCEPTABLE)
                            .body(new Message("不支持的格式: " + accept));
                    }
                }
            }

            // 数据对象
            public class DataObject {
                private Long id;
                private String name;
                private String description;
                private Map<String, Object> attributes;

                @Override
                public String toString() {
                    return "DataObject{id=" + id + ", name=" + name +
                           ", description=" + description + "}";
                }

                // Getter和Setter省略
            }

            // curl示例
            // curl -H "Accept: application/json" http://localhost:8080/api/content/data
            // curl -H "Accept: application/xml" http://localhost:8080/api/content/data
            // curl -H "Accept: text/plain" http://localhost:8080/api/content/data
            ---
    b.流式响应
        a.Server-Sent Events
            返回Publisher<Event>实现服务器推送事件,建立持久连接向客户端推送实时消息。使用text/event-stream格式,客户端通过EventSource API接收。
        b.流式响应示例
            ---
            import io.micronaut.http.sse.Event;

            @Controller("/api/stream")
            public class StreamResponseController {
                private final StreamService streamService;

                public StreamResponseController(StreamService streamService) {
                    this.streamService = streamService;
                }

                // Server-Sent Events流
                @Get("/events")
                @Produces(MediaType.TEXT_EVENT_STREAM)
                public Publisher<Event<String>> streamEvents() {
                    System.out.println("开始推送事件流");

                    return Flux.interval(Duration.ofSeconds(1))
                        .map(seq -> Event.of("事件 " + seq)
                            .id(String.valueOf(seq))
                            .comment("序列号: " + seq));
                }

                // 流式JSON数据
                @Get("/products")
                @Produces(MediaType.APPLICATION_JSON_STREAM)
                public Flux<Product> streamProducts() {
                    System.out.println("流式传输产品列表");
                    return streamService.streamAllProducts();
                }

                // 分块传输大文件
                @Get("/download/{fileId}")
                public HttpResponse<StreamedFile> downloadLargeFile(String fileId) {
                    File file = streamService.getFile(fileId);
                    String fileName = file.getName();

                    StreamedFile streamedFile = new StreamedFile(file, MediaType.APPLICATION_OCTET_STREAM_TYPE);

                    return HttpResponse.ok(streamedFile)
                        .header("Content-Disposition",
                               "attachment; filename=\"" + fileName + "\"")
                        .header("Transfer-Encoding", "chunked");
                }

                // 实时进度推送
                @Post("/long-running")
                @Produces(MediaType.TEXT_EVENT_STREAM)
                public Publisher<Event<ProgressUpdate>> longRunningTask(@Body TaskRequest request) {
                    System.out.println("启动长时间运行任务");

                    return Flux.create(emitter -> {
                        streamService.executeLongTask(request, progress -> {
                            ProgressUpdate update = new ProgressUpdate(
                                progress.getPercent(),
                                progress.getMessage()
                            );
                            emitter.next(Event.of(update));

                            if (progress.isCompleted()) {
                                emitter.complete();
                            }
                        });
                    });
                }

                // 日志流式推送
                @Get("/logs/{serviceId}")
                @Produces(MediaType.TEXT_EVENT_STREAM)
                public Flux<Event<LogEntry>> streamLogs(String serviceId) {
                    System.out.println("开始推送日志: " + serviceId);

                    return streamService.watchLogs(serviceId)
                        .map(log -> Event.of(log)
                            .id(log.getId())
                            .event("log")
                            .comment("Level: " + log.getLevel()));
                }
            }

            // 进度更新对象
            public class ProgressUpdate {
                private int percent;
                private String message;
                private long timestamp;

                public ProgressUpdate(int percent, String message) {
                    this.percent = percent;
                    this.message = message;
                    this.timestamp = System.currentTimeMillis();
                }

                // Getter省略
            }

            // 日志条目对象
            public class LogEntry {
                private String id;
                private String level;
                private String message;
                private LocalDateTime timestamp;

                // Getter和Setter省略
            }

            // JavaScript客户端示例
            // const eventSource = new EventSource('http://localhost:8080/api/stream/events');
            // eventSource.onmessage = (event) => {
            //     console.log('收到事件:', event.data);
            // };
            ---

4.5 过滤器与拦截器

01.HTTP过滤器
    a.@Filter注解
        a.过滤器定义
            @Filter注解标记HTTP过滤器类,实现HttpFilter接口拦截HTTP请求和响应。过滤器可以修改请求、响应、添加日志、认证授权等,按照定义的patterns匹配URL路径执行过滤逻辑。
        b.基础过滤器示例
            ---
            import io.micronaut.http.HttpRequest;
            import io.micronaut.http.MutableHttpResponse;
            import io.micronaut.http.annotation.Filter;
            import io.micronaut.http.filter.HttpServerFilter;
            import io.micronaut.http.filter.ServerFilterChain;
            import org.reactivestreams.Publisher;
            import reactor.core.publisher.Flux;

            // 拦截所有/api/**路径的请求
            @Filter("/api/**")
            public class LoggingFilter implements HttpServerFilter {

                @Override
                public Publisher<MutableHttpResponse<?>> doFilter(
                    HttpRequest<?> request,
                    ServerFilterChain chain) {

                    long startTime = System.currentTimeMillis();

                    System.out.println("=== 请求开始 ===");
                    System.out.println("方法: " + request.getMethod());
                    System.out.println("路径: " + request.getPath());
                    System.out.println("参数: " + request.getParameters().asMap());

                    // 继续执行请求链
                    return Flux.from(chain.proceed(request))
                        .doOnNext(response -> {
                            long duration = System.currentTimeMillis() - startTime;
                            System.out.println("状态码: " + response.getStatus());
                            System.out.println("耗时: " + duration + "ms");
                            System.out.println("=== 请求结束 ===\n");
                        });
                }
            }

            // 拦截特定路径的过滤器
            @Filter("/api/secure/**")
            public class SecurityFilter implements HttpServerFilter {

                @Override
                public Publisher<MutableHttpResponse<?>> doFilter(
                    HttpRequest<?> request,
                    ServerFilterChain chain) {

                    System.out.println("安全过滤器: 检查访问权限");

                    // 获取Authorization请求头
                    String authorization = request.getHeaders().get("Authorization");

                    if (authorization == null || !authorization.startsWith("Bearer ")) {
                        // 未提供认证信息,返回401
                        System.out.println("认证失败: 缺少Authorization头");
                        MutableHttpResponse<?> response = HttpResponse.unauthorized();
                        return Flux.just(response);
                    }

                    String token = authorization.substring(7);
                    if (!isValidToken(token)) {
                        // Token无效,返回401
                        System.out.println("认证失败: Token无效");
                        return Flux.just(HttpResponse.unauthorized());
                    }

                    System.out.println("认证成功,继续执行请求");
                    // Token有效,继续执行
                    return chain.proceed(request);
                }

                private boolean isValidToken(String token) {
                    // 简化的Token验证逻辑
                    return token != null && token.length() > 10;
                }
            }

            // 多路径匹配的过滤器
            @Filter(patterns = {"/api/admin/**", "/api/management/**"})
            public class AdminFilter implements HttpServerFilter {

                @Override
                public Publisher<MutableHttpResponse<?>> doFilter(
                    HttpRequest<?> request,
                    ServerFilterChain chain) {

                    System.out.println("管理员过滤器: 检查管理员权限");

                    String token = request.getHeaders().get("Authorization");
                    if (!hasAdminRole(token)) {
                        System.out.println("权限不足: 需要管理员权限");
                        ErrorResponse error = new ErrorResponse(
                            "FORBIDDEN",
                            "需要管理员权限",
                            null
                        );
                        return Flux.just(HttpResponse.status(HttpStatus.FORBIDDEN).body(error));
                    }

                    System.out.println("管理员权限验证通过");
                    return chain.proceed(request);
                }

                private boolean hasAdminRole(String token) {
                    // 检查用户是否有管理员角色
                    return token != null && token.contains("admin");
                }
            }
            ---
    b.过滤器顺序
        a.执行优先级
            使用@Order注解控制过滤器执行顺序,数字越小优先级越高。未指定Order的过滤器默认优先级为0,可以使用负数提高优先级。
        b.过滤器顺序示例
            ---
            import io.micronaut.core.order.Ordered;

            // 优先级最高: 先执行
            @Filter("/api/**")
            @Order(Ordered.HIGHEST_PRECEDENCE)
            public class FirstFilter implements HttpServerFilter {

                @Override
                public Publisher<MutableHttpResponse<?>> doFilter(
                    HttpRequest<?> request,
                    ServerFilterChain chain) {

                    System.out.println("1. FirstFilter: 最高优先级过滤器");
                    return chain.proceed(request);
                }
            }

            // 优先级-100: 第二执行
            @Filter("/api/**")
            @Order(-100)
            public class AuthenticationFilter implements HttpServerFilter {

                @Override
                public Publisher<MutableHttpResponse<?>> doFilter(
                    HttpRequest<?> request,
                    ServerFilterChain chain) {

                    System.out.println("2. AuthenticationFilter: 认证过滤器 (优先级-100)");

                    // 认证逻辑
                    String token = request.getHeaders().get("X-Auth-Token");
                    if (token == null) {
                        System.out.println("   认证失败: 缺少token");
                        return Flux.just(HttpResponse.unauthorized());
                    }

                    System.out.println("   认证通过");
                    return chain.proceed(request);
                }
            }

            // 优先级0(默认): 第三执行
            @Filter("/api/**")
            public class LoggingFilter implements HttpServerFilter {

                @Override
                public Publisher<MutableHttpResponse<?>> doFilter(
                    HttpRequest<?> request,
                    ServerFilterChain chain) {

                    System.out.println("3. LoggingFilter: 日志过滤器 (默认优先级0)");

                    long start = System.currentTimeMillis();
                    return Flux.from(chain.proceed(request))
                        .doOnNext(response -> {
                            long duration = System.currentTimeMillis() - start;
                            System.out.println("   请求耗时: " + duration + "ms");
                        });
                }
            }

            // 优先级100: 第四执行
            @Filter("/api/**")
            @Order(100)
            public class CacheFilter implements HttpServerFilter {

                @Override
                public Publisher<MutableHttpResponse<?>> doFilter(
                    HttpRequest<?> request,
                    ServerFilterChain chain) {

                    System.out.println("4. CacheFilter: 缓存过滤器 (优先级100)");

                    // 检查缓存
                    String cacheKey = request.getPath();
                    Object cached = checkCache(cacheKey);

                    if (cached != null) {
                        System.out.println("   缓存命中");
                        return Flux.just(HttpResponse.ok(cached));
                    }

                    System.out.println("   缓存未命中,继续执行");
                    return chain.proceed(request);
                }

                private Object checkCache(String key) {
                    // 简化的缓存检查逻辑
                    return null;
                }
            }

            // 优先级最低: 最后执行
            @Filter("/api/**")
            @Order(Ordered.LOWEST_PRECEDENCE)
            public class LastFilter implements HttpServerFilter {

                @Override
                public Publisher<MutableHttpResponse<?>> doFilter(
                    HttpRequest<?> request,
                    ServerFilterChain chain) {

                    System.out.println("5. LastFilter: 最低优先级过滤器");
                    return chain.proceed(request);
                }
            }

            // 执行顺序示例输出:
            // 1. FirstFilter: 最高优先级过滤器
            // 2. AuthenticationFilter: 认证过滤器 (优先级-100)
            //    认证通过
            // 3. LoggingFilter: 日志过滤器 (默认优先级0)
            // 4. CacheFilter: 缓存过滤器 (优先级100)
            //    缓存未命中,继续执行
            // 5. LastFilter: 最低优先级过滤器
            // [Controller处理请求]
            //    请求耗时: 45ms
            ---

02.请求拦截
    a.请求修改
        a.修改请求内容
            过滤器可以修改请求的头部、参数、路径等信息,实现请求预处理、参数转换、请求重写等功能。通过创建新的MutableHttpRequest对象实现请求修改。
        b.请求修改示例
            ---
            @Filter("/api/**")
            public class RequestModificationFilter implements HttpServerFilter {

                @Override
                public Publisher<MutableHttpResponse<?>> doFilter(
                    HttpRequest<?> request,
                    ServerFilterChain chain) {

                    System.out.println("原始请求: " + request.getPath());

                    // 1. 添加请求头
                    MutableHttpRequest<?> modifiedRequest = request.mutate()
                        .header("X-Request-Id", UUID.randomUUID().toString())
                        .header("X-Processing-Time", String.valueOf(System.currentTimeMillis()))
                        .header("X-Client-IP", getClientIp(request));

                    System.out.println("添加请求头: X-Request-Id, X-Processing-Time, X-Client-IP");

                    // 2. 继续执行修改后的请求
                    return chain.proceed(modifiedRequest);
                }

                private String getClientIp(HttpRequest<?> request) {
                    // 获取客户端真实IP
                    String forwarded = request.getHeaders().get("X-Forwarded-For");
                    if (forwarded != null) {
                        return forwarded.split(",")[0].trim();
                    }
                    return request.getRemoteAddress().getAddress().getHostAddress();
                }
            }

            // 参数转换过滤器
            @Filter("/api/**")
            public class ParameterTransformFilter implements HttpServerFilter {

                @Override
                public Publisher<MutableHttpResponse<?>> doFilter(
                    HttpRequest<?> request,
                    ServerFilterChain chain) {

                    // 将查询参数转换为小写
                    MutableHttpRequest<?> modifiedRequest = request.mutate();

                    request.getParameters().forEach((key, values) -> {
                        List<String> lowercaseValues = values.stream()
                            .map(String::toLowerCase)
                            .collect(Collectors.toList());
                        System.out.println("参数转换: " + key + " = " + values + " → " + lowercaseValues);
                    });

                    return chain.proceed(modifiedRequest);
                }
            }

            // 用户上下文注入过滤器
            @Filter("/api/**")
            @Order(-50)
            public class UserContextFilter implements HttpServerFilter {
                private final JwtService jwtService;

                public UserContextFilter(JwtService jwtService) {
                    this.jwtService = jwtService;
                }

                @Override
                public Publisher<MutableHttpResponse<?>> doFilter(
                    HttpRequest<?> request,
                    ServerFilterChain chain) {

                    String authorization = request.getHeaders().get("Authorization");

                    if (authorization != null && authorization.startsWith("Bearer ")) {
                        String token = authorization.substring(7);

                        try {
                            // 解析JWT Token
                            UserInfo userInfo = jwtService.parseToken(token);

                            System.out.println("用户上下文: ID=" + userInfo.getId() +
                                             ", 用户名=" + userInfo.getUsername() +
                                             ", 角色=" + userInfo.getRoles());

                            // 将用户信息添加到请求属性中
                            MutableHttpRequest<?> modifiedRequest = request.mutate()
                                .header("X-User-Id", userInfo.getId().toString())
                                .header("X-Username", userInfo.getUsername())
                                .header("X-User-Roles", String.join(",", userInfo.getRoles()));

                            return chain.proceed(modifiedRequest);

                        } catch (Exception e) {
                            System.out.println("Token解析失败: " + e.getMessage());
                            return Flux.just(HttpResponse.unauthorized());
                        }
                    }

                    // 没有认证信息,继续执行
                    return chain.proceed(request);
                }
            }

            // 用户信息对象
            public class UserInfo {
                private Long id;
                private String username;
                private List<String> roles;

                public UserInfo(Long id, String username, List<String> roles) {
                    this.id = id;
                    this.username = username;
                    this.roles = roles;
                }

                // Getter省略
            }
            ---
    b.请求验证
        a.输入验证
            在过滤器中对请求进行验证,检查请求头、参数、内容类型等是否符合要求,实现统一的请求验证和安全防护。
        b.请求验证示例
            ---
            @Filter("/api/**")
            @Order(-200)
            public class RequestValidationFilter implements HttpServerFilter {

                @Override
                public Publisher<MutableHttpResponse<?>> doFilter(
                    HttpRequest<?> request,
                    ServerFilterChain chain) {

                    System.out.println("请求验证过滤器");

                    // 1. 验证Content-Type
                    if (request.getMethod().equals(HttpMethod.POST) ||
                        request.getMethod().equals(HttpMethod.PUT)) {

                        String contentType = request.getContentType().orElse(null);
                        if (contentType == null) {
                            System.out.println("验证失败: 缺少Content-Type");
                            ErrorResponse error = new ErrorResponse(
                                "INVALID_CONTENT_TYPE",
                                "POST/PUT请求必须指定Content-Type",
                                null
                            );
                            return Flux.just(HttpResponse.badRequest(error));
                        }
                    }

                    // 2. 验证必需的请求头
                    if (!request.getHeaders().contains("X-API-Version")) {
                        System.out.println("验证失败: 缺少X-API-Version头");
                        ErrorResponse error = new ErrorResponse(
                            "MISSING_API_VERSION",
                            "请求必须包含X-API-Version头",
                            null
                        );
                        return Flux.just(HttpResponse.badRequest(error));
                    }

                    // 3. 验证User-Agent
                    String userAgent = request.getHeaders().get("User-Agent");
                    if (userAgent == null || userAgent.isEmpty()) {
                        System.out.println("验证失败: 缺少User-Agent");
                        ErrorResponse error = new ErrorResponse(
                            "MISSING_USER_AGENT",
                            "请求必须包含User-Agent头",
                            null
                        );
                        return Flux.just(HttpResponse.badRequest(error));
                    }

                    // 4. 验证请求路径长度
                    if (request.getPath().length() > 2000) {
                        System.out.println("验证失败: URL过长");
                        ErrorResponse error = new ErrorResponse(
                            "URI_TOO_LONG",
                            "请求URL长度不能超过2000字符",
                            null
                        );
                        return Flux.just(
                            HttpResponse.status(HttpStatus.URI_TOO_LONG).body(error)
                        );
                    }

                    System.out.println("请求验证通过");
                    return chain.proceed(request);
                }
            }

            // SQL注入防护过滤器
            @Filter("/api/**")
            public class SqlInjectionFilter implements HttpServerFilter {

                private static final Pattern SQL_INJECTION_PATTERN =
                    Pattern.compile("('.*(or|and|union|select|insert|update|delete|drop|create|alter).*')",
                                  Pattern.CASE_INSENSITIVE);

                @Override
                public Publisher<MutableHttpResponse<?>> doFilter(
                    HttpRequest<?> request,
                    ServerFilterChain chain) {

                    // 检查查询参数中的SQL注入
                    for (Map.Entry<String, List<String>> entry : request.getParameters().asMap().entrySet()) {
                        for (String value : entry.getValue()) {
                            if (SQL_INJECTION_PATTERN.matcher(value).find()) {
                                System.out.println("SQL注入检测: 参数=" + entry.getKey() + ", 值=" + value);
                                ErrorResponse error = new ErrorResponse(
                                    "SQL_INJECTION_DETECTED",
                                    "检测到潜在的SQL注入攻击",
                                    "参数: " + entry.getKey()
                                );
                                return Flux.just(HttpResponse.badRequest(error));
                            }
                        }
                    }

                    return chain.proceed(request);
                }
            }

            // XSS防护过滤器
            @Filter("/api/**")
            public class XssFilter implements HttpServerFilter {

                private static final Pattern XSS_PATTERN =
                    Pattern.compile("<script[^>]*>.*?</script>|javascript:|onerror=|onclick=",
                                  Pattern.CASE_INSENSITIVE);

                @Override
                public Publisher<MutableHttpResponse<?>> doFilter(
                    HttpRequest<?> request,
                    ServerFilterChain chain) {

                    // 检查查询参数中的XSS攻击
                    for (Map.Entry<String, List<String>> entry : request.getParameters().asMap().entrySet()) {
                        for (String value : entry.getValue()) {
                            if (XSS_PATTERN.matcher(value).find()) {
                                System.out.println("XSS检测: 参数=" + entry.getKey());
                                ErrorResponse error = new ErrorResponse(
                                    "XSS_DETECTED",
                                    "检测到潜在的XSS攻击",
                                    "参数: " + entry.getKey()
                                );
                                return Flux.just(HttpResponse.badRequest(error));
                            }
                        }
                    }

                    return chain.proceed(request);
                }
            }
            ---

03.响应拦截
    a.响应修改
        a.修改响应内容
            过滤器可以修改响应的状态码、头部、响应体等信息,实现响应后处理、添加通用响应头、响应转换等功能。
        b.响应修改示例
            ---
            @Filter("/api/**")
            public class ResponseModificationFilter implements HttpServerFilter {

                @Override
                public Publisher<MutableHttpResponse<?>> doFilter(
                    HttpRequest<?> request,
                    ServerFilterChain chain) {

                    return Flux.from(chain.proceed(request))
                        .map(response -> {
                            System.out.println("修改响应");

                            // 1. 添加通用响应头
                            response.header("X-Powered-By", "Micronaut")
                                   .header("X-Response-Time", String.valueOf(System.currentTimeMillis()))
                                   .header("X-Server-Region", "us-west-1");

                            // 2. 添加CORS头
                            response.header("Access-Control-Allow-Origin", "*")
                                   .header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
                                   .header("Access-Control-Allow-Headers", "Content-Type, Authorization")
                                   .header("Access-Control-Max-Age", "3600");

                            // 3. 添加安全头
                            response.header("X-Content-Type-Options", "nosniff")
                                   .header("X-Frame-Options", "DENY")
                                   .header("X-XSS-Protection", "1; mode=block")
                                   .header("Strict-Transport-Security", "max-age=31536000; includeSubDomains");

                            System.out.println("响应头已添加");
                            return response;
                        });
                }
            }

            // 响应压缩标记过滤器
            @Filter("/api/**")
            public class CompressionFilter implements HttpServerFilter {

                @Override
                public Publisher<MutableHttpResponse<?>> doFilter(
                    HttpRequest<?> request,
                    ServerFilterChain chain) {

                    String acceptEncoding = request.getHeaders().get("Accept-Encoding");

                    return Flux.from(chain.proceed(request))
                        .map(response -> {
                            // 如果客户端支持gzip压缩
                            if (acceptEncoding != null && acceptEncoding.contains("gzip")) {
                                // 获取响应体大小
                                Object body = response.body();
                                if (body != null) {
                                    String bodyStr = body.toString();
                                    if (bodyStr.length() > 1024) {
                                        // 响应体大于1KB,标记为可压缩
                                        response.header("Content-Encoding", "gzip");
                                        System.out.println("响应将被压缩: 原始大小=" + bodyStr.length());
                                    }
                                }
                            }
                            return response;
                        });
                }
            }

            // 响应缓存过滤器
            @Filter("/api/**")
            public class CacheResponseFilter implements HttpServerFilter {

                @Override
                public Publisher<MutableHttpResponse<?>> doFilter(
                    HttpRequest<?> request,
                    ServerFilterChain chain) {

                    return Flux.from(chain.proceed(request))
                        .map(response -> {
                            // 只缓存成功的GET请求
                            if (request.getMethod().equals(HttpMethod.GET) &&
                                response.getStatus().equals(HttpStatus.OK)) {

                                String path = request.getPath();

                                // 根据路径设置不同的缓存策略
                                if (path.startsWith("/api/public/")) {
                                    // 公共资源,缓存1小时
                                    response.header("Cache-Control", "public, max-age=3600");
                                    System.out.println("公共资源缓存: 1小时");

                                } else if (path.startsWith("/api/static/")) {
                                    // 静态资源,缓存1天
                                    response.header("Cache-Control", "public, max-age=86400");
                                    System.out.println("静态资源缓存: 1天");

                                } else {
                                    // 私有资源,不缓存
                                    response.header("Cache-Control", "private, no-cache, no-store, must-revalidate");
                                    System.out.println("私有资源: 禁止缓存");
                                }

                                // 添加ETag
                                String etag = generateETag(response.body());
                                response.header("ETag", etag);
                            }

                            return response;
                        });
                }

                private String generateETag(Object body) {
                    // 简化的ETag生成逻辑
                    if (body != null) {
                        return "W/\"" + body.hashCode() + "\"";
                    }
                    return "W/\"empty\"";
                }
            }

            // 统一响应包装过滤器
            @Filter("/api/**")
            @Order(200)
            public class ResponseWrapperFilter implements HttpServerFilter {

                @Override
                public Publisher<MutableHttpResponse<?>> doFilter(
                    HttpRequest<?> request,
                    ServerFilterChain chain) {

                    return Flux.from(chain.proceed(request))
                        .map(response -> {
                            // 只包装成功的响应
                            if (response.getStatus().getCode() >= 200 &&
                                response.getStatus().getCode() < 300) {

                                Object originalBody = response.body();

                                // 创建统一响应格式
                                ApiResponse<?> wrappedResponse = new ApiResponse<>(
                                    200,
                                    "success",
                                    originalBody,
                                    System.currentTimeMillis()
                                );

                                System.out.println("响应已包装为统一格式");
                                return response.body(wrappedResponse);
                            }

                            return response;
                        });
                }
            }

            // 统一响应格式
            public class ApiResponse<T> {
                private int code;
                private String message;
                private T data;
                private long timestamp;

                public ApiResponse(int code, String message, T data, long timestamp) {
                    this.code = code;
                    this.message = message;
                    this.data = data;
                    this.timestamp = timestamp;
                }

                // Getter省略
            }
            ---
    b.性能监控
        a.请求度量
            通过过滤器收集请求处理时间、响应大小、错误率等性能指标,实现请求监控和性能分析。
        b.性能监控示例
            ---
            import java.util.concurrent.ConcurrentHashMap;
            import java.util.concurrent.atomic.AtomicLong;

            @Singleton
            @Filter("/api/**")
            @Order(-500)
            public class PerformanceMonitorFilter implements HttpServerFilter {

                // 请求计数器
                private final AtomicLong requestCount = new AtomicLong(0);
                private final AtomicLong errorCount = new AtomicLong(0);

                // 路径统计
                private final ConcurrentHashMap<String, PathStats> pathStatsMap = new ConcurrentHashMap<>();

                @Override
                public Publisher<MutableHttpResponse<?>> doFilter(
                    HttpRequest<?> request,
                    ServerFilterChain chain) {

                    long requestId = requestCount.incrementAndGet();
                    long startTime = System.currentTimeMillis();
                    String path = request.getPath();
                    String method = request.getMethod().name();
                    String key = method + " " + path;

                    System.out.println("=== 请求 #" + requestId + " 开始 ===");
                    System.out.println(method + " " + path);

                    return Flux.from(chain.proceed(request))
                        .doOnNext(response -> {
                            // 请求成功
                            long duration = System.currentTimeMillis() - startTime;

                            // 更新统计信息
                            PathStats stats = pathStatsMap.computeIfAbsent(key, k -> new PathStats());
                            stats.incrementCount();
                            stats.addDuration(duration);

                            // 计算响应大小
                            long responseSize = calculateResponseSize(response);
                            stats.addResponseSize(responseSize);

                            System.out.println("状态: " + response.getStatus().getCode());
                            System.out.println("耗时: " + duration + "ms");
                            System.out.println("响应大小: " + responseSize + " bytes");
                            System.out.println("平均耗时: " + stats.getAverageDuration() + "ms");
                            System.out.println("=== 请求 #" + requestId + " 完成 ===\n");

                            // 添加性能头到响应
                            response.header("X-Response-Time", duration + "ms")
                                   .header("X-Request-Id", String.valueOf(requestId));
                        })
                        .doOnError(error -> {
                            // 请求失败
                            long duration = System.currentTimeMillis() - startTime;
                            errorCount.incrementAndGet();

                            PathStats stats = pathStatsMap.computeIfAbsent(key, k -> new PathStats());
                            stats.incrementErrorCount();

                            System.err.println("请求失败 #" + requestId);
                            System.err.println("错误: " + error.getMessage());
                            System.err.println("耗时: " + duration + "ms");
                            System.err.println("=== 请求 #" + requestId + " 失败 ===\n");
                        });
                }

                private long calculateResponseSize(MutableHttpResponse<?> response) {
                    Object body = response.body();
                    if (body == null) {
                        return 0;
                    }
                    if (body instanceof byte[]) {
                        return ((byte[]) body).length;
                    }
                    if (body instanceof String) {
                        return ((String) body).length();
                    }
                    // 估算JSON序列化后的大小
                    return body.toString().length();
                }

                // 获取统计信息的端点
                @Get("/api/stats")
                public Map<String, Object> getStats() {
                    Map<String, Object> stats = new HashMap<>();
                    stats.put("totalRequests", requestCount.get());
                    stats.put("totalErrors", errorCount.get());
                    stats.put("errorRate", String.format("%.2f",
                                     (usedMemory * 100.0 / maxMemory)));
                }

                // 对比传统JPA
                public void compareWithTraditionalJPA() {
                    System.out.println("\n=== Micronaut Data vs 传统JPA ===");
                    System.out.println("\nMicronaut Data优势:");
                    System.out.println("1. 编译时生成 - 无运行时反射");
                    System.out.println("2. 更快的启动速度 - 通常快50-90%");
                    System.out.println("3. 更低的内存占用 - 减少30-50%");
                    System.out.println("4. 更小的应用体积 - 减少依赖");
                    System.out.println("5. AOT编译友好 - 支持GraalVM Native Image");

                    System.out.println("\n传统JPA特点:");
                    System.out.println("1. 运行时生成代理 - 使用反射");
                    System.out.println("2. 较慢的启动速度 - 需要初始化EntityManager");
                    System.out.println("3. 较高的内存占用 - 代理和缓存开销");
                    System.out.println("4. 成熟的生态系统 - 更多工具和集成");
                }
            }

            // 性能测试输出示例
            // === 启动性能测试 ===
            // 启动时间: 1200ms
            // Bean数量: 245
            //
            // === 查询性能测试 ===
            // findAll() x1000: 450ms
            // 平均: 0.45ms
            //
            // findByUsername() x1000: 520ms
            // 平均: 0.52ms
            //
            // save() x100: 180ms
            // 平均: 1.8ms
            //
            // === 内存占用测试 ===
            // 已用内存: 128 MB
            // 最大内存: 512 MB
            // 使用率: 25.00%
            ---

02.支持的数据库
    a.关系型数据库
        a.主流数据库支持
            Micronaut Data支持MySQL、PostgreSQL、Oracle、SQL Server、H2等主流关系型数据库,通过JDBC或R2DBC访问。提供数据库方言自动适配,简化多数据库支持。
        b.多数据库配置示例
            ---
            // application.yml - 多数据源配置
            datasources:
              # 主数据源 - MySQL
              default:
                url: jdbc:mysql://localhost:3306/app_db
                driverClassName: com.mysql.cj.jdbc.Driver
                username: root
                password: ${DB_PASSWORD}
                dialect: MYSQL
                maximum-pool-size: 10
                minimum-idle: 2

              # 从数据源 - PostgreSQL
              analytics:
                url: jdbc:postgresql://localhost:5432/analytics_db
                driverClassName: org.postgresql.Driver
                username: analytics_user
                password: ${ANALYTICS_DB_PASSWORD}
                dialect: POSTGRES
                maximum-pool-size: 5

              # H2内存数据库 - 用于测试
              test:
                url: jdbc:h2:mem:testDb
                driverClassName: org.h2.Driver
                username: sa
                password: ''
                dialect: H2

            jpa:
              default:
                properties:
                  hibernate:
                    hbm2ddl:
                      auto: update
                    show_sql: true

            // MySQL实体示例
            @Entity
            @Table(name = "products")
            public class Product {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                @Column(nullable = false, length = 100)
                private String name;

                @Column(precision = 10, scale = 2)
                private BigDecimal price;

                @Column(columnDefinition = "TEXT")
                private String description;

                @Column(name = "created_at", columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
                private LocalDateTime createdAt;

                // Getter和Setter省略
            }

            // MySQL Repository
            @Repository
            public interface ProductRepository extends JpaRepository<Product, Long> {
                @Query("SELECT p FROM Product p WHERE p.price BETWEEN :minPrice AND :maxPrice")
                List<Product> findByPriceRange(
                    @Param("minPrice") BigDecimal minPrice,
                    @Param("maxPrice") BigDecimal maxPrice
                );

                @Query("SELECT p FROM Product p WHERE LOWER(p.name) LIKE LOWER(CONCAT('%', :keyword, '%'))")
                List<Product> searchByName(@Param("keyword") String keyword);
            }

            // PostgreSQL实体示例
            @Entity
            @Table(name = "analytics_events")
            public class AnalyticsEvent {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                @Column(name = "event_type", nullable = false)
                private String eventType;

                @Column(name = "user_id")
                private Long userId;

                @Column(columnDefinition = "jsonb")
                private String properties;  // PostgreSQL JSON类型

                @Column(name = "occurred_at", nullable = false)
                private LocalDateTime occurredAt;

                // Getter和Setter省略
            }

            // PostgreSQL Repository - 使用特定数据源
            @Repository("analytics")
            @JdbcRepository(dialect = Dialect.POSTGRES)
            public interface AnalyticsEventRepository extends CrudRepository<AnalyticsEvent, Long> {
                @Query("SELECT * FROM analytics_events WHERE occurred_at >= :startDate " +
                       "AND occurred_at < :endDate ORDER BY occurred_at DESC")
                List<AnalyticsEvent> findEventsByDateRange(
                    LocalDateTime startDate,
                    LocalDateTime endDate
                );

                @Query("SELECT event_type, COUNT(*) as count FROM analytics_events " +
                       "WHERE occurred_at >= :date GROUP BY event_type")
                List<Map<String, Object>> getEventCountsByType(LocalDateTime date);
            }

            // 多数据源服务
            @Singleton
            public class MultiDataSourceService {
                private final ProductRepository productRepository;
                private final AnalyticsEventRepository analyticsRepository;

                public MultiDataSourceService(ProductRepository productRepository,
                                            AnalyticsEventRepository analyticsRepository) {
                    this.productRepository = productRepository;
                    this.analyticsRepository = analyticsRepository;
                    System.out.println("多数据源服务初始化");
                }

                @Transactional("default")  // 使用主数据源事务
                public Product createProduct(String name, BigDecimal price) {
                    System.out.println("创建产品: " + name);

                    Product product = new Product();
                    product.setName(name);
                    product.setPrice(price);
                    product.setCreatedAt(LocalDateTime.now());

                    Product saved = productRepository.save(product);

                    // 记录分析事件到PostgreSQL
                    recordAnalyticsEvent("product_created", saved.getId());

                    return saved;
                }

                @Transactional("analytics")  // 使用分析数据源事务
                public void recordAnalyticsEvent(String eventType, Long entityId) {
                    System.out.println("记录分析事件: " + eventType);

                    AnalyticsEvent event = new AnalyticsEvent();
                    event.setEventType(eventType);
                    event.setUserId(entityId);
                    event.setOccurredAt(LocalDateTime.now());
                    event.setProperties("{\"entity_id\": " + entityId + "}");

                    analyticsRepository.save(event);
                }

                public List<Product> searchProducts(String keyword) {
                    System.out.println("搜索产品: " + keyword);
                    return productRepository.searchByName(keyword);
                }

                public Map<String, Object> getAnalyticsSummary(LocalDateTime startDate) {
                    System.out.println("获取分析摘要");

                    List<Map<String, Object>> eventCounts =
                        analyticsRepository.getEventCountsByType(startDate);

                    Map<String, Object> summary = new HashMap<>();
                    summary.put("startDate", startDate);
                    summary.put("eventCounts", eventCounts);
                    summary.put("generatedAt", LocalDateTime.now());

                    return summary;
                }
            }

            // 数据库方言特定功能
            @Singleton
            public class DatabaseDialectService {

                // MySQL特定 - 全文搜索
                @Query(value = "SELECT * FROM products WHERE MATCH(name, description) " +
                              "AGAINST(:keyword IN NATURAL LANGUAGE MODE)",
                       nativeQuery = true)
                public List<Product> fullTextSearch(String keyword) {
                    // MySQL全文搜索功能
                    return Collections.emptyList();
                }

                // PostgreSQL特定 - 数组操作
                @Query(value = "SELECT * FROM users WHERE :tag = ANY(tags)",
                       nativeQuery = true)
                public List<User> findByTag(String tag) {
                    // PostgreSQL数组查询
                    return Collections.emptyList();
                }

                // Oracle特定 - 分页查询
                @Query(value = "SELECT * FROM (SELECT a.*, ROWNUM rnum FROM " +
                              "(SELECT * FROM products ORDER BY id) a WHERE ROWNUM <= :end) " +
                              "WHERE rnum > :start",
                       nativeQuery = true)
                public List<Product> findWithOraclePagination(int start, int end) {
                    // Oracle特定分页
                    return Collections.emptyList();
                }
            }
            ---
    b.NoSQL支持
        a.MongoDB集成
            通过Micronaut Data MongoDB模块支持MongoDB,提供与关系型数据库相同的Repository抽象。支持文档映射、查询构建、聚合操作等MongoDB特性。
        b.MongoDB配置示例
            ---
            // build.gradle - MongoDB依赖
            dependencies {
                annotationProcessor("io.micronaut.data:micronaut-data-processor")
                implementation("io.micronaut.data:micronaut-data-mongodb")
                runtimeOnly("org.mongodb:mongodb-driver-sync")
            }

            // application.yml - MongoDB配置
            mongodb:
              uri: mongodb://localhost:27017/mydb
              package-names:
                - com.example.domain

            // MongoDB文档实体
            import io.micronaut.data.mongodb.annotation.MongoRepository;
            import org.bson.types.ObjectId;
            import io.micronaut.data.annotation.Id;
            import io.micronaut.data.annotation.MappedEntity;

            @MappedEntity
            public class Article {
                @Id
                private ObjectId id;

                private String title;
                private String content;
                private String author;
                private List<String> tags;
                private LocalDateTime publishedAt;
                private int viewCount;
                private Map<String, Object> metadata;

                // 构造函数
                public Article() {}

                public Article(String title, String content, String author) {
                    this.title = title;
                    this.content = content;
                    this.author = author;
                    this.tags = new ArrayList<>();
                    this.publishedAt = LocalDateTime.now();
                    this.viewCount = 0;
                    this.metadata = new HashMap<>();
                }

                // Getter和Setter
                public ObjectId getId() { return id; }
                public void setId(ObjectId id) { this.id = id; }

                public String getTitle() { return title; }
                public void setTitle(String title) { this.title = title; }

                public String getContent() { return content; }
                public void setContent(String content) { this.content = content; }

                public String getAuthor() { return author; }
                public void setAuthor(String author) { this.author = author; }

                public List<String> getTags() { return tags; }
                public void setTags(List<String> tags) { this.tags = tags; }

                public LocalDateTime getPublishedAt() { return publishedAt; }
                public void setPublishedAt(LocalDateTime publishedAt) { this.publishedAt = publishedAt; }

                public int getViewCount() { return viewCount; }
                public void setViewCount(int viewCount) { this.viewCount = viewCount; }

                public Map<String, Object> getMetadata() { return metadata; }
                public void setMetadata(Map<String, Object> metadata) { this.metadata = metadata; }
            }

            // MongoDB Repository
            @MongoRepository
            public interface ArticleRepository extends CrudRepository<Article, ObjectId> {
                // 方法名查询
                List<Article> findByAuthor(String author);

                List<Article> findByTitleContaining(String keyword);

                List<Article> findByPublishedAtAfter(LocalDateTime date);

                List<Article> findByViewCountGreaterThan(int count);

                // 自定义查询
                @Query("{\"tags\": {\"$in\": :tags}}")
                List<Article> findByTags(List<String> tags);

                @Query("{\"author\": :author, \"publishedAt\": {\"$gte\": :startDate, \"$lt\": :endDate}}")
                List<Article> findByAuthorAndDateRange(
                    String author,
                    LocalDateTime startDate,
                    LocalDateTime endDate
                );

                // 聚合查询
                @Query(value = "{\"$group\": {\"_id\": \"$author\", \"count\": {\"$sum\": 1}}}")
                List<Map<String, Object>> countArticlesByAuthor();

                // 更新操作
                @Query(value = "{\"_id\": :id}",
                       update = "{\"$inc\": {\"viewCount\": 1}}")
                void incrementViewCount(ObjectId id);
            }

            // MongoDB服务
            @Singleton
            public class ArticleService {
                private final ArticleRepository articleRepository;

                public ArticleService(ArticleRepository articleRepository) {
                    this.articleRepository = articleRepository;
                    System.out.println("ArticleService初始化");
                }

                public Article createArticle(String title, String content, String author) {
                    System.out.println("创建文章: " + title);

                    Article article = new Article(title, content, author);
                    Article saved = articleRepository.save(article);

                    System.out.println("文章已保存, ID: " + saved.getId());
                    return saved;
                }

                public void addTags(ObjectId articleId, List<String> tags) {
                    System.out.println("添加标签: " + tags);

                    Optional<Article> optionalArticle = articleRepository.findById(articleId);
                    if (optionalArticle.isPresent()) {
                        Article article = optionalArticle.get();
                        article.getTags().addAll(tags);
                        articleRepository.update(article);
                        System.out.println("标签已添加");
                    }
                }

                public List<Article> findByTags(List<String> tags) {
                    System.out.println("按标签查询: " + tags);
                    return articleRepository.findByTags(tags);
                }

                public void incrementViewCount(ObjectId articleId) {
                    System.out.println("增加浏览次数: " + articleId);
                    articleRepository.incrementViewCount(articleId);
                }

                public List<Article> getPopularArticles(int minViews) {
                    System.out.println("查询热门文章 (浏览 > " + minViews + ")");
                    return articleRepository.findByViewCountGreaterThan(minViews);
                }

                public Map<String, Long> getArticleCountByAuthor() {
                    System.out.println("统计作者文章数");

                    List<Map<String, Object>> results = articleRepository.countArticlesByAuthor();
                    Map<String, Long> counts = new HashMap<>();

                    for (Map<String, Object> result : results) {
                        String author = (String) result.get("_id");
                        Number count = (Number) result.get("count");
                        counts.put(author, count.longValue());
                    }

                    return counts;
                }
            }

            // MongoDB控制器
            @Controller("/api/articles")
            public class ArticleController {
                private final ArticleService articleService;

                public ArticleController(ArticleService articleService) {
                    this.articleService = articleService;
                }

                @Post
                public Article create(@Body CreateArticleRequest request) {
                    return articleService.createArticle(
                        request.getTitle(),
                        request.getContent(),
                        request.getAuthor()
                    );
                }

                @Post("/{id}/tags")
                public void addTags(String id, @Body List<String> tags) {
                    articleService.addTags(new ObjectId(id), tags);
                }

                @Get("/tags")
                public List<Article> findByTags(@QueryValue List<String> tags) {
                    return articleService.findByTags(tags);
                }

                @Get("/popular")
                public List<Article> getPopular(
                    @QueryValue(defaultValue = "100") int minViews) {
                    return articleService.getPopularArticles(minViews);
                }

                @Get("/stats/authors")
                public Map<String, Long> getAuthorStats() {
                    return articleService.getArticleCountByAuthor();
                }
            }

            // 请求对象
            public class CreateArticleRequest {
                private String title;
                private String content;
                private String author;

                // Getter和Setter省略
            }
            ---

03.查询方法
    a.方法名派生
        a.命名规范
            根据方法名自动生成查询实现,支持丰富的关键字如findBy、countBy、deleteBy、existsBy等。支持And、Or、Between、LessThan、GreaterThan等条件组合。
        b.方法名查询示例
            ---
            @Repository
            public interface UserRepository extends JpaRepository<User, Long> {

                // === 基础查询 ===

                // 按单个字段查询
                Optional<User> findByUsername(String username);
                List<User> findByEmail(String email);

                // 查询所有
                List<User> findByActive(boolean active);

                // 计数
                long countByActive(boolean active);
                long countByCreatedAtAfter(LocalDateTime date);

                // 存在性检查
                boolean existsByUsername(String username);
                boolean existsByEmail(String email);

                // 删除
                void deleteByUsername(String username);
                long deleteByActiveAndCreatedAtBefore(boolean active, LocalDateTime date);

                // === 条件组合 ===

                // And条件
                Optional<User> findByUsernameAndEmail(String username, String email);
                List<User> findByActiveAndCreatedAtAfter(boolean active, LocalDateTime date);

                // Or条件
                List<User> findByUsernameOrEmail(String username, String email);
                List<User> findByActiveOrVerified(boolean active, boolean verified);

                // === 比较操作 ===

                // 大于/小于
                List<User> findByAgeGreaterThan(int age);
                List<User> findByAgeLessThan(int age);
                List<User> findByAgeGreaterThanEqual(int age);
                List<User> findByAgeLessThanEqual(int age);

                // Between
                List<User> findByAgeBetween(int minAge, int maxAge);
                List<User> findByCreatedAtBetween(LocalDateTime start, LocalDateTime end);

                // === 字符串操作 ===

                // Like
                List<User> findByUsernameLike(String pattern);
                List<User> findByEmailContaining(String emailPart);
                List<User> findByUsernameStartingWith(String prefix);
                List<User> findByUsernameEndingWith(String suffix);

                // IgnoreCase
                Optional<User> findByUsernameIgnoreCase(String username);
                List<User> findByEmailContainingIgnoreCase(String emailPart);

                // === 空值处理 ===

                List<User> findByPhoneIsNull();
                List<User> findByPhoneIsNotNull();

                // === 集合操作 ===

                List<User> findByIdIn(List<Long> ids);
                List<User> findByUsernameIn(Collection<String> usernames);
                List<User> findByIdNotIn(List<Long> ids);

                // === 排序 ===

                List<User> findByActiveOrderByCreatedAtDesc(boolean active);
                List<User> findByActiveOrderByUsernameAscCreatedAtDesc(boolean active);

                // === 分页和限制 ===

                // 限制结果数量
                List<User> findTop10ByActive(boolean active);
                List<User> findFirst5ByActiveOrderByCreatedAtDesc(boolean active);

                // 使用Pageable分页
                Page<User> findByActive(boolean active, Pageable pageable);
                Slice<User> findByEmailContaining(String emailPart, Pageable pageable);

                // === 投��查询 ===

                // 只查询特定字段
                List<String> findUsernameByActive(boolean active);
                List<UserProjection> findProjectionByActive(boolean active);

                // === Distinct ===

                List<String> findDistinctEmailByActive(boolean active);

                // === 复杂组合示例 ===

                List<User> findByActiveAndAgeBetweenAndEmailContainingIgnoreCaseOrderByCreatedAtDesc(
                    boolean active,
                    int minAge,
                    int maxAge,
                    String emailPart
                );

                List<User> findTop10ByActiveOrVerifiedAndCreatedAtAfterOrderByUsernameAsc(
                    boolean active,
                    boolean verified,
                    LocalDateTime date
                );
            }

            // 投影接口
            public interface UserProjection {
                String getUsername();
                String getEmail();
                LocalDateTime getCreatedAt();
            }

            // 使用示例
            @Singleton
            public class QueryMethodService {
                private final UserRepository userRepository;

                public QueryMethodService(UserRepository userRepository) {
                    this.userRepository = userRepository;
                }

                public void demonstrateQueryMethods() {
                    System.out.println("=== 查询方法演示 ===\n");

                    // 基础查询
                    System.out.println("1. 按用户名查询:");
                    Optional<User> user = userRepository.findByUsername("john");
                    user.ifPresent(u -> System.out.println("  找到: " + u));

                    // 条件组合
                    System.out.println("\n2. And条件查询:");
                    LocalDateTime cutoffDate = LocalDateTime.now().minusDays(30);
                    List<User> activeUsers = userRepository.findByActiveAndCreatedAtAfter(
                        true, cutoffDate
                    );
                    System.out.println("  找到 " + activeUsers.size() + " 个活跃用户");

                    // 字符串模糊查询
                    System.out.println("\n3. 邮箱模糊查询:");
                    List<User> gmailUsers = userRepository.findByEmailContaining("gmail");
                    System.out.println("  找到 " + gmailUsers.size() + " 个Gmail用户");

                    // 范围查询
                    System.out.println("\n4. 年龄范围查询:");
                    List<User> adults = userRepository.findByAgeBetween(18, 65);
                    System.out.println("  找到 " + adults.size() + " 个成年用户");

                    // 排序查询
                    System.out.println("\n5. 排序查询:");
                    List<User> sortedUsers = userRepository
                        .findByActiveOrderByCreatedAtDesc(true);
                    System.out.println("  按时间倒序查询到 " + sortedUsers.size() + " 个用户");

                    // 分页查询
                    System.out.println("\n6. 分页查询:");
                    Pageable pageable = Pageable.from(0, 10);
                    Page<User> page = userRepository.findByActive(true, pageable);
                    System.out.println("  第1页: " + page.getContent().size() + " 个用户");
                    System.out.println("  总数: " + page.getTotalSize());
                    System.out.println("  总页数: " + page.getTotalPages());

                    // 限制结果
                    System.out.println("\n7. Top N查询:");
                    List<User> topUsers = userRepository
                        .findTop10ByActive(true);
                    System.out.println("  查询到前 " + topUsers.size() + " 个用户");

                    // 存在性检查
                    System.out.println("\n8. 存在性检查:");
                    boolean exists = userRepository.existsByUsername("admin");
                    System.out.println("  admin用户" + (exists ? "存在" : "不存在"));

                    // 计数
                    System.out.println("\n9. 计数查询:");
                    long count = userRepository.countByActive(true);
                    System.out.println("  活跃用户数: " + count);
                }
            }

            // 查询方法命名规则总结
            // 前缀: find, read, get, query, search, stream
            // 条件: By + 字段名 + 操作符
            // 操作符:
            //   - 相等: 无后缀 (findByName)
            //   - Like: Like, Containing, StartingWith, EndingWith
            //   - 比较: GreaterThan, LessThan, Between
            //   - 空值: IsNull, IsNotNull
            //   - 集合: In, NotIn
            //   - 逻辑: And, Or
            //   - 忽略大小写: IgnoreCase
            // 排序: OrderBy + 字段名 + Asc/Desc
            // 限制: Top/First + 数字
            ---
    b.@Query注解
        a.自定义查询
            使用@Query注解编写JPQL或原生SQL查询,实现复杂查询逻辑。支持命名参数、位置参数、动态查询等,提供更灵活的查询能力。
        b.自定义查询示例
            ---
            @Repository
            public interface AdvancedUserRepository extends JpaRepository<User, Long> {

                // === JPQL查询 ===

                // 基础JPQL
                @Query("SELECT u FROM User u WHERE u.username = :username")
                Optional<User> findUserByUsername(@Param("username") String username);

                @Query("SELECT u FROM User u WHERE u.active = :active ORDER BY u.createdAt DESC")
                List<User> findActiveUsers(@Param("active") boolean active);

                // 联接查询
                @Query("SELECT u FROM User u LEFT JOIN FETCH u.roles WHERE u.id = :id")
                Optional<User> findUserWithRoles(@Param("id") Long id);

                @Query("SELECT u FROM User u JOIN u.orders o WHERE o.status = :status")
                List<User> findUsersWithOrderStatus(@Param("status") String status);

                // 聚合查询
                @Query("SELECT COUNT(u) FROM User u WHERE u.createdAt >= :date")
                long countNewUsers(@Param("date") LocalDateTime date);

                @Query("SELECT u.department, COUNT(u) FROM User u GROUP BY u.department")
                List<Object[]> countUsersByDepartment();

                // 子查询
                @Query("SELECT u FROM User u WHERE u.id IN " +
                       "(SELECT o.userId FROM Order o WHERE o.total > :amount)")
                List<User> findUsersWithLargeOrders(@Param("amount") BigDecimal amount);

                // === 原生SQL查询 ===

                @Query(value = "SELECT * FROM users WHERE username LIKE CONCAT(:prefix, '%')",
                       nativeQuery = true)
                List<User> findByUsernamePrefix(@Param("prefix") String prefix);

                @Query(value = "SELECT u.*, COUNT(o.id) as order_count FROM users u " +
                              "LEFT JOIN orders o ON u.id = o.user_id " +
                              "GROUP BY u.id HAVING COUNT(o.id) > :minOrders",
                       nativeQuery = true)
                List<Object[]> findUsersWithMinOrders(@Param("minOrders") int minOrders);

                // 数据库特定功能
                @Query(value = "SELECT * FROM users WHERE MATCH(username, email) " +
                              "AGAINST(:keyword IN BOOLEAN MODE)",
                       nativeQuery = true)
                List<User> fullTextSearch(@Param("keyword") String keyword);

                // === 修改查询 ===

                @Modifying
                @Query("UPDATE User u SET u.active = :active WHERE u.lastLoginAt < :date")
                int deactivateInactiveUsers(
                    @Param("active") boolean active,
                    @Param("date") LocalDateTime date
                );

                @Modifying
                @Query("DELETE FROM User u WHERE u.active = false AND u.createdAt < :date")
                int deleteInactiveUsers(@Param("date") LocalDateTime date);

                @Modifying
                @Query("UPDATE User u SET u.loginCount = u.loginCount + 1, " +
                       "u.lastLoginAt = :now WHERE u.id = :id")
                void updateLoginInfo(@Param("id") Long id, @Param("now") LocalDateTime now);

                // === 动态查询 ===

                @Query("SELECT u FROM User u WHERE " +
                       "(:username IS NULL OR u.username LIKE CONCAT('%', :username, '%')) AND " +
                       "(:email IS NULL OR u.email LIKE CONCAT('%', :email, '%')) AND " +
                       "(:active IS NULL OR u.active = :active)")
                List<User> dynamicSearch(
                    @Param("username") @Nullable String username,
                    @Param("email") @Nullable String email,
                    @Param("active") @Nullable Boolean active
                );

                // === 投影查询 ===

                @Query("SELECT new map(u.username as username, u.email as email, " +
                       "u.createdAt as createdAt) FROM User u WHERE u.active = true")
                List<Map<String, Object>> findActiveUserProjections();

                @Query("SELECT u.username FROM User u WHERE u.department = :dept")
                List<String> findUsernamesByDepartment(@Param("dept") String department);

                // DTO投影
                @Query("SELECT new com.example.dto.UserSummaryDTO(u.id, u.username, u.email) " +
                       "FROM User u WHERE u.active = true")
                List<UserSummaryDTO> findUserSummaries();

                // === 分页查询 ===

                @Query("SELECT u FROM User u WHERE u.department = :dept ORDER BY u.createdAt DESC")
                Page<User> findByDepartment(@Param("dept") String department, Pageable pageable);

                @Query(value = "SELECT * FROM users WHERE department = :dept",
                       countQuery = "SELECT COUNT(*) FROM users WHERE department = :dept",
                       nativeQuery = true)
                Page<User> findByDepartmentNative(@Param("dept") String department, Pageable pageable);

                // === 命名参数 vs 位置参数 ===

                // 命名参数 (推荐)
                @Query("SELECT u FROM User u WHERE u.username = :username AND u.email = :email")
                Optional<User> findByUsernameAndEmail(
                    @Param("username") String username,
                    @Param("email") String email
                );

                // 位置参数
                @Query("SELECT u FROM User u WHERE u.username = ?1 AND u.email = ?2")
                Optional<User> findByUsernameAndEmailPositional(String username, String email);

                // === 集合参数 ===

                @Query("SELECT u FROM User u WHERE u.id IN :ids")
                List<User> findByIds(@Param("ids") List<Long> ids);

                @Query("SELECT u FROM User u WHERE u.role IN :roles AND u.active = true")
                List<User> findByRoles(@Param("roles") Collection<String> roles);
            }

            // DTO对象
            public class UserSummaryDTO {
                private Long id;
                private String username;
                private String email;

                public UserSummaryDTO(Long id, String username, String email) {
                    this.id = id;
                    this.username = username;
                    this.email = email;
                }

                // Getter省略
            }

            // 使用示例
            @Singleton
            public class CustomQueryService {
                private final AdvancedUserRepository userRepository;

                public CustomQueryService(AdvancedUserRepository userRepository) {
                    this.userRepository = userRepository;
                }

                public void demonstrateCustomQueries() {
                    System.out.println("=== 自定义查询演示 ===\n");

                    // JPQL查询
                    System.out.println("1. JPQL查询:");
                    List<User> activeUsers = userRepository.findActiveUsers(true);
                    System.out.println("  找到 " + activeUsers.size() + " 个活跃用户");

                    // 聚合查询
                    System.out.println("\n2. 聚合查询:");
                    List<Object[]> deptCounts = userRepository.countUsersByDepartment();
                    deptCounts.forEach(row ->
                        System.out.println("  " + row[0] + ": " + row[1] + " 人")
                    );

                    // 动态查���
                    System.out.println("\n3. 动态查询:");
                    List<User> searchResults = userRepository.dynamicSearch(
                        "john",
                        null,
                        true
                    );
                    System.out.println("  找到 " + searchResults.size() + " 个匹配用户");

                    // 投影查询
                    System.out.println("\n4. 投影查询:");
                    List<UserSummaryDTO> summaries = userRepository.findUserSummaries();
                    System.out.println("  查询到 " + summaries.size() + " 个用户摘要");

                    // 修改查询
                    System.out.println("\n5. 批量更新:");
                    LocalDateTime cutoffDate = LocalDateTime.now().minusMonths(6);
                    int deactivated = userRepository.deactivateInactiveUsers(false, cutoffDate);
                    System.out.println("  停用了 " + deactivated + " 个不活跃用户");

                    // 分页查询
                    System.out.println("\n6. 分页查询:");
                    Pageable pageable = Pageable.from(0, 10);
                    Page<User> page = userRepository.findByDepartment("Engineering", pageable);
                    System.out.println("  第1页: " + page.getContent().size() + " 个用户");
                    System.out.println("  总数: " + page.getTotalSize());
                }
            }
            ---

5.2 Repository模式

01.Repository接口
    a.CrudRepository
        a.基础CRUD操作
            CrudRepository提供基本的增删改查操作,包括save、findById、findAll、delete等方法。作为最基础的Repository接口,适合简单的数据访问需求。
        b.CrudRepository示例
            ---
            import io.micronaut.data.repository.CrudRepository;
            import io.micronaut.data.annotation.Repository;

            // 基础CRUD Repository
            @Repository
            public interface ProductRepository extends CrudRepository<Product, Long> {
                // 继承的方法:
                // - <S extends Product> S save(S entity)
                // - <S extends Product> Iterable<S> saveAll(Iterable<S> entities)
                // - Optional<Product> findById(Long id)
                // - boolean existsById(Long id)
                // - Iterable<Product> findAll()
                // - long count()
                // - void deleteById(Long id)
                // - void delete(Product entity)
                // - void deleteAll(Iterable<? extends Product> entities)
                // - void deleteAll()
            }

            // 产品实体
            @Entity
            @Table(name = "products")
            public class Product {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                @Column(nullable = false)
                private String name;

                @Column(precision = 10, scale = 2)
                private BigDecimal price;

                @Column
                private Integer stock;

                @Column
                private String category;

                @Column(name = "created_at")
                private LocalDateTime createdAt;

                // 构造函数
                public Product() {}

                public Product(String name, BigDecimal price, Integer stock) {
                    this.name = name;
                    this.price = price;
                    this.stock = stock;
                    this.createdAt = LocalDateTime.now();
                }

                // Getter和Setter省略
            }

            // 使用CrudRepository
            @Singleton
            public class ProductService {
                private final ProductRepository productRepository;

                public ProductService(ProductRepository productRepository) {
                    this.productRepository = productRepository;
                    System.out.println("ProductService初始化");
                }

                // 创建产品
                public Product createProduct(String name, BigDecimal price, Integer stock) {
                    System.out.println("创建产品: " + name);

                    Product product = new Product(name, price, stock);
                    Product saved = productRepository.save(product);

                    System.out.println("  产品已保存, ID: " + saved.getId());
                    return saved;
                }

                // 批量创建
                public List<Product> createProducts(List<Product> products) {
                    System.out.println("批量创建产品: " + products.size() + " 个");

                    Iterable<Product> saved = productRepository.saveAll(products);
                    List<Product> result = new ArrayList<>();
                    saved.forEach(result::add);

                    System.out.println("  批量保存完成");
                    return result;
                }

                // 查询单个产品
                public Optional<Product> findProduct(Long id) {
                    System.out.println("查询产品: " + id);
                    return productRepository.findById(id);
                }

                // 查询所有产品
                public List<Product> findAllProducts() {
                    System.out.println("查询所有产品");

                    Iterable<Product> products = productRepository.findAll();
                    List<Product> result = new ArrayList<>();
                    products.forEach(result::add);

                    System.out.println("  找到 " + result.size() + " 个产品");
                    return result;
                }

                // 检查产品是否存在
                public boolean productExists(Long id) {
                    System.out.println("检查产品是否存在: " + id);
                    return productRepository.existsById(id);
                }

                // 统计产品数量
                public long countProducts() {
                    long count = productRepository.count();
                    System.out.println("产品总数: " + count);
                    return count;
                }

                // 更新产品
                public Product updateProduct(Long id, String name, BigDecimal price) {
                    System.out.println("更新产品: " + id);

                    Optional<Product> optionalProduct = productRepository.findById(id);
                    if (optionalProduct.isEmpty()) {
                        throw new IllegalArgumentException("产品不存在: " + id);
                    }

                    Product product = optionalProduct.get();
                    product.setName(name);
                    product.setPrice(price);

                    Product updated = productRepository.update(product);
                    System.out.println("  产品已更新");
                    return updated;
                }

                // 删除产品
                public void deleteProduct(Long id) {
                    System.out.println("删除产品: " + id);
                    productRepository.deleteById(id);
                    System.out.println("  产品已删除");
                }

                // 批量删除
                public void deleteProducts(List<Long> ids) {
                    System.out.println("批量删除产品: " + ids.size() + " 个");

                    List<Product> products = ids.stream()
                        .map(id -> {
                            Product p = new Product();
                            p.setId(id);
                            return p;
                        })
                        .collect(Collectors.toList());

                    productRepository.deleteAll(products);
                    System.out.println("  批量删除完成");
                }

                // 清空所有产品
                public void deleteAllProducts() {
                    System.out.println("删除所有产品");
                    productRepository.deleteAll();
                    System.out.println("  所有产品已删除");
                }
            }

            // 控制器
            @Controller("/api/products")
            public class ProductController {
                private final ProductService productService;

                public ProductController(ProductService productService) {
                    this.productService = productService;
                }

                @Post
                public Product create(@Body CreateProductRequest request) {
                    return productService.createProduct(
                        request.getName(),
                        request.getPrice(),
                        request.getStock()
                    );
                }

                @Get("/{id}")
                public Optional<Product> get(Long id) {
                    return productService.findProduct(id);
                }

                @Get
                public List<Product> getAll() {
                    return productService.findAllProducts();
                }

                @Put("/{id}")
                public Product update(Long id, @Body UpdateProductRequest request) {
                    return productService.updateProduct(
                        id,
                        request.getName(),
                        request.getPrice()
                    );
                }

                @Delete("/{id}")
                @Status(HttpStatus.NO_CONTENT)
                public void delete(Long id) {
                    productService.deleteProduct(id);
                }

                @Get("/count")
                public Map<String, Long> count() {
                    return Map.of("count", productService.countProducts());
                }
            }

            // 请求对象
            public class CreateProductRequest {
                private String name;
                private BigDecimal price;
                private Integer stock;

                // Getter和Setter省略
            }

            public class UpdateProductRequest {
                private String name;
                private BigDecimal price;

                // Getter和Setter省略
            }
            ---
    b.JpaRepository
        a.JPA扩展功能
            JpaRepository扩展CrudRepository,添加flush、saveAndFlush等JPA特定方法。提供批量操作优化,支持实体状态管理,适合使用JPA的应用。
        b.JpaRepository示例
            ---
            import io.micronaut.data.jpa.repository.JpaRepository;
            import io.micronaut.data.jpa.repository.criteria.Specification;

            @Repository
            public interface OrderRepository extends JpaRepository<Order, Long> {
                // 继承CrudRepository的所有方法,额外提供:
                // - void flush()
                // - <S extends Order> S saveAndFlush(S entity)
                // - void deleteInBatch(Iterable<Order> entities)
                // - void deleteAllInBatch()
                // - Order getOne(Long id)
                // - List<Order> findAll(Specification<Order> spec)
            }

            // 订单实体
            @Entity
            @Table(name = "orders")
            public class Order {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                @Column(name = "order_number", unique = true)
                private String orderNumber;

                @Column(name = "user_id")
                private Long userId;

                @Column
                private String status;  // PENDING, CONFIRMED, SHIPPED, DELIVERED

                @Column(precision = 10, scale = 2)
                private BigDecimal total;

                @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
                private List<OrderItem> items = new ArrayList<>();

                @Column(name = "created_at")
                private LocalDateTime createdAt;

                @Column(name = "updated_at")
                private LocalDateTime updatedAt;

                @PrePersist
                protected void onCreate() {
                    createdAt = LocalDateTime.now();
                    updatedAt = LocalDateTime.now();
                }

                @PreUpdate
                protected void onUpdate() {
                    updatedAt = LocalDateTime.now();
                }

                // Getter和Setter省略
            }

            // 订单项实体
            @Entity
            @Table(name = "order_items")
            public class OrderItem {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                @ManyToOne(fetch = FetchType.LAZY)
                @JoinColumn(name = "order_id")
                private Order order;

                @Column(name = "product_id")
                private Long productId;

                @Column
                private Integer quantity;

                @Column(precision = 10, scale = 2)
                private BigDecimal price;

                // Getter和Setter省略
            }

            // 使用JpaRepository
            @Singleton
            public class OrderService {
                private final OrderRepository orderRepository;

                public OrderService(OrderRepository orderRepository) {
                    this.orderRepository = orderRepository;
                    System.out.println("OrderService初始化");
                }

                // 创建订单并立即刷新
                @Transactional
                public Order createOrderAndFlush(Long userId, List<OrderItem> items) {
                    System.out.println("创建订单: 用户ID=" + userId);

                    Order order = new Order();
                    order.setOrderNumber(generateOrderNumber());
                    order.setUserId(userId);
                    order.setStatus("PENDING");

                    // 添加订单项
                    BigDecimal total = BigDecimal.ZERO;
                    for (OrderItem item : items) {
                        item.setOrder(order);
                        order.getItems().add(item);
                        total = total.add(item.getPrice().multiply(
                            BigDecimal.valueOf(item.getQuantity())
                        ));
                    }
                    order.setTotal(total);

                    // 保存并立即刷新到数据库
                    Order saved = orderRepository.saveAndFlush(order);
                    System.out.println("  订单已保存并刷新, ID: " + saved.getId());
                    System.out.println("  订单号: " + saved.getOrderNumber());

                    return saved;
                }

                // 批量删除订单
                @Transactional
                public void deleteOrdersInBatch(List<Long> orderIds) {
                    System.out.println("批量删除订单: " + orderIds.size() + " 个");

                    List<Order> orders = orderIds.stream()
                        .map(id -> {
                            Order order = new Order();
                            order.setId(id);
                            return order;
                        })
                        .collect(Collectors.toList());

                    // 批量删除,减少数据库交互
                    orderRepository.deleteInBatch(orders);
                    System.out.println("  批量删除完成");
                }

                // 手动刷新
                @Transactional
                public void updateOrderStatus(Long orderId, String newStatus) {
                    System.out.println("更新订单状态: " + orderId + " -> " + newStatus);

                    Optional<Order> optionalOrder = orderRepository.findById(orderId);
                    if (optionalOrder.isEmpty()) {
                        throw new IllegalArgumentException("订单不存在: " + orderId);
                    }

                    Order order = optionalOrder.get();
                    order.setStatus(newStatus);

                    // 保存但不立即刷新
                    orderRepository.save(order);

                    // 执行其他操作...

                    // 手动刷新到数据库
                    orderRepository.flush();
                    System.out.println("  订单状态已更新并刷新");
                }

                // 获取订单引用
                public Order getOrderReference(Long id) {
                    System.out.println("获取订单引用: " + id);
                    // getOne返回懒加载代理,不立即查询数据库
                    return orderRepository.getOne(id);
                }

                // 查询订单
                public Optional<Order> findOrder(Long id) {
                    System.out.println("查询订单: " + id);
                    return orderRepository.findById(id);
                }

                // 统计订单
                public Map<String, Object> getOrderStatistics() {
                    System.out.println("统计订单信息");

                    long totalOrders = orderRepository.count();

                    Map<String, Object> stats = new HashMap<>();
                    stats.put("totalOrders", totalOrders);
                    stats.put("timestamp", LocalDateTime.now());

                    return stats;
                }

                private String generateOrderNumber() {
                    return "ORD-" + System.currentTimeMillis();
                }
            }

            // 控制器
            @Controller("/api/orders")
            public class OrderController {
                private final OrderService orderService;

                public OrderController(OrderService orderService) {
                    this.orderService = orderService;
                }

                @Post
                public Order create(@Body CreateOrderRequest request) {
                    return orderService.createOrderAndFlush(
                        request.getUserId(),
                        request.getItems()
                    );
                }

                @Get("/{id}")
                public Optional<Order> get(Long id) {
                    return orderService.findOrder(id);
                }

                @Put("/{id}/status")
                public void updateStatus(Long id, @Body UpdateStatusRequest request) {
                    orderService.updateOrderStatus(id, request.getStatus());
                }

                @Delete("/batch")
                @Status(HttpStatus.NO_CONTENT)
                public void deleteBatch(@Body List<Long> orderIds) {
                    orderService.deleteOrdersInBatch(orderIds);
                }

                @Get("/statistics")
                public Map<String, Object> getStatistics() {
                    return orderService.getOrderStatistics();
                }
            }

            // 请求对象
            public class CreateOrderRequest {
                private Long userId;
                private List<OrderItem> items;

                // Getter和Setter省略
            }

            public class UpdateStatusRequest {
                private String status;

                // Getter和Setter省略
            }
            ---

02.分页与排序
    a.Pageable接口
        a.分页查询
            使用Pageable接口实现分页查询,支持页码、页大小、排序等参数。返回Page对象包含数据列表、总数、总页数等分页信息,简化分页实现。
        b.分页查询示例
            ---
            import io.micronaut.data.model.Page;
            import io.micronaut.data.model.Pageable;
            import io.micronaut.data.model.Sort;

            @Repository
            public interface BookRepository extends JpaRepository<Book, Long> {
                // 基础分页
                Page<Book> findAll(Pageable pageable);

                // 条件分页
                Page<Book> findByCategory(String category, Pageable pageable);

                Page<Book> findByAuthor(String author, Pageable pageable);

                Page<Book> findByPriceBetween(BigDecimal minPrice, BigDecimal maxPrice, Pageable pageable);

                // 复杂条件分页
                Page<Book> findByTitleContainingAndCategoryOrderByPublishedDateDesc(
                    String title,
                    String category,
                    Pageable pageable
                );
            }

            // 图书实体
            @Entity
            @Table(name = "books")
            public class Book {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                @Column(nullable = false)
                private String title;

                @Column
                private String author;

                @Column
                private String category;

                @Column
                private String isbn;

                @Column(precision = 10, scale = 2)
                private BigDecimal price;

                @Column(name = "published_date")
                private LocalDate publishedDate;

                @Column
                private Integer pageCount;

                @Column(columnDefinition = "TEXT")
                private String description;

                // Getter和Setter省略
            }

            // 分页服务
            @Singleton
            public class BookService {
                private final BookRepository bookRepository;

                public BookService(BookRepository bookRepository) {
                    this.bookRepository = bookRepository;
                    System.out.println("BookService初始化");
                }

                // 基础分页查询
                public Page<Book> findBooks(int page, int size) {
                    System.out.println("分页查询图书: page=" + page + ", size=" + size);

                    Pageable pageable = Pageable.from(page, size);
                    Page<Book> result = bookRepository.findAll(pageable);

                    System.out.println("  当前页: " + result.getPageNumber());
                    System.out.println("  页大小: " + result.getSize());
                    System.out.println("  总记录数: " + result.getTotalSize());
                    System.out.println("  总页数: " + result.getTotalPages());
                    System.out.println("  当前页记录数: " + result.getContent().size());

                    return result;
                }

                // 带排序的分页
                public Page<Book> findBooksWithSort(int page, int size, String sortBy, String direction) {
                    System.out.println("排序分页查询: page=" + page + ", size=" + size +
                                     ", sort=" + sortBy + " " + direction);

                    Sort.Order order = direction.equalsIgnoreCase("ASC") ?
                        Sort.Order.asc(sortBy) :
                        Sort.Order.desc(sortBy);

                    Pageable pageable = Pageable.from(page, size, Sort.of(order));
                    Page<Book> result = bookRepository.findAll(pageable);

                    System.out.println("  找到 " + result.getContent().size() + " 本图书");
                    return result;
                }

                // 多字段排序
                public Page<Book> findBooksWithMultipleSort(int page, int size) {
                    System.out.println("多字段排序分页查询");

                    Sort sort = Sort.of(
                        Sort.Order.desc("publishedDate"),
                        Sort.Order.asc("title")
                    );

                    Pageable pageable = Pageable.from(page, size, sort);
                    Page<Book> result = bookRepository.findAll(pageable);

                    return result;
                }

                // 按分类分页
                public Page<Book> findBooksByCategory(String category, int page, int size) {
                    System.out.println("按分类分页: " + category);

                    Pageable pageable = Pageable.from(page, size);
                    Page<Book> result = bookRepository.findByCategory(category, pageable);

                    System.out.println("  分类 '" + category + "' 总数: " + result.getTotalSize());
                    return result;
                }

                // 价格范围分页
                public Page<Book> findBooksByPriceRange(BigDecimal minPrice, BigDecimal maxPrice,
                                                        int page, int size) {
                    System.out.println("价格范围分页: " + minPrice + " - " + maxPrice);

                    Sort sort = Sort.of(Sort.Order.asc("price"));
                    Pageable pageable = Pageable.from(page, size, sort);

                    Page<Book> result = bookRepository.findByPriceBetween(minPrice, maxPrice, pageable);

                    System.out.println("  找到 " + result.getTotalSize() + " 本符合价格范围的图书");
                    return result;
                }

                // 搜索分页
                public Page<Book> searchBooks(String keyword, String category, int page, int size) {
                    System.out.println("搜索图书: keyword=" + keyword + ", category=" + category);

                    Sort sort = Sort.of(Sort.Order.desc("publishedDate"));
                    Pageable pageable = Pageable.from(page, size, sort);

                    Page<Book> result = bookRepository
                        .findByTitleContainingAndCategoryOrderByPublishedDateDesc(
                            keyword,
                            category,
                            pageable
                        );

                    return result;
                }

                // 分页导航
                public Map<String, Object> getPageInfo(Page<Book> page) {
                    Map<String, Object> info = new HashMap<>();

                    info.put("currentPage", page.getPageNumber());
                    info.put("pageSize", page.getSize());
                    info.put("totalPages", page.getTotalPages());
                    info.put("totalElements", page.getTotalSize());
                    info.put("hasNext", page.getPageNumber() < page.getTotalPages() - 1);
                    info.put("hasPrevious", page.getPageNumber() > 0);
                    info.put("isFirst", page.getPageNumber() == 0);
                    info.put("isLast", page.getPageNumber() == page.getTotalPages() - 1);
                    info.put("content", page.getContent());

                    return info;
                }
            }

            // 分页控制器
            @Controller("/api/books")
            public class BookController {
                private final BookService bookService;

                public BookController(BookService bookService) {
                    this.bookService = bookService;
                }

                // 基础分页
                @Get
                public Page<Book> list(
                    @QueryValue(defaultValue = "0") int page,
                    @QueryValue(defaultValue = "20") int size) {
                    return bookService.findBooks(page, size);
                }

                // 带排序的分页
                @Get("/sorted")
                public Page<Book> listSorted(
                    @QueryValue(defaultValue = "0") int page,
                    @QueryValue(defaultValue = "20") int size,
                    @QueryValue(defaultValue = "title") String sort,
                    @QueryValue(defaultValue = "ASC") String direction) {
                    return bookService.findBooksWithSort(page, size, sort, direction);
                }

                // 按分类分页
                @Get("/category/{category}")
                public Page<Book> listByCategory(
                    String category,
                    @QueryValue(defaultValue = "0") int page,
                    @QueryValue(defaultValue = "20") int size) {
                    return bookService.findBooksByCategory(category, page, size);
                }

                // 价格范围分页
                @Get("/price-range")
                public Page<Book> listByPriceRange(
                    @QueryValue BigDecimal minPrice,
                    @QueryValue BigDecimal maxPrice,
                    @QueryValue(defaultValue = "0") int page,
                    @QueryValue(defaultValue = "20") int size) {
                    return bookService.findBooksByPriceRange(minPrice, maxPrice, page, size);
                }

                // 搜索分页
                @Get("/search")
                public Page<Book> search(
                    @QueryValue String keyword,
                    @QueryValue String category,
                    @QueryValue(defaultValue = "0") int page,
                    @QueryValue(defaultValue = "20") int size) {
                    return bookService.searchBooks(keyword, category, page, size);
                }

                // 分页信息
                @Get("/page-info")
                public Map<String, Object> getPageInfo(
                    @QueryValue(defaultValue = "0") int page,
                    @QueryValue(defaultValue = "20") int size) {
                    Page<Book> bookPage = bookService.findBooks(page, size);
                    return bookService.getPageInfo(bookPage);
                }
            }

            // 分页响应示例
            // GET /api/books?page=0&size=10
            // {
            //   "content": [...],
            //   "pageable": {
            //     "number": 0,
            //     "size": 10,
            //     "sort": {
            //       "sorted": false
            //     }
            //   },
            //   "totalPages": 15,
            //   "totalSize": 150,
            //   "size": 10,
            //   "number": 0
            // }
            ---
    b.Sort排序
        a.排序配置
            通过Sort对象配置查询结果的排序方式,支持单字段和多字段排序,可指定升序或降序。排序配置可独立使用或与分页结合。
        b.排序配置示例
            ---
            @Singleton
            public class SortingService {
                private final BookRepository bookRepository;

                public SortingService(BookRepository bookRepository) {
                    this.bookRepository = bookRepository;
                }

                // 单字段排序
                public List<Book> findBooksSortedByTitle() {
                    System.out.println("按标题排序查询");

                    Sort sort = Sort.of(Sort.Order.asc("title"));
                    Pageable pageable = Pageable.from(0, 100, sort);

                    return bookRepository.findAll(pageable).getContent();
                }

                // 多字段排序
                public List<Book> findBooksSortedByMultipleFields() {
                    System.out.println("多字段排序查询");

                    Sort sort = Sort.of(
                        Sort.Order.desc("publishedDate"),  // 首先按出版日期降序
                        Sort.Order.asc("title"),           // 然后按标题升序
                        Sort.Order.desc("price")           // 最后按价格降序
                    );

                    Pageable pageable = Pageable.from(0, 100, sort);
                    return bookRepository.findAll(pageable).getContent();
                }

                // 忽略大小写排序
                public List<Book> findBooksSortedIgnoreCase() {
                    System.out.println("忽略大小写排序");

                    Sort sort = Sort.of(
                        Sort.Order.asc("title").ignoreCase()
                    );

                    Pageable pageable = Pageable.from(0, 100, sort);
                    return bookRepository.findAll(pageable).getContent();
                }

                // 空值处理排序
                public List<Book> findBooksSortedWithNullHandling() {
                    System.out.println("空值处理排序");

                    Sort sort = Sort.of(
                        Sort.Order.desc("publishedDate")
                            .nullsLast()  // 空值放在最后
                    );

                    Pageable pageable = Pageable.from(0, 100, sort);
                    return bookRepository.findAll(pageable).getContent();
                }

                // 动态排序
                public List<Book> findBooksWithDynamicSort(String sortField, String direction) {
                    System.out.println("动态排序: " + sortField + " " + direction);

                    Sort.Order order;
                    if ("ASC".equalsIgnoreCase(direction)) {
                        order = Sort.Order.asc(sortField);
                    } else {
                        order = Sort.Order.desc(sortField);
                    }

                    Sort sort = Sort.of(order);
                    Pageable pageable = Pageable.from(0, 100, sort);

                    return bookRepository.findAll(pageable).getContent();
                }

                // 条件排序
                public List<Book> findBooksWithConditionalSort(String category, String sortBy) {
                    System.out.println("条件排序: category=" + category + ", sortBy=" + sortBy);

                    Sort sort = switch (sortBy) {
                        case "price-asc" -> Sort.of(Sort.Order.asc("price"));
                        case "price-desc" -> Sort.of(Sort.Order.desc("price"));
                        case "date-new" -> Sort.of(Sort.Order.desc("publishedDate"));
                        case "date-old" -> Sort.of(Sort.Order.asc("publishedDate"));
                        case "title" -> Sort.of(Sort.Order.asc("title"));
                        default -> Sort.of(Sort.Order.desc("publishedDate"));
                    };

                    Pageable pageable = Pageable.from(0, 100, sort);
                    return bookRepository.findByCategory(category, pageable).getContent();
                }

                // 复合排序示例
                public List<Book> findBooksWithComplexSort() {
                    System.out.println("复合排序");

                    // 按分类升序,同分类内按价格降序,同价格按标题升序
                    Sort sort = Sort.of(
                        Sort.Order.asc("category"),
                        Sort.Order.desc("price"),
                        Sort.Order.asc("title").ignoreCase()
                    );

                    Pageable pageable = Pageable.from(0, 100, sort);
                    return bookRepository.findAll(pageable).getContent();
                }
            }

            // 排序控制器
            @Controller("/api/books/sort")
            public class SortingController {
                private final SortingService sortingService;

                public SortingController(SortingService sortingService) {
                    this.sortingService = sortingService;
                }

                @Get("/title")
                public List<Book> sortByTitle() {
                    return sortingService.findBooksSortedByTitle();
                }

                @Get("/multiple")
                public List<Book> sortByMultiple() {
                    return sortingService.findBooksSortedByMultipleFields();
                }

                @Get("/dynamic")
                public List<Book> sortDynamic(
                    @QueryValue String field,
                    @QueryValue String direction) {
                    return sortingService.findBooksWithDynamicSort(field, direction);
                }

                @Get("/conditional")
                public List<Book> sortConditional(
                    @QueryValue String category,
                    @QueryValue String sortBy) {
                    return sortingService.findBooksWithConditionalSort(category, sortBy);
                }
            }
            ---

03.自定义Repository
    a.接口扩展
        a.添加自定义方法
            通过接口继承和实现类扩展Repository功能,添加复杂查询逻辑。可以混合使用派生查询、@Query注解和自定义实现方法。
        b.接口扩展示例
            ---
            // 自定义Repository接口
            public interface CustomUserRepository {
                List<User> findUsersWithCustomLogic(String criteria);

                Map<String, Long> getUserStatistics();

                void bulkUpdateUserStatus(List<Long> userIds, String status);
            }

            // 标准Repository接口
            @Repository
            public interface UserRepository extends JpaRepository<User, Long>, CustomUserRepository {
                // 标准查询方法
                Optional<User> findByUsername(String username);

                List<User> findByActive(boolean active);

                // 同时继承CustomUserRepository的自定义方法
            }

            // 自定义Repository实现
            @Singleton
            public class CustomUserRepositoryImpl implements CustomUserRepository {
                private final EntityManager entityManager;

                public CustomUserRepositoryImpl(EntityManager entityManager) {
                    this.entityManager = entityManager;
                    System.out.println("CustomUserRepositoryImpl初始化");
                }

                @Override
                @Transactional
                public List<User> findUsersWithCustomLogic(String criteria) {
                    System.out.println("自定义查询逻辑: " + criteria);

                    // 使用EntityManager执行复杂查询
                    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
                    CriteriaQuery<User> query = cb.createQuery(User.class);
                    Root<User> root = query.from(User.class);

                    // 构建复杂查询条件
                    List<Predicate> predicates = new ArrayList<>();

                    if (criteria.contains("active")) {
                        predicates.add(cb.equal(root.get("active"), true));
                    }

                    if (criteria.contains("verified")) {
                        predicates.add(cb.equal(root.get("verified"), true));
                    }

                    if (criteria.contains("recent")) {
                        LocalDateTime cutoff = LocalDateTime.now().minusDays(30);
                        predicates.add(cb.greaterThan(root.get("createdAt"), cutoff));
                    }

                    query.where(predicates.toArray(new Predicate[0]));
                    query.orderBy(cb.desc(root.get("createdAt")));

                    List<User> results = entityManager.createQuery(query).getResultList();
                    System.out.println("  找到 " + results.size() + " 个用户");

                    return results;
                }

                @Override
                public Map<String, Long> getUserStatistics() {
                    System.out.println("获取用户统计信息");

                    Map<String, Long> stats = new HashMap<>();

                    // 总用户数
                    Long totalUsers = entityManager.createQuery(
                        "SELECT COUNT(u) FROM User u",
                        Long.class
                    ).getSingleResult();
                    stats.put("totalUsers", totalUsers);

                    // 活跃用户数
                    Long activeUsers = entityManager.createQuery(
                        "SELECT COUNT(u) FROM User u WHERE u.active = true",
                        Long.class
                    ).getSingleResult();
                    stats.put("activeUsers", activeUsers);

                    // 已验证用户数
                    Long verifiedUsers = entityManager.createQuery(
                        "SELECT COUNT(u) FROM User u WHERE u.verified = true",
                        Long.class
                    ).getSingleResult();
                    stats.put("verifiedUsers", verifiedUsers);

                    // 本月新用户数
                    LocalDateTime monthStart = LocalDateTime.now().withDayOfMonth(1).withHour(0).withMinute(0);
                    Long newUsersThisMonth = entityManager.createQuery(
                        "SELECT COUNT(u) FROM User u WHERE u.createdAt >= :monthStart",
                        Long.class
                    ).setParameter("monthStart", monthStart).getSingleResult();
                    stats.put("newUsersThisMonth", newUsersThisMonth);

                    System.out.println("  统计结果: " + stats);
                    return stats;
                }

                @Override
                @Transactional
                public void bulkUpdateUserStatus(List<Long> userIds, String status) {
                    System.out.println("批量更新用户状态: " + userIds.size() + " 个用户");

                    int updated = entityManager.createQuery(
                        "UPDATE User u SET u.status = :status, u.updatedAt = :now " +
                        "WHERE u.id IN :ids"
                    )
                    .setParameter("status", status)
                    .setParameter("now", LocalDateTime.now())
                    .setParameter("ids", userIds)
                    .executeUpdate();

                    System.out.println("  更新了 " + updated + " 个用户");
                }
            }

            // 使用自定义Repository
            @Singleton
            public class UserManagementService {
                private final UserRepository userRepository;

                public UserManagementService(UserRepository userRepository) {
                    this.userRepository = userRepository;
                    System.out.println("UserManagementService初始化");
                }

                // 使用标准方法
                public Optional<User> findByUsername(String username) {
                    return userRepository.findByUsername(username);
                }

                // 使用自定义方法
                public List<User> findActiveRecentUsers() {
                    return userRepository.findUsersWithCustomLogic("active,recent");
                }

                // 获取统计信息
                public Map<String, Long> getStatistics() {
                    return userRepository.getUserStatistics();
                }

                // 批量更新
                public void suspendUsers(List<Long> userIds) {
                    userRepository.bulkUpdateUserStatus(userIds, "SUSPENDED");
                }
            }
            ---
    b.Repository组合
        a.多Repository协作
            在服务层组合多个Repository实现复杂业务逻辑,协调不同实体的数据访问。通过事务管理保证数据一致性,实现跨Repository的业务操作。
        b.Repository组合示例
            ---
            // 多个Repository
            @Repository
            public interface UserRepository extends JpaRepository<User, Long> {
                Optional<User> findByUsername(String username);
                List<User> findByIdIn(List<Long> ids);
            }

            @Repository
            public interface OrderRepository extends JpaRepository<Order, Long> {
                List<Order> findByUserId(Long userId);
                List<Order> findByStatus(String status);
            }

            @Repository
            public interface ProductRepository extends JpaRepository<Product, Long> {
                List<Product> findByIdIn(List<Long> ids);
            }

            @Repository
            public interface WalletRepository extends JpaRepository<Wallet, Long> {
                Optional<Wallet> findByUserId(Long userId);
            }

            // 钱包实体
            @Entity
            @Table(name = "wallets")
            public class Wallet {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                @Column(name = "user_id", unique = true)
                private Long userId;

                @Column(precision = 10, scale = 2)
                private BigDecimal balance;

                @Version
                private Long version;  // 乐观锁

                // Getter和Setter省略
            }

            // 组合多Repository的服务
            @Singleton
            public class OrderManagementService {
                private final OrderRepository orderRepository;
                private final UserRepository userRepository;
                private final ProductRepository productRepository;
                private final WalletRepository walletRepository;

                public OrderManagementService(
                    OrderRepository orderRepository,
                    UserRepository userRepository,
                    ProductRepository productRepository,
                    WalletRepository walletRepository) {

                    this.orderRepository = orderRepository;
                    this.userRepository = userRepository;
                    this.productRepository = productRepository;
                    this.walletRepository = walletRepository;
                    System.out.println("OrderManagementService初始化");
                }

                // 创建订单 - 涉及多个Repository
                @Transactional
                public Order createOrder(Long userId, List<OrderItemRequest> items) {
                    System.out.println("创建订单: 用户ID=" + userId);

                    // 1. 验证用户存在
                    User user = userRepository.findById(userId)
                        .orElseThrow(() -> new IllegalArgumentException("用户不存在"));

                    // 2. 获取产品信息
                    List<Long> productIds = items.stream()
                        .map(OrderItemRequest::getProductId)
                        .collect(Collectors.toList());

                    List<Product> products = productRepository.findByIdIn(productIds);
                    if (products.size() != productIds.size()) {
                        throw new IllegalArgumentException("部分产品不存在");
                    }

                    // 3. 计算总价
                    BigDecimal total = BigDecimal.ZERO;
                    for (OrderItemRequest item : items) {
                        Product product = products.stream()
                            .filter(p -> p.getId().equals(item.getProductId()))
                            .findFirst()
                            .orElseThrow();

                        BigDecimal itemTotal = product.getPrice()
                            .multiply(BigDecimal.valueOf(item.getQuantity()));
                        total = total.add(itemTotal);
                    }

                    // 4. 创建订单
                    Order order = new Order();
                    order.setOrderNumber("ORD-" + System.currentTimeMillis());
                    order.setUserId(userId);
                    order.setStatus("PENDING");
                    order.setTotal(total);

                    Order savedOrder = orderRepository.save(order);
                    System.out.println("  订单已创建: " + savedOrder.getOrderNumber());

                    return savedOrder;
                }

                // 支付订单 - 涉及订单和钱包
                @Transactional
                public void payOrder(Long orderId) {
                    System.out.println("支付订单: " + orderId);

                    // 1. 获取订单
                    Order order = orderRepository.findById(orderId)
                        .orElseThrow(() -> new IllegalArgumentException("订单不存在"));

                    if (!"PENDING".equals(order.getStatus())) {
                        throw new IllegalStateException("订单状态不正确");
                    }

                    // 2. 获取用户钱包
                    Wallet wallet = walletRepository.findByUserId(order.getUserId())
                        .orElseThrow(() -> new IllegalArgumentException("钱包不存在"));

                    // 3. 检查余额
                    if (wallet.getBalance().compareTo(order.getTotal()) < 0) {
                        throw new IllegalStateException("余额不足");
                    }

                    // 4. 扣除余额
                    wallet.setBalance(wallet.getBalance().subtract(order.getTotal()));
                    walletRepository.update(wallet);

                    // 5. 更新订单状态
                    order.setStatus("PAID");
                    orderRepository.update(order);

                    System.out.println("  订单支付成功");
                }

                // 获取用户订单摘要
                @Transactional(readOnly = true)
                public UserOrderSummary getUserOrderSummary(Long userId) {
                    System.out.println("获取用户订单摘要: " + userId);

                    // 1. 获取用户信息
                    User user = userRepository.findById(userId)
                        .orElseThrow(() -> new IllegalArgumentException("用户不存在"));

                    // 2. 获取用户所有订单
                    List<Order> orders = orderRepository.findByUserId(userId);

                    // 3. 获取钱包余额
                    Wallet wallet = walletRepository.findByUserId(userId)
                        .orElse(null);

                    // 4. 统计订单信息
                    long totalOrders = orders.size();
                    long paidOrders = orders.stream()
                        .filter(o -> "PAID".equals(o.getStatus()))
                        .count();
                    BigDecimal totalSpent = orders.stream()
                        .filter(o -> "PAID".equals(o.getStatus()))
                        .map(Order::getTotal)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);

                    UserOrderSummary summary = new UserOrderSummary(
                        user.getUsername(),
                        totalOrders,
                        paidOrders,
                        totalSpent,
                        wallet != null ? wallet.getBalance() : BigDecimal.ZERO
                    );

                    System.out.println("  摘要: " + summary);
                    return summary;
                }

                // 批量处理待支付订单
                @Transactional
                public Map<String, Integer> processPendingOrders() {
                    System.out.println("批量处理待支付订单");

                    List<Order> pendingOrders = orderRepository.findByStatus("PENDING");
                    System.out.println("  待支付订单: " + pendingOrders.size());

                    int processed = 0;
                    int failed = 0;

                    for (Order order : pendingOrders) {
                        try {
                            payOrder(order.getId());
                            processed++;
                        } catch (Exception e) {
                            System.err.println("  订单支付失败: " + order.getId() + " - " + e.getMessage());
                            failed++;
                        }
                    }

                    Map<String, Integer> result = new HashMap<>();
                    result.put("processed", processed);
                    result.put("failed", failed);

                    System.out.println("  处理完成: 成功=" + processed + ", 失败=" + failed);
                    return result;
                }
            }

            // 订单项请求
            public class OrderItemRequest {
                private Long productId;
                private Integer quantity;

                // Getter和Setter省略
            }

            // 用户订单摘要
            public class UserOrderSummary {
                private String username;
                private long totalOrders;
                private long paidOrders;
                private BigDecimal totalSpent;
                private BigDecimal walletBalance;

                public UserOrderSummary(String username, long totalOrders, long paidOrders,
                                      BigDecimal totalSpent, BigDecimal walletBalance) {
                    this.username = username;
                    this.totalOrders = totalOrders;
                    this.paidOrders = paidOrders;
                    this.totalSpent = totalSpent;
                    this.walletBalance = walletBalance;
                }

                @Override
                public String toString() {
                    return "UserOrderSummary{username='" + username + "', totalOrders=" + totalOrders +
                           ", paidOrders=" + paidOrders + ", totalSpent=" + totalSpent +
                           ", walletBalance=" + walletBalance + "}";
                }

                // Getter省略
            }
            ---

5.3 JPA集成

01.实体映射
    a.@Entity注解
        a.实体类定义
            使用@Entity标记JPA实体类,@Table指定表名,@Column配置列属性。实体类通过注解映射到数据库表,实现对象关系映射(ORM)。
        b.实体映射示例
            ---
            import jakarta.persistence.*;
            import java.time.LocalDateTime;

            // 基础实体映射
            @Entity
            @Table(name = "employees")
            public class Employee {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                @Column(name = "employee_number", unique = true, nullable = false, length = 20)
                private String employeeNumber;

                @Column(name = "first_name", nullable = false, length = 50)
                private String firstName;

                @Column(name = "last_name", nullable = false, length = 50)
                private String lastName;

                @Column(nullable = false, unique = true, length = 100)
                private String email;

                @Column(length = 20)
                private String phone;

                @Column(length = 50)
                private String department;

                @Column(length = 50)
                private String position;

                @Column(precision = 10, scale = 2)
                private BigDecimal salary;

                @Column(name = "hire_date", nullable = false)
                private LocalDate hireDate;

                @Column(name = "is_active", nullable = false)
                private Boolean active = true;

                @Column(name = "created_at", nullable = false, updatable = false)
                private LocalDateTime createdAt;

                @Column(name = "updated_at")
                private LocalDateTime updatedAt;

                // 生命周期回调
                @PrePersist
                protected void onCreate() {
                    createdAt = LocalDateTime.now();
                    updatedAt = LocalDateTime.now();
                    System.out.println("准备保存员工: " + employeeNumber);
                }

                @PreUpdate
                protected void onUpdate() {
                    updatedAt = LocalDateTime.now();
                    System.out.println("准备更新员工: " + employeeNumber);
                }

                @PostPersist
                protected void afterCreate() {
                    System.out.println("员工已保存: " + id);
                }

                @PostUpdate
                protected void afterUpdate() {
                    System.out.println("员工已更新: " + id);
                }

                @PostLoad
                protected void afterLoad() {
                    System.out.println("员工已加载: " + employeeNumber);
                }

                // 构造函数
                public Employee() {}

                public Employee(String employeeNumber, String firstName, String lastName, String email) {
                    this.employeeNumber = employeeNumber;
                    this.firstName = firstName;
                    this.lastName = lastName;
                    this.email = email;
                    this.hireDate = LocalDate.now();
                }

                // Getter和Setter省略
            }

            // 枚举类型映射
            @Entity
            @Table(name = "tasks")
            public class Task {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                @Column(nullable = false)
                private String title;

                @Column(columnDefinition = "TEXT")
                private String description;

                // 枚举映射为字符串
                @Enumerated(EnumType.STRING)
                @Column(length = 20)
                private TaskStatus status;

                // 枚举映射为整数
                @Enumerated(EnumType.ORDINAL)
                @Column
                private TaskPriority priority;

                @Column(name = "due_date")
                private LocalDate dueDate;

                // Getter和Setter省略
            }

            // 任务状态枚举
            public enum TaskStatus {
                TODO,
                IN_PROGRESS,
                REVIEW,
                DONE,
                CANCELLED
            }

            // 任务优先级枚举
            public enum TaskPriority {
                LOW,      // 0
                MEDIUM,   // 1
                HIGH,     // 2
                URGENT    // 3
            }

            // 大对象(LOB)映射
            @Entity
            @Table(name = "documents")
            public class Document {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                @Column(nullable = false)
                private String title;

                // 大文本对象
                @Lob
                @Column(columnDefinition = "TEXT")
                private String content;

                // 二进制大对象
                @Lob
                @Column(columnDefinition = "BLOB")
                private byte[] fileData;

                @Column(name = "file_name")
                private String fileName;

                @Column(name = "file_type")
                private String fileType;

                // Getter和Setter省略
            }

            // 嵌入式对象
            @Embeddable
            public class Address {
                @Column(length = 100)
                private String street;

                @Column(length = 50)
                private String city;

                @Column(length = 50)
                private String state;

                @Column(name = "zip_code", length = 10)
                private String zipCode;

                @Column(length = 50)
                private String country;

                // 构造函数
                public Address() {}

                public Address(String street, String city, String state, String zipCode, String country) {
                    this.street = street;
                    this.city = city;
                    this.state = state;
                    this.zipCode = zipCode;
                    this.country = country;
                }

                // Getter和Setter省略
            }

            // 使用嵌入式对象的实体
            @Entity
            @Table(name = "customers")
            public class Customer {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                @Column(nullable = false)
                private String name;

                @Column(nullable = false, unique = true)
                private String email;

                // 嵌入地址对象
                @Embedded
                @AttributeOverrides({
                    @AttributeOverride(name = "street", column = @Column(name = "billing_street")),
                    @AttributeOverride(name = "city", column = @Column(name = "billing_city")),
                    @AttributeOverride(name = "state", column = @Column(name = "billing_state")),
                    @AttributeOverride(name = "zipCode", column = @Column(name = "billing_zip")),
                    @AttributeOverride(name = "country", column = @Column(name = "billing_country"))
                })
                private Address billingAddress;

                @Embedded
                @AttributeOverrides({
                    @AttributeOverride(name = "street", column = @Column(name = "shipping_street")),
                    @AttributeOverride(name = "city", column = @Column(name = "shipping_city")),
                    @AttributeOverride(name = "state", column = @Column(name = "shipping_state")),
                    @AttributeOverride(name = "zipCode", column = @Column(name = "shipping_zip")),
                    @AttributeOverride(name = "country", column = @Column(name = "shipping_country"))
                })
                private Address shippingAddress;

                // Getter和Setter省略
            }

            // Repository使用示例
            @Repository
            public interface EmployeeRepository extends JpaRepository<Employee, Long> {
                Optional<Employee> findByEmployeeNumber(String employeeNumber);
                List<Employee> findByDepartment(String department);
                List<Employee> findByActiveTrue();
                List<Employee> findByHireDateBetween(LocalDate start, LocalDate end);
            }

            @Repository
            public interface TaskRepository extends JpaRepository<Task, Long> {
                List<Task> findByStatus(TaskStatus status);
                List<Task> findByPriority(TaskPriority priority);
                List<Task> findByDueDateBefore(LocalDate date);
            }

            @Repository
            public interface CustomerRepository extends JpaRepository<Customer, Long> {
                Optional<Customer> findByEmail(String email);
            }

            // 服务层使用
            @Singleton
            public class EmployeeService {
                private final EmployeeRepository employeeRepository;

                public EmployeeService(EmployeeRepository employeeRepository) {
                    this.employeeRepository = employeeRepository;
                }

                @Transactional
                public Employee createEmployee(String empNumber, String firstName,
                                             String lastName, String email) {
                    System.out.println("创建员工: " + empNumber);

                    Employee employee = new Employee(empNumber, firstName, lastName, email);
                    employee.setDepartment("Engineering");
                    employee.setPosition("Software Engineer");
                    employee.setSalary(new BigDecimal("80000.00"));

                    Employee saved = employeeRepository.save(employee);
                    System.out.println("员工已创建: " + saved.getId());

                    return saved;
                }

                public List<Employee> findByDepartment(String department) {
                    System.out.println("查询部门员工: " + department);
                    return employeeRepository.findByDepartment(department);
                }
            }
            ---
    b.关系映射
        a.一对一、一对多、多对多
            使用@OneToOne、@OneToMany、@ManyToOne、@ManyToMany注解定义实体间关系。支持级联操作、懒加载、fetch策略等配置,实现复杂的对象关系映射。
        b.关系映射示例
            ---
            // === 一对一关系 ===

            // 用户实体
            @Entity
            @Table(name = "users")
            public class User {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                @Column(unique = true, nullable = false)
                private String username;

                @Column(nullable = false)
                private String email;

                // 一对一关系 - 用户详情
                @OneToOne(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
                private UserProfile profile;

                // 构造函数
                public User() {}

                public User(String username, String email) {
                    this.username = username;
                    this.email = email;
                }

                // Getter和Setter省略
            }

            // 用户详情实体
            @Entity
            @Table(name = "user_profiles")
            public class UserProfile {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                @OneToOne(fetch = FetchType.LAZY)
                @JoinColumn(name = "user_id", unique = true, nullable = false)
                private User user;

                @Column(name = "full_name")
                private String fullName;

                @Column(name = "phone_number")
                private String phoneNumber;

                @Column
                private LocalDate birthDate;

                @Column(columnDefinition = "TEXT")
                private String bio;

                // Getter和Setter省略
            }

            // === 一对多 / 多对一关系 ===

            // 部门实体
            @Entity
            @Table(name = "departments")
            public class Department {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                @Column(unique = true, nullable = false)
                private String name;

                @Column
                private String description;

                // 一对多关系 - 部门有多个员工
                @OneToMany(mappedBy = "department", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
                private List<Employee> employees = new ArrayList<>();

                // 便捷方法
                public void addEmployee(Employee employee) {
                    employees.add(employee);
                    employee.setDepartment(this);
                }

                public void removeEmployee(Employee employee) {
                    employees.remove(employee);
                    employee.setDepartment(null);
                }

                // Getter和Setter省略
            }

            // 员工实体(扩展)
            @Entity
            @Table(name = "employees")
            public class Employee {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                @Column(nullable = false)
                private String name;

                // 多对一关系 - 员工属于一个部门
                @ManyToOne(fetch = FetchType.LAZY)
                @JoinColumn(name = "department_id")
                private Department department;

                // Getter和Setter省略
            }

            // === 多对多关系 ===

            // 学生实体
            @Entity
            @Table(name = "students")
            public class Student {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                @Column(nullable = false)
                private String name;

                @Column(unique = true)
                private String studentNumber;

                // 多对多关系 - 学生选修多门课程
                @ManyToMany(fetch = FetchType.LAZY)
                @JoinTable(
                    name = "student_courses",
                    joinColumns = @JoinColumn(name = "student_id"),
                    inverseJoinColumns = @JoinColumn(name = "course_id")
                )
                private Set<Course> courses = new HashSet<>();

                // 便捷方法
                public void enrollCourse(Course course) {
                    courses.add(course);
                    course.getStudents().add(this);
                }

                public void dropCourse(Course course) {
                    courses.remove(course);
                    course.getStudents().remove(this);
                }

                // Getter和Setter省略
            }

            // 课程实体
            @Entity
            @Table(name = "courses")
            public class Course {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                @Column(nullable = false)
                private String name;

                @Column(unique = true)
                private String courseCode;

                @Column
                private Integer credits;

                // 多对多关系 - 课程有多个学生
                @ManyToMany(mappedBy = "courses", fetch = FetchType.LAZY)
                private Set<Student> students = new HashSet<>();

                // Getter和Setter省略
            }

            // === 带属性的多对多关系 ===

            // 订单实体
            @Entity
            @Table(name = "orders")
            public class Order {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                @Column(name = "order_number")
                private String orderNumber;

                // 一对多关系 - 订单有多个订单项
                @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
                private List<OrderItem> orderItems = new ArrayList<>();

                // 便捷方法
                public void addOrderItem(Product product, Integer quantity, BigDecimal price) {
                    OrderItem orderItem = new OrderItem(this, product, quantity, price);
                    orderItems.add(orderItem);
                }

                // Getter和Setter省略
            }

            // 产品实体
            @Entity
            @Table(name = "products")
            public class Product {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                @Column(nullable = false)
                private String name;

                @Column(precision = 10, scale = 2)
                private BigDecimal price;

                // 一对多关系 - 产品在多个订单项中
                @OneToMany(mappedBy = "product")
                private List<OrderItem> orderItems = new ArrayList<>();

                // Getter和Setter省略
            }

            // 订单项实体 - 关联实体
            @Entity
            @Table(name = "order_items")
            public class OrderItem {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                // 多对一关系 - 订单
                @ManyToOne(fetch = FetchType.LAZY)
                @JoinColumn(name = "order_id", nullable = false)
                private Order order;

                // 多对一关系 - 产品
                @ManyToOne(fetch = FetchType.LAZY)
                @JoinColumn(name = "product_id", nullable = false)
                private Product product;

                @Column(nullable = false)
                private Integer quantity;

                @Column(precision = 10, scale = 2, nullable = false)
                private BigDecimal price;

                // 构造函数
                public OrderItem() {}

                public OrderItem(Order order, Product product, Integer quantity, BigDecimal price) {
                    this.order = order;
                    this.product = product;
                    this.quantity = quantity;
                    this.price = price;
                }

                // Getter和Setter省略
            }

            // Repository
            @Repository
            public interface DepartmentRepository extends JpaRepository<Department, Long> {
                Optional<Department> findByName(String name);

                @Query("SELECT d FROM Department d LEFT JOIN FETCH d.employees WHERE d.id = :id")
                Optional<Department> findByIdWithEmployees(@Param("id") Long id);
            }

            @Repository
            public interface StudentRepository extends JpaRepository<Student, Long> {
                Optional<Student> findByStudentNumber(String studentNumber);

                @Query("SELECT s FROM Student s LEFT JOIN FETCH s.courses WHERE s.id = :id")
                Optional<Student> findByIdWithCourses(@Param("id") Long id);
            }

            @Repository
            public interface OrderRepository extends JpaRepository<Order, Long> {
                @Query("SELECT o FROM Order o LEFT JOIN FETCH o.orderItems WHERE o.id = :id")
                Optional<Order> findByIdWithItems(@Param("id") Long id);
            }

            // 服务层使用
            @Singleton
            public class RelationshipService {
                private final DepartmentRepository departmentRepository;
                private final StudentRepository studentRepository;
                private final OrderRepository orderRepository;
                private final ProductRepository productRepository;

                public RelationshipService(DepartmentRepository departmentRepository,
                                         StudentRepository studentRepository,
                                         OrderRepository orderRepository,
                                         ProductRepository productRepository) {
                    this.departmentRepository = departmentRepository;
                    this.studentRepository = studentRepository;
                    this.orderRepository = orderRepository;
                    this.productRepository = productRepository;
                }

                // 一对多示例
                @Transactional
                public void demonstrateOneToMany() {
                    System.out.println("\n=== 一对多关系演示 ===");

                    // 创建部门
                    Department department = new Department();
                    department.setName("Engineering");
                    department.setDescription("Engineering Department");

                    // 创建员工
                    Employee emp1 = new Employee();
                    emp1.setName("John Doe");

                    Employee emp2 = new Employee();
                    emp2.setName("Jane Smith");

                    // 建立关系
                    department.addEmployee(emp1);
                    department.addEmployee(emp2);

                    // 保存(级联保存员工)
                    departmentRepository.save(department);
                    System.out.println("部门及员工已保存");
                }

                // 多对多示例
                @Transactional
                public void demonstrateManyToMany() {
                    System.out.println("\n=== 多对多关系演示 ===");

                    // 创建学生
                    Student student = new Student();
                    student.setName("Alice Johnson");
                    student.setStudentNumber("S001");

                    // 创建课程
                    Course course1 = new Course();
                    course1.setName("Java Programming");
                    course1.setCourseCode("CS101");

                    Course course2 = new Course();
                    course2.setName("Database Systems");
                    course2.setCourseCode("CS201");

                    // 学生选课
                    student.enrollCourse(course1);
                    student.enrollCourse(course2);

                    // 保存
                    studentRepository.save(student);
                    System.out.println("学生及选课已保存");
                }

                // 带属性的多对多示例
                @Transactional
                public void demonstrateOrderItems() {
                    System.out.println("\n=== 订单项关系演示 ===");

                    // 创建订单
                    Order order = new Order();
                    order.setOrderNumber("ORD-001");

                    // 获取产品
                    Product product1 = productRepository.findById(1L).orElseThrow();
                    Product product2 = productRepository.findById(2L).orElseThrow();

                    // 添加订单项
                    order.addOrderItem(product1, 2, product1.getPrice());
                    order.addOrderItem(product2, 1, product2.getPrice());

                    // 保存
                    orderRepository.save(order);
                    System.out.println("订单及订单项已保存");
                }
            }
            ---

02.EntityManager
    a.实体管理
        a.持久化上下文
            EntityManager管理实体的生命周期,包括托管、游离、删除状态。提供persist、merge、remove、find等方法操作实体,管理实体与数据库的同步。
        b.EntityManager使用示例
            ---
            import jakarta.persistence.EntityManager;
            import jakarta.persistence.TypedQuery;
            import jakarta.persistence.criteria.*;

            @Singleton
            public class EntityManagerService {
                private final EntityManager entityManager;

                public EntityManagerService(EntityManager entityManager) {
                    this.entityManager = entityManager;
                    System.out.println("EntityManagerService初始化");
                }

                // 持久化新实体
                @Transactional
                public Employee persistEmployee(Employee employee) {
                    System.out.println("持久化员工: " + employee.getName());

                    // persist将新实体添加到持久化上下文
                    entityManager.persist(employee);
                    System.out.println("  员工已添加到持久化上下文");

                    // flush将更改同步到数据库
                    entityManager.flush();
                    System.out.println("  更改已刷新到数据库, ID: " + employee.getId());

                    return employee;
                }

                // 查找实体
                @Transactional(readOnly = true)
                public Employee findEmployee(Long id) {
                    System.out.println("查找员工: " + id);

                    // find立即从数据库加载
                    Employee employee = entityManager.find(Employee.class, id);

                    if (employee != null) {
                        System.out.println("  找到员工: " + employee.getName());
                        System.out.println("  实体状态: 托管(Managed)");
                    } else {
                        System.out.println("  员工不存在");
                    }

                    return employee;
                }

                // 获取实体引用
                @Transactional(readOnly = true)
                public Employee getEmployeeReference(Long id) {
                    System.out.println("获取员工引用: " + id);

                    // getReference返回代理,不立即访问数据库
                    Employee employee = entityManager.getReference(Employee.class, id);
                    System.out.println("  获得代理对象");

                    // 访问属性时才真正加载
                    System.out.println("  员工姓名: " + employee.getName());

                    return employee;
                }

                // 合并游离实体
                @Transactional
                public Employee mergeEmployee(Employee detachedEmployee) {
                    System.out.println("合并游离实体: " + detachedEmployee.getId());

                    // merge将游离实体的状态合并到托管实体
                    Employee managedEmployee = entityManager.merge(detachedEmployee);
                    System.out.println("  实体已合并,状态: 托管(Managed)");

                    return managedEmployee;
                }

                // 刷新实体
                @Transactional
                public Employee refreshEmployee(Long id) {
                    System.out.println("刷新实体: " + id);

                    Employee employee = entityManager.find(Employee.class, id);
                    if (employee != null) {
                        // refresh从数据库重新加载实体状态
                        entityManager.refresh(employee);
                        System.out.println("  实体已从数据库刷新");
                    }

                    return employee;
                }

                // 分离实体
                @Transactional
                public Employee detachEmployee(Long id) {
                    System.out.println("分离实体: " + id);

                    Employee employee = entityManager.find(Employee.class, id);
                    if (employee != null) {
                        // detach将实体从持久化上下文移除
                        entityManager.detach(employee);
                        System.out.println("  实体已分离,状态: 游离(Detached)");

                        // 对游离实体的修改不会同步到数据库
                        employee.setName("Modified Name");
                        System.out.println("  修改游离实体(不会保存到数据库)");
                    }

                    return employee;
                }

                // 删除实体
                @Transactional
                public void removeEmployee(Long id) {
                    System.out.println("删除实体: " + id);

                    Employee employee = entityManager.find(Employee.class, id);
                    if (employee != null) {
                        // remove标记实体为删除状态
                        entityManager.remove(employee);
                        System.out.println("  实体已标记删除");

                        // flush执行实际的DELETE语句
                        entityManager.flush();
                        System.out.println("  DELETE语句已执行");
                    }
                }

                // 检查实体是否被管理
                @Transactional
                public void checkEntityState(Long id) {
                    System.out.println("\n=== 检查实体状态 ===");

                    Employee employee = entityManager.find(Employee.class, id);
                    System.out.println("1. find后: " + (entityManager.contains(employee) ? "托管" : "游离"));

                    entityManager.detach(employee);
                    System.out.println("2. detach后: " + (entityManager.contains(employee) ? "托管" : "游离"));

                    Employee merged = entityManager.merge(employee);
                    System.out.println("3. merge后: " + (entityManager.contains(merged) ? "托管" : "游离"));
                }

                // 清空持久化上下文
                @Transactional
                public void clearPersistenceContext() {
                    System.out.println("清空持久化上下文");

                    // clear分离所有托管实体
                    entityManager.clear();
                    System.out.println("  所有实体已分离");
                }

                // 手动刷新
                @Transactional
                public void manualFlush() {
                    System.out.println("手动刷新演示");

                    Employee employee = new Employee();
                    employee.setName("Test Employee");
                    entityManager.persist(employee);
                    System.out.println("  实体已persist (未刷新到数据库)");

                    // 手动刷新
                    entityManager.flush();
                    System.out.println("  已刷新到数据库, ID: " + employee.getId());
                }

                // 实体生命周期演示
                @Transactional
                public void demonstrateEntityLifecycle() {
                    System.out.println("\n=== 实体生命周期演示 ===");

                    // 1. 新建(New)状态
                    Employee employee = new Employee();
                    employee.setName("Lifecycle Demo");
                    System.out.println("1. 新建状态: contains=" + entityManager.contains(employee));

                    // 2. 托管(Managed)状态
                    entityManager.persist(employee);
                    System.out.println("2. persist后: contains=" + entityManager.contains(employee));

                    // 3. 修改托管实体
                    employee.setName("Modified Name");
                    System.out.println("3. 修改托管实体(自动同步)");

                    // 4. 刷新到数据库
                    entityManager.flush();
                    System.out.println("4. flush后: ID=" + employee.getId());

                    // 5. 分离(Detached)状态
                    entityManager.detach(employee);
                    System.out.println("5. detach后: contains=" + entityManager.contains(employee));

                    // 6. 重新托管
                    Employee managed = entityManager.merge(employee);
                    System.out.println("6. merge后: contains=" + entityManager.contains(managed));

                    // 7. 删除(Removed)状态
                    entityManager.remove(managed);
                    System.out.println("7. remove后: 标记为删除");
                }
            }
            ---
    b.JPQL查询
        a.对象查询语言
            JPQL是面向对象的查询语言,使用实体和属性而非表和列。支持SELECT、UPDATE、DELETE操作,提供丰富的查询功能如聚合、分组、排序、子查询等。
        b.JPQL查询示例
            ---
            @Singleton
            public class JPQLQueryService {
                private final EntityManager entityManager;

                public JPQLQueryService(EntityManager entityManager) {
                    this.entityManager = entityManager;
                }

                // 基础查询
                @Transactional(readOnly = true)
                public List<Employee> findAllEmployees() {
                    System.out.println("JPQL: 查询所有员工");

                    String jpql = "SELECT e FROM Employee e";
                    TypedQuery<Employee> query = entityManager.createQuery(jpql, Employee.class);

                    List<Employee> results = query.getResultList();
                    System.out.println("  找到 " + results.size() + " 个员工");

                    return results;
                }

                // 条件查询
                @Transactional(readOnly = true)
                public List<Employee> findEmployeesByDepartment(String department) {
                    System.out.println("JPQL: 按部门查询");

                    String jpql = "SELECT e FROM Employee e WHERE e.department = :dept";
                    TypedQuery<Employee> query = entityManager.createQuery(jpql, Employee.class);
                    query.setParameter("dept", department);

                    return query.getResultList();
                }

                // 多条件查询
                @Transactional(readOnly = true)
                public List<Employee> findEmployeesWithCriteria(String department, BigDecimal minSalary) {
                    System.out.println("JPQL: 多条件查询");

                    String jpql = "SELECT e FROM Employee e " +
                                 "WHERE e.department = :dept AND e.salary >= :minSalary " +
                                 "ORDER BY e.salary DESC";

                    TypedQuery<Employee> query = entityManager.createQuery(jpql, Employee.class);
                    query.setParameter("dept", department);
                    query.setParameter("minSalary", minSalary);

                    return query.getResultList();
                }

                // 聚合查询
                @Transactional(readOnly = true)
                public Map<String, Object> getEmployeeStatistics() {
                    System.out.println("JPQL: 聚合查询");

                    // 统计员工总数
                    String countJpql = "SELECT COUNT(e) FROM Employee e WHERE e.active = true";
                    Long count = entityManager.createQuery(countJpql, Long.class).getSingleResult();

                    // 计算平均工资
                    String avgJpql = "SELECT AVG(e.salary) FROM Employee e WHERE e.active = true";
                    Double avgSalary = entityManager.createQuery(avgJpql, Double.class).getSingleResult();

                    // 最高工资
                    String maxJpql = "SELECT MAX(e.salary) FROM Employee e";
                    BigDecimal maxSalary = entityManager.createQuery(maxJpql, BigDecimal.class).getSingleResult();

                    // 最低工资
                    String minJpql = "SELECT MIN(e.salary) FROM Employee e WHERE e.active = true";
                    BigDecimal minSalary = entityManager.createQuery(minJpql, BigDecimal.class).getSingleResult();

                    Map<String, Object> stats = new HashMap<>();
                    stats.put("totalEmployees", count);
                    stats.put("averageSalary", avgSalary);
                    stats.put("maxSalary", maxSalary);
                    stats.put("minSalary", minSalary);

                    System.out.println("  统计结果: " + stats);
                    return stats;
                }

                // 分组查询
                @Transactional(readOnly = true)
                public List<Object[]> getEmployeeCountByDepartment() {
                    System.out.println("JPQL: 分组查询");

                    String jpql = "SELECT e.department, COUNT(e), AVG(e.salary) " +
                                 "FROM Employee e " +
                                 "WHERE e.active = true " +
                                 "GROUP BY e.department " +
                                 "HAVING COUNT(e) > 0 " +
                                 "ORDER BY COUNT(e) DESC";

                    List<Object[]> results = entityManager.createQuery(jpql).getResultList();

                    System.out.println("  部门统计:");
                    for (Object[] row : results) {
                        System.out.println("    " + row[0] + ": " + row[1] + " 人, 平均工资: " + row[2]);
                    }

                    return results;
                }

                // 连接查询
                @Transactional(readOnly = true)
                public List<Employee> findEmployeesWithDepartment() {
                    System.out.println("JPQL: 连接查询");

                    String jpql = "SELECT e FROM Employee e " +
                                 "JOIN FETCH e.department d " +
                                 "WHERE d.name = :deptName";

                    TypedQuery<Employee> query = entityManager.createQuery(jpql, Employee.class);
                    query.setParameter("deptName", "Engineering");

                    return query.getResultList();
                }

                // 子查询
                @Transactional(readOnly = true)
                public List<Employee> findHighEarners() {
                    System.out.println("JPQL: 子查询");

                    String jpql = "SELECT e FROM Employee e " +
                                 "WHERE e.salary > (SELECT AVG(e2.salary) FROM Employee e2)";

                    TypedQuery<Employee> query = entityManager.createQuery(jpql, Employee.class);
                    return query.getResultList();
                }

                // 更新查询
                @Transactional
                public int updateEmployeeSalary(String department, BigDecimal increment) {
                    System.out.println("JPQL: 批量更新");

                    String jpql = "UPDATE Employee e " +
                                 "SET e.salary = e.salary + :increment " +
                                 "WHERE e.department = :dept";

                    int updated = entityManager.createQuery(jpql)
                        .setParameter("increment", increment)
                        .setParameter("dept", department)
                        .executeUpdate();

                    System.out.println("  更新了 " + updated + " 个员工");
                    return updated;
                }

                // 删除查询
                @Transactional
                public int deleteInactiveEmployees(LocalDate before) {
                    System.out.println("JPQL: 批量删除");

                    String jpql = "DELETE FROM Employee e " +
                                 "WHERE e.active = false AND e.hireDate < :date";

                    int deleted = entityManager.createQuery(jpql)
                        .setParameter("date", before)
                        .executeUpdate();

                    System.out.println("  删除了 " + deleted + " 个员工");
                    return deleted;
                }

                // 分页查询
                @Transactional(readOnly = true)
                public List<Employee> findEmployeesWithPagination(int page, int size) {
                    System.out.println("JPQL: 分页查询");

                    String jpql = "SELECT e FROM Employee e ORDER BY e.id";
                    TypedQuery<Employee> query = entityManager.createQuery(jpql, Employee.class);

                    query.setFirstResult(page * size);
                    query.setMaxResults(size);

                    List<Employee> results = query.getResultList();
                    System.out.println("  第 " + page + " 页, 共 " + results.size() + " 条");

                    return results;
                }

                // 命名查询
                @Transactional(readOnly = true)
                public List<Employee> useNamedQuery(String department) {
                    System.out.println("JPQL: 使用命名查询");

                    TypedQuery<Employee> query = entityManager.createNamedQuery(
                        "Employee.findByDepartment",
                        Employee.class
                    );
                    query.setParameter("dept", department);

                    return query.getResultList();
                }
            }

            // 在Employee实体中定义命名查询
            @Entity
            @Table(name = "employees")
            @NamedQueries({
                @NamedQuery(
                    name = "Employee.findByDepartment",
                    query = "SELECT e FROM Employee e WHERE e.department = :dept"
                ),
                @NamedQuery(
                    name = "Employee.findActive",
                    query = "SELECT e FROM Employee e WHERE e.active = true ORDER BY e.name"
                )
            })
            public class Employee {
                // ... 实体定义
            }
            ---

03.Criteria API
    a.类型安全查询
        a.Criteria构建器
            Criteria API提供类型安全的查询构建方式,通过Java代码而非字符串构建查询。编译时检查类型错误,支持动态查询条件组合,适合复杂查询场景。
        b.Criteria查询示例
            ---
            @Singleton
            public class CriteriaQueryService {
                private final EntityManager entityManager;

                public CriteriaQueryService(EntityManager entityManager) {
                    this.entityManager = entityManager;
                }

                // 基础Criteria查询
                @Transactional(readOnly = true)
                public List<Employee> findAllWithCriteria() {
                    System.out.println("Criteria: 查询所有员工");

                    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
                    CriteriaQuery<Employee> cq = cb.createQuery(Employee.class);
                    Root<Employee> root = cq.from(Employee.class);

                    cq.select(root);

                    TypedQuery<Employee> query = entityManager.createQuery(cq);
                    return query.getResultList();
                }

                // 条件查询
                @Transactional(readOnly = true)
                public List<Employee> findByDepartmentWithCriteria(String department) {
                    System.out.println("Criteria: 按部门查询");

                    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
                    CriteriaQuery<Employee> cq = cb.createQuery(Employee.class);
                    Root<Employee> root = cq.from(Employee.class);

                    // 构建WHERE条件
                    Predicate predicate = cb.equal(root.get("department"), department);
                    cq.where(predicate);

                    return entityManager.createQuery(cq).getResultList();
                }

                // 多条件组合
                @Transactional(readOnly = true)
                public List<Employee> findWithMultipleConditions(
                    String department, BigDecimal minSalary, Boolean active) {

                    System.out.println("Criteria: 多条件查询");

                    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
                    CriteriaQuery<Employee> cq = cb.createQuery(Employee.class);
                    Root<Employee> root = cq.from(Employee.class);

                    List<Predicate> predicates = new ArrayList<>();

                    // 添加部门条件
                    if (department != null) {
                        predicates.add(cb.equal(root.get("department"), department));
                    }

                    // 添加工资条件
                    if (minSalary != null) {
                        predicates.add(cb.greaterThanOrEqualTo(root.get("salary"), minSalary));
                    }

                    // 添加状态条件
                    if (active != null) {
                        predicates.add(cb.equal(root.get("active"), active));
                    }

                    // 组合所有条件(AND)
                    cq.where(predicates.toArray(new Predicate[0]));

                    // 排序
                    cq.orderBy(cb.desc(root.get("salary")));

                    return entityManager.createQuery(cq).getResultList();
                }

                // OR条件
                @Transactional(readOnly = true)
                public List<Employee> findWithOrConditions(String dept1, String dept2) {
                    System.out.println("Criteria: OR条件查询");

                    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
                    CriteriaQuery<Employee> cq = cb.createQuery(Employee.class);
                    Root<Employee> root = cq.from(Employee.class);

                    // OR条件
                    Predicate or = cb.or(
                        cb.equal(root.get("department"), dept1),
                        cb.equal(root.get("department"), dept2)
                    );

                    cq.where(or);
                    return entityManager.createQuery(cq).getResultList();
                }

                // LIKE查询
                @Transactional(readOnly = true)
                public List<Employee> searchByName(String keyword) {
                    System.out.println("Criteria: LIKE查询");

                    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
                    CriteriaQuery<Employee> cq = cb.createQuery(Employee.class);
                    Root<Employee> root = cq.from(Employee.class);

                    // LIKE条件
                    Predicate like = cb.like(
                        cb.lower(root.get("name")),
                        "%" + keyword.toLowerCase() + "%"
                    );

                    cq.where(like);
                    return entityManager.createQuery(cq).getResultList();
                }

                // 范围查询
                @Transactional(readOnly = true)
                public List<Employee> findBySalaryRange(BigDecimal min, BigDecimal max) {
                    System.out.println("Criteria: 范围查询");

                    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
                    CriteriaQuery<Employee> cq = cb.createQuery(Employee.class);
                    Root<Employee> root = cq.from(Employee.class);

                    // BETWEEN条件
                    Predicate between = cb.between(root.get("salary"), min, max);
                    cq.where(between);

                    return entityManager.createQuery(cq).getResultList();
                }

                // 聚合查询
                @Transactional(readOnly = true)
                public Long countEmployeesByDepartment(String department) {
                    System.out.println("Criteria: 统计查询");

                    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
                    CriteriaQuery<Long> cq = cb.createQuery(Long.class);
                    Root<Employee> root = cq.from(Employee.class);

                    // COUNT聚合
                    cq.select(cb.count(root));
                    cq.where(cb.equal(root.get("department"), department));

                    return entityManager.createQuery(cq).getSingleResult();
                }

                // 分组查询
                @Transactional(readOnly = true)
                public List<Object[]> getAverageSalaryByDepartment() {
                    System.out.println("Criteria: 分组查询");

                    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
                    CriteriaQuery<Object[]> cq = cb.createQuery(Object[].class);
                    Root<Employee> root = cq.from(Employee.class);

                    // 选择部门和平均工资
                    cq.multiselect(
                        root.get("department"),
                        cb.avg(root.get("salary"))
                    );

                    // 按部门分组
                    cq.groupBy(root.get("department"));

                    // HAVING条件
                    cq.having(cb.gt(cb.count(root), 0));

                    return entityManager.createQuery(cq).getResultList();
                }

                // 连接查询
                @Transactional(readOnly = true)
                public List<Employee> findEmployeesWithDepartmentCriteria() {
                    System.out.println("Criteria: 连接查询");

                    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
                    CriteriaQuery<Employee> cq = cb.createQuery(Employee.class);
                    Root<Employee> root = cq.from(Employee.class);

                    // JOIN FETCH
                    root.fetch("department", JoinType.LEFT);

                    cq.select(root);
                    return entityManager.createQuery(cq).getResultList();
                }

                // 排序
                @Transactional(readOnly = true)
                public List<Employee> findWithSort(boolean ascending) {
                    System.out.println("Criteria: 排序查询");

                    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
                    CriteriaQuery<Employee> cq = cb.createQuery(Employee.class);
                    Root<Employee> root = cq.from(Employee.class);

                    cq.select(root);

                    // 动态排序
                    if (ascending) {
                        cq.orderBy(cb.asc(root.get("salary")));
                    } else {
                        cq.orderBy(cb.desc(root.get("salary")));
                    }

                    return entityManager.createQuery(cq).getResultList();
                }

                // 分页
                @Transactional(readOnly = true)
                public List<Employee> findWithPagination(int page, int size) {
                    System.out.println("Criteria: 分页查询");

                    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
                    CriteriaQuery<Employee> cq = cb.createQuery(Employee.class);
                    Root<Employee> root = cq.from(Employee.class);

                    cq.select(root);
                    cq.orderBy(cb.asc(root.get("id")));

                    TypedQuery<Employee> query = entityManager.createQuery(cq);
                    query.setFirstResult(page * size);
                    query.setMaxResults(size);

                    return query.getResultList();
                }

                // 动态查询构建器
                @Transactional(readOnly = true)
                public List<Employee> dynamicSearch(EmployeeSearchCriteria criteria) {
                    System.out.println("Criteria: 动态搜索");

                    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
                    CriteriaQuery<Employee> cq = cb.createQuery(Employee.class);
                    Root<Employee> root = cq.from(Employee.class);

                    List<Predicate> predicates = new ArrayList<>();

                    // 姓名搜索
                    if (criteria.getName() != null && !criteria.getName().isEmpty()) {
                        predicates.add(cb.like(
                            cb.lower(root.get("name")),
                            "%" + criteria.getName().toLowerCase() + "%"
                        ));
                    }

                    // 部门筛选
                    if (criteria.getDepartment() != null) {
                        predicates.add(cb.equal(root.get("department"), criteria.getDepartment()));
                    }

                    // 工资范围
                    if (criteria.getMinSalary() != null) {
                        predicates.add(cb.greaterThanOrEqualTo(
                            root.get("salary"),
                            criteria.getMinSalary()
                        ));
                    }
                    if (criteria.getMaxSalary() != null) {
                        predicates.add(cb.lessThanOrEqualTo(
                            root.get("salary"),
                            criteria.getMaxSalary()
                        ));
                    }

                    // 入职日期范围
                    if (criteria.getHireDateFrom() != null) {
                        predicates.add(cb.greaterThanOrEqualTo(
                            root.get("hireDate"),
                            criteria.getHireDateFrom()
                        ));
                    }
                    if (criteria.getHireDateTo() != null) {
                        predicates.add(cb.lessThanOrEqualTo(
                            root.get("hireDate"),
                            criteria.getHireDateTo()
                        ));
                    }

                    // 状态筛选
                    if (criteria.getActive() != null) {
                        predicates.add(cb.equal(root.get("active"), criteria.getActive()));
                    }

                    // 组合所有条件
                    cq.where(predicates.toArray(new Predicate[0]));

                    // 排序
                    if (criteria.getSortBy() != null) {
                        if (criteria.isAscending()) {
                            cq.orderBy(cb.asc(root.get(criteria.getSortBy())));
                        } else {
                            cq.orderBy(cb.desc(root.get(criteria.getSortBy())));
                        }
                    }

                    TypedQuery<Employee> query = entityManager.createQuery(cq);

                    // 分页
                    if (criteria.getPage() != null && criteria.getSize() != null) {
                        query.setFirstResult(criteria.getPage() * criteria.getSize());
                        query.setMaxResults(criteria.getSize());
                    }

                    return query.getResultList();
                }
            }

            // 搜索条件对象
            public class EmployeeSearchCriteria {
                private String name;
                private String department;
                private BigDecimal minSalary;
                private BigDecimal maxSalary;
                private LocalDate hireDateFrom;
                private LocalDate hireDateTo;
                private Boolean active;
                private String sortBy;
                private boolean ascending = true;
                private Integer page;
                private Integer size;

                // Getter和Setter省略
            }
            ---
    b.动态查询构建
        a.条件组合器
            使用Specification模式或Predicate组合实现灵活的动态查询构建。根据运行时条件动态添加查询子句,避免硬编码大量查询方法。
        b.Specification模式示例
            ---
            import io.micronaut.data.jpa.repository.criteria.Specification;

            // Specification工具类
            public class EmployeeSpecifications {

                public static Specification<Employee> hasName(String name) {
                    return (root, query, cb) -> {
                        if (name == null || name.isEmpty()) {
                            return cb.conjunction();
                        }
                        return cb.like(cb.lower(root.get("name")),
                                      "%" + name.toLowerCase() + "%");
                    };
                }

                public static Specification<Employee> hasDepartment(String department) {
                    return (root, query, cb) -> {
                        if (department == null) {
                            return cb.conjunction();
                        }
                        return cb.equal(root.get("department"), department);
                    };
                }

                public static Specification<Employee> salaryBetween(BigDecimal min, BigDecimal max) {
                    return (root, query, cb) -> {
                        if (min == null && max == null) {
                            return cb.conjunction();
                        }
                        if (min != null && max != null) {
                            return cb.between(root.get("salary"), min, max);
                        }
                        if (min != null) {
                            return cb.greaterThanOrEqualTo(root.get("salary"), min);
                        }
                        return cb.lessThanOrEqualTo(root.get("salary"), max);
                    };
                }

                public static Specification<Employee> isActive(Boolean active) {
                    return (root, query, cb) -> {
                        if (active == null) {
                            return cb.conjunction();
                        }
                        return cb.equal(root.get("active"), active);
                    };
                }

                public static Specification<Employee> hiredAfter(LocalDate date) {
                    return (root, query, cb) -> {
                        if (date == null) {
                            return cb.conjunction();
                        }
                        return cb.greaterThanOrEqualTo(root.get("hireDate"), date);
                    };
                }
            }

            // 使用Specification
            @Singleton
            public class EmployeeSpecificationService {
                private final EmployeeRepository employeeRepository;

                public EmployeeSpecificationService(EmployeeRepository employeeRepository) {
                    this.employeeRepository = employeeRepository;
                }

                public List<Employee> searchEmployees(String name, String department,
                                                     BigDecimal minSalary, BigDecimal maxSalary) {
                    System.out.println("Specification搜索");

                    // 组合多个Specification
                    Specification<Employee> spec = Specification
                        .where(EmployeeSpecifications.hasName(name))
                        .and(EmployeeSpecifications.hasDepartment(department))
                        .and(EmployeeSpecifications.salaryBetween(minSalary, maxSalary))
                        .and(EmployeeSpecifications.isActive(true));

                    return employeeRepository.findAll(spec);
                }

                public List<Employee> complexSearch(EmployeeSearchCriteria criteria) {
                    System.out.println("复杂Specification搜索");

                    Specification<Employee> spec = Specification.where(null);

                    if (criteria.getName() != null) {
                        spec = spec.and(EmployeeSpecifications.hasName(criteria.getName()));
                    }

                    if (criteria.getDepartment() != null) {
                        spec = spec.and(EmployeeSpecifications.hasDepartment(criteria.getDepartment()));
                    }

                    if (criteria.getMinSalary() != null || criteria.getMaxSalary() != null) {
                        spec = spec.and(EmployeeSpecifications.salaryBetween(
                            criteria.getMinSalary(),
                            criteria.getMaxSalary()
                        ));
                    }

                    if (criteria.getHireDateFrom() != null) {
                        spec = spec.and(EmployeeSpecifications.hiredAfter(criteria.getHireDateFrom()));
                    }

                    if (criteria.getActive() != null) {
                        spec = spec.and(EmployeeSpecifications.isActive(criteria.getActive()));
                    }

                    return employeeRepository.findAll(spec);
                }
            }
            ---

5.4 JDBC支持

01.JDBC配置
    a.数据源配置
        a.连接池设置
            配置JDBC数据源和连接池,包括URL、驱动、用户名、密码、连接池大小等参数。Micronaut Data JDBC提供轻量级的数据访问方式,无需JPA的额外开销。
        b.JDBC配置示例
            ---
            // build.gradle - JDBC依赖
            dependencies {
                annotationProcessor("io.micronaut.data:micronaut-data-processor")
                implementation("io.micronaut.data:micronaut-data-jdbc")
                implementation("io.micronaut.sql:micronaut-jdbc-hikari")
                runtimeOnly("mysql:mysql-connector-java")
            }

            // application.yml - JDBC配置
            datasources:
              default:
                url: jdbc:mysql://localhost:3306/mydb
                driverClassName: com.mysql.cj.jdbc.Driver
                username: root
                password: ${DB_PASSWORD}
                dialect: MYSQL
                # HikariCP连接池配置
                maximum-pool-size: 10
                minimum-idle: 2
                connection-timeout: 30000
                idle-timeout: 600000
                max-lifetime: 1800000

            // JDBC实体
            import io.micronaut.data.annotation.*;
            import io.micronaut.data.model.naming.NamingStrategies;

            @MappedEntity(value = "products", namingStrategy = NamingStrategies.UnderScoreSeparated.class)
            public class Product {
                @Id
                @GeneratedValue
                private Long id;

                private String name;
                private BigDecimal price;
                private Integer stock;
                private String category;

                @DateCreated
                private LocalDateTime createdAt;

                @DateUpdated
                private LocalDateTime updatedAt;

                // 构造函数
                public Product() {}

                public Product(String name, BigDecimal price, Integer stock) {
                    this.name = name;
                    this.price = price;
                    this.stock = stock;
                }

                // Getter和Setter省略
            }

            // JDBC Repository
            import io.micronaut.data.jdbc.annotation.JdbcRepository;
            import io.micronaut.data.model.query.builder.sql.Dialect;

            @JdbcRepository(dialect = Dialect.MYSQL)
            public interface ProductRepository extends CrudRepository<Product, Long> {
                List<Product> findByCategory(String category);
                List<Product> findByPriceBetween(BigDecimal min, BigDecimal max);
                Optional<Product> findByName(String name);

                @Query("SELECT * FROM products WHERE stock < :threshold")
                List<Product> findLowStock(int threshold);
            }

            // JDBC服务
            @Singleton
            public class ProductJdbcService {
                private final ProductRepository productRepository;

                public ProductJdbcService(ProductRepository productRepository) {
                    this.productRepository = productRepository;
                    System.out.println("ProductJdbcService初始化");
                }

                @Transactional
                public Product createProduct(String name, BigDecimal price, Integer stock) {
                    System.out.println("JDBC创建产品: " + name);

                    Product product = new Product(name, price, stock);
                    product.setCategory("Electronics");

                    Product saved = productRepository.save(product);
                    System.out.println("  产品已保存, ID: " + saved.getId());

                    return saved;
                }

                public List<Product> findByCategory(String category) {
                    System.out.println("JDBC查询分类: " + category);
                    return productRepository.findByCategory(category);
                }

                public List<Product> findLowStockProducts() {
                    System.out.println("JDBC查询低库存产品");
                    return productRepository.findLowStock(10);
                }
            }
            ---
    b.原生SQL
        a.@Query原生SQL
            使用@Query注解编写原生SQL语句,直接操作数据库。支持命名参数、位置参数,适合需要数据库特定功能或优化查询的场景。
        b.原生SQL示例
            ---
            @JdbcRepository(dialect = Dialect.MYSQL)
            public interface NativeSQLRepository extends CrudRepository<Product, Long> {

                // 原生SQL查询
                @Query(value = "SELECT * FROM products WHERE price > :price ORDER BY price DESC",
                       nativeQuery = true)
                List<Product> findExpensiveProducts(BigDecimal price);

                // 原生SQL聚合
                @Query(value = "SELECT category, COUNT(*), AVG(price) FROM products GROUP BY category",
                       nativeQuery = true)
                List<Map<String, Object>> getCategoryStatistics();

                // 原生SQL更新
                @Query(value = "UPDATE products SET stock = stock + :amount WHERE id = :id",
                       nativeQuery = true)
                int increaseStock(Long id, int amount);

                // 原生SQL删除
                @Query(value = "DELETE FROM products WHERE stock = 0 AND created_at < :date",
                       nativeQuery = true)
                int deleteZeroStockProducts(LocalDateTime date);

                // MySQL特定功能 - 全文搜索
                @Query(value = "SELECT * FROM products WHERE MATCH(name, description) " +
                              "AGAINST(:keyword IN NATURAL LANGUAGE MODE)",
                       nativeQuery = true)
                List<Product> fullTextSearch(String keyword);
            }

            @Singleton
            public class NativeSQLService {
                private final NativeSQLRepository repository;

                public NativeSQLService(NativeSQLRepository repository) {
                    this.repository = repository;
                }

                public void demonstrateNativeSQL() {
                    System.out.println("=== 原生SQL演示 ===");

                    // 查询贵重产品
                    List<Product> expensive = repository.findExpensiveProducts(
                        new BigDecimal("1000")
                    );
                    System.out.println("贵重产品数: " + expensive.size());

                    // 分类统计
                    List<Map<String, Object>> stats = repository.getCategoryStatistics();
                    stats.forEach(stat ->
                        System.out.println("  " + stat.get("category") + ": " +
                                         stat.get("COUNT(*)") + " 个, 平均价格: " +
                                         stat.get("AVG(price)"))
                    );

                    // 增加库存
                    int updated = repository.increaseStock(1L, 50);
                    System.out.println("更新库存: " + updated + " 条记录");
                }
            }
            ---

02.批量操作
    a.批量插入
        a.saveAll批量保存
            使用saveAll方法批量保存实体,JDBC实现通过批处理优化多条INSERT语句的执行,提升大量数据插入的性能。
        b.批量插入示例
            ---
            @Singleton
            public class BatchInsertService {
                private final ProductRepository productRepository;

                public BatchInsertService(ProductRepository productRepository) {
                    this.productRepository = productRepository;
                }

                @Transactional
                public List<Product> batchInsert(int count) {
                    System.out.println("批量插入: " + count + " 个产品");

                    List<Product> products = new ArrayList<>();
                    for (int i = 0; i < count; i++) {
                        Product product = new Product();
                        product.setName("Product " + i);
                        product.setPrice(BigDecimal.valueOf(100 + i));
                        product.setStock(100);
                        product.setCategory("Category" + (i % 5));
                        products.add(product);
                    }

                    long start = System.currentTimeMillis();
                    Iterable<Product> saved = productRepository.saveAll(products);
                    long duration = System.currentTimeMillis() - start;

                    List<Product> result = new ArrayList<>();
                    saved.forEach(result::add);

                    System.out.println("  批量插入完成: " + duration + "ms");
                    System.out.println("  平均: " + (duration * 1.0 / count) + "ms/条");

                    return result;
                }

                @Transactional
                public void batchUpdate(List<Long> ids, String newCategory) {
                    System.out.println("批量更新: " + ids.size() + " 个产品");

                    List<Product> products = new ArrayList<>();
                    for (Long id : ids) {
                        Product product = productRepository.findById(id).orElse(null);
                        if (product != null) {
                            product.setCategory(newCategory);
                            products.add(product);
                        }
                    }

                    productRepository.updateAll(products);
                    System.out.println("  批量更新完成");
                }
            }
            ---
    b.批量更新和删除
        a.批量操作优化
            使用批量更新和删除方法减少数据库交互次数,通过单条SQL语句处理多条记录,显著提升大批量数据操作的性能。
        b.批量操作示例
            ---
            @JdbcRepository(dialect = Dialect.MYSQL)
            public interface BatchOperationRepository extends CrudRepository<Product, Long> {

                // 批量更新
                @Query("UPDATE products SET stock = stock - :amount WHERE id IN (:ids)")
                int decreaseStockBatch(List<Long> ids, int amount);

                @Query("UPDATE products SET category = :category WHERE id IN (:ids)")
                int updateCategoryBatch(List<Long> ids, String category);

                // 批量删除
                @Query("DELETE FROM products WHERE id IN (:ids)")
                int deleteBatch(List<Long> ids);

                void deleteAll(Iterable<Product> products);
            }

            @Singleton
            public class BatchOperationService {
                private final BatchOperationRepository repository;

                public BatchOperationService(BatchOperationRepository repository) {
                    this.repository = repository;
                }

                @Transactional
                public void batchDecreaseStock(List<Long> productIds, int amount) {
                    System.out.println("批量减少库存: " + productIds.size() + " 个产品");

                    int updated = repository.decreaseStockBatch(productIds, amount);
                    System.out.println("  更新了 " + updated + " 条记录");
                }

                @Transactional
                public void batchDelete(List<Long> ids) {
                    System.out.println("批量删除: " + ids.size() + " 个产品");

                    int deleted = repository.deleteBatch(ids);
                    System.out.println("  删除了 " + deleted + " 条记录");
                }
            }
            ---

03.事务管理
    a.@Transactional
        a.声明式事务
            使用@Transactional注解声明事务边界,支持事务传播、隔离级别、只读事务等配置。框架自动管理事务的开启、提交、回滚。
        b.事务管理示例
            ---
            @Singleton
            public class TransactionService {
                private final ProductRepository productRepository;
                private final OrderRepository orderRepository;

                public TransactionService(ProductRepository productRepository,
                                        OrderRepository orderRepository) {
                    this.productRepository = productRepository;
                    this.orderRepository = orderRepository;
                }

                // 基础事务
                @Transactional
                public void createOrder(Long productId, int quantity) {
                    System.out.println("创建订单(事务)");

                    // 减少库存
                    Product product = productRepository.findById(productId)
                        .orElseThrow(() -> new IllegalArgumentException("产品不存在"));

                    if (product.getStock() < quantity) {
                        throw new IllegalStateException("库存不足");
                    }

                    product.setStock(product.getStock() - quantity);
                    productRepository.update(product);

                    // 创建订单
                    Order order = new Order();
                    order.setProductId(productId);
                    order.setQuantity(quantity);
                    order.setTotal(product.getPrice().multiply(BigDecimal.valueOf(quantity)));
                    orderRepository.save(order);

                    System.out.println("  订单创建成功(事务提交)");
                }

                // 只读事务
                @Transactional(readOnly = true)
                public List<Product> findAllProducts() {
                    System.out.println("查询所有产品(只读事务)");
                    return productRepository.findAll();
                }

                // 事务回滚
                @Transactional
                public void failingOperation() {
                    System.out.println("失败操作(事务回滚)");

                    Product product = new Product("Test", BigDecimal.TEN, 100);
                    productRepository.save(product);

                    // 抛出异常,触发回滚
                    throw new RuntimeException("模拟异常");
                }

                // 嵌套事务
                @Transactional
                public void outerTransaction() {
                    System.out.println("外层事务");
                    Product product = new Product("Outer", BigDecimal.TEN, 100);
                    productRepository.save(product);

                    try {
                        innerTransaction();
                    } catch (Exception e) {
                        System.out.println("  内层事务失败,但外层继续");
                    }

                    System.out.println("  外层事务完成");
                }

                @Transactional(propagation = Propagation.REQUIRES_NEW)
                public void innerTransaction() {
                    System.out.println("  内层事务(独立事务)");
                    Product product = new Product("Inner", BigDecimal.TEN, 100);
                    productRepository.save(product);
                    throw new RuntimeException("内层失败");
                }
            }
            ---
    b.编程式事务
        a.TransactionOperations
            使用TransactionOperations接口编程式控制事务,提供更灵活的事务管理方式。适合需要动态控制事务边界或复杂事务逻辑的场景。
        b.编程式事务示例
            ---
            import io.micronaut.transaction.TransactionOperations;
            import io.micronaut.transaction.TransactionStatus;

            @Singleton
            public class ProgrammaticTransactionService {
                private final TransactionOperations<Connection> transactionManager;
                private final ProductRepository productRepository;

                public ProgrammaticTransactionService(
                    TransactionOperations<Connection> transactionManager,
                    ProductRepository productRepository) {
                    this.transactionManager = transactionManager;
                    this.productRepository = productRepository;
                }

                public void executeInTransaction() {
                    System.out.println("编程式事务");

                    transactionManager.executeWrite(status -> {
                        System.out.println("  事务已开始");

                        Product product = new Product("Test", BigDecimal.TEN, 100);
                        productRepository.save(product);
                        System.out.println("  产品已保存");

                        return product;
                    });

                    System.out.println("  事务已提交");
                }

                public void conditionalTransaction(boolean shouldCommit) {
                    System.out.println("条件事务: shouldCommit=" + shouldCommit);

                    transactionManager.executeWrite(status -> {
                        Product product = new Product("Conditional", BigDecimal.TEN, 100);
                        productRepository.save(product);

                        if (!shouldCommit) {
                            System.out.println("  手动回滚");
                            status.setRollbackOnly();
                        }

                        return product;
                    });
                }

                public <T> T executeWithRetry(Supplier<T> operation, int maxRetries) {
                    System.out.println("带重试的事务");

                    int attempt = 0;
                    while (attempt < maxRetries) {
                        try {
                            return transactionManager.executeWrite(status -> {
                                System.out.println("  尝试 " + (attempt + 1));
                                return operation.get();
                            });
                        } catch (Exception e) {
                            attempt++;
                            if (attempt >= maxRetries) {
                                throw e;
                            }
                            System.out.println("  失败,重试...");
                        }
                    }

                    throw new RuntimeException("重试失败");
                }
            }
            ---

04.性能优化
    a.连接池调优
        a.HikariCP配置
            调整连接池参数优化数据库连接管理,包括最大连接数、最小空闲连接、连接超时、空闲超时等。合理配置连接池提升应用性能和资源利用率。
        b.连接池优化示例
            ---
            // application.yml - HikariCP优化配置
            datasources:
              default:
                url: jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC
                driverClassName: com.mysql.cj.jdbc.Driver
                username: root
                password: ${DB_PASSWORD}

                # 连接池大小
                maximum-pool-size: 20          # 最大连接数
                minimum-idle: 5                # 最小空闲连接

                # 超时设置
                connection-timeout: 30000      # 连接超时(30秒)
                idle-timeout: 600000           # 空闲超时(10分钟)
                max-lifetime: 1800000          # 连接最大生命周期(30分钟)

                # 性能优化
                auto-commit: true
                connection-test-query: SELECT 1
                leak-detection-threshold: 60000  # 连接泄漏检测(60秒)

                # 连接池名称
                pool-name: HikariPool-Default

            // 连接池监控
            @Singleton
            public class ConnectionPoolMonitor {
                private final DataSource dataSource;

                public ConnectionPoolMonitor(DataSource dataSource) {
                    this.dataSource = dataSource;
                }

                public Map<String, Object> getPoolStatistics() {
                    if (dataSource instanceof HikariDataSource) {
                        HikariDataSource hikari = (HikariDataSource) dataSource;
                        HikariPoolMXBean pool = hikari.getHikariPoolMXBean();

                        Map<String, Object> stats = new HashMap<>();
                        stats.put("activeConnections", pool.getActiveConnections());
                        stats.put("idleConnections", pool.getIdleConnections());
                        stats.put("totalConnections", pool.getTotalConnections());
                        stats.put("threadsAwaitingConnection", pool.getThreadsAwaitingConnection());

                        System.out.println("连接池统计:");
                        System.out.println("  活跃连接: " + pool.getActiveConnections());
                        System.out.println("  空闲连接: " + pool.getIdleConnections());
                        System.out.println("  总连接数: " + pool.getTotalConnections());

                        return stats;
                    }
                    return Collections.emptyMap();
                }
            }
            ---
    b.查询优化
        a.索引和查询计划
            通过创建索引、优化查询语句、使用EXPLAIN分析查询计划等方式提升查询性能。避免全表扫描,合理使用索引和查询条件。
        b.查询优化示例
            ---
            @Singleton
            public class QueryOptimizationService {
                private final ProductRepository productRepository;
                private final EntityManager entityManager;

                public QueryOptimizationService(ProductRepository productRepository,
                                              EntityManager entityManager) {
                    this.productRepository = productRepository;
                    this.entityManager = entityManager;
                }

                // 批量查询优化
                public List<Product> findProductsBatch(List<Long> ids) {
                    System.out.println("批量查询优化: " + ids.size() + " 个ID");

                    // 使用IN查询,避免多次单独查询
                    String jpql = "SELECT p FROM Product p WHERE p.id IN :ids";
                    return entityManager.createQuery(jpql, Product.class)
                        .setParameter("ids", ids)
                        .getResultList();
                }

                // 投影查询优化
                @Query("SELECT p.id, p.name, p.price FROM Product p WHERE p.category = :category")
                public List<Object[]> findProductProjection(String category) {
                    // 只查询需要的字段,减少数据传输
                    System.out.println("投影查询: " + category);
                    return Collections.emptyList();
                }

                // 分页查询优化
                public Page<Product> findWithOptimizedPagination(int page, int size) {
                    System.out.println("优化分页查询");

                    // 使用覆盖索引
                    Sort sort = Sort.of(Sort.Order.asc("id"));
                    Pageable pageable = Pageable.from(page, size, sort);

                    return productRepository.findAll(pageable);
                }

                // 避免N+1查询
                @Query("SELECT p FROM Product p LEFT JOIN FETCH p.category WHERE p.id IN :ids")
                public List<Product> findWithCategory(List<Long> ids) {
                    // 使用JOIN FETCH一次性加载关联数据
                    System.out.println("避免N+1查询");
                    return Collections.emptyList();
                }
            }
            ---

5.5 缓存策略

01.缓存配置
    a.@Cacheable注解
        a.方法级缓存
            使用@Cacheable注解在方法级别启用缓存,减少数据库访问次数。首次调用执行数据库查询并缓存结果,后续调用直接返回缓存数据,显著提升查询性能。
        b.缓存配置示例
            ---
            // build.gradle - 缓存依赖
            dependencies {
                implementation("io.micronaut.cache:micronaut-cache-caffeine")
                implementation("io.micronaut.cache:micronaut-cache-redis")
            }

            // application.yml - 缓存配置
            micronaut:
              caches:
                # Caffeine本地缓存
                users:
                  maximum-size: 1000
                  expire-after-write: 10m
                  expire-after-access: 5m
                  record-stats: true

                products:
                  maximum-size: 5000
                  expire-after-write: 30m
                  initial-capacity: 100

                # Redis分布式缓存
                sessions:
                  redis:
                    enabled: true
                    expire-after-write: 1h

            redis:
              uri: redis://localhost:6379
              caches:
                sessions:
                  expire-after-write: 3600s

            // 缓存实体
            @Entity
            @Table(name = "users")
            public class User {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                @Column(unique = true)
                private String username;

                @Column
                private String email;

                @Column
                private LocalDateTime lastModified;

                // 构造函数和Getter/Setter省略
            }

            // 使用@Cacheable的Repository
            @Repository
            public interface UserRepository extends JpaRepository<User, Long> {
                Optional<User> findByUsername(String username);

                List<User> findByEmail(String email);
            }

            // 缓存服务
            import io.micronaut.cache.annotation.Cacheable;
            import io.micronaut.cache.annotation.CacheInvalidate;
            import io.micronaut.cache.annotation.CachePut;

            @Singleton
            public class UserCacheService {
                private final UserRepository userRepository;

                public UserCacheService(UserRepository userRepository) {
                    this.userRepository = userRepository;
                    System.out.println("UserCacheService初始化");
                }

                // 方法结果缓存
                @Cacheable("users")
                public Optional<User> findById(Long id) {
                    System.out.println("从数据库查询用户: " + id);
                    return userRepository.findById(id);
                }

                // 使用复合键缓存
                @Cacheable(value = "users", parameters = {"username"})
                public Optional<User> findByUsername(String username) {
                    System.out.println("从数据库查询用户名: " + username);
                    return userRepository.findByUsername(username);
                }

                // 缓存列表结果
                @Cacheable(value = "users", parameters = {"email"})
                public List<User> findByEmail(String email) {
                    System.out.println("从数据库查询邮箱: " + email);
                    return userRepository.findByEmail(email);
                }

                // 创建用户(不缓存)
                public User createUser(String username, String email) {
                    System.out.println("创建用户: " + username);

                    User user = new User();
                    user.setUsername(username);
                    user.setEmail(email);
                    user.setLastModified(LocalDateTime.now());

                    return userRepository.save(user);
                }

                // 缓存统计
                public void logCacheStatistics() {
                    System.out.println("\n=== 缓存统计 ===");
                    System.out.println("缓存有效降低数据库访问次数");
                }
            }

            // 控制器使用缓存
            @Controller("/api/cached-users")
            public class CachedUserController {
                private final UserCacheService userService;

                public CachedUserController(UserCacheService userService) {
                    this.userService = userService;
                }

                @Get("/{id}")
                public Optional<User> get(Long id) {
                    // 第一次调用查询数据库并缓存
                    // 后续调用直接从缓存返回
                    return userService.findById(id);
                }

                @Get("/username/{username}")
                public Optional<User> getByUsername(String username) {
                    return userService.findByUsername(username);
                }

                @Get("/email/{email}")
                public List<User> getByEmail(String email) {
                    return userService.findByEmail(email);
                }

                @Post
                public User create(@Body CreateUserRequest request) {
                    return userService.createUser(
                        request.getUsername(),
                        request.getEmail()
                    );
                }
            }

            // 测试缓存效果
            @Singleton
            public class CacheTestService {
                private final UserCacheService userService;

                public CacheTestService(UserCacheService userService) {
                    this.userService = userService;
                }

                public void testCachePerformance() {
                    System.out.println("=== 缓存性能测试 ===\n");

                    Long userId = 1L;

                    // 第一次调用 - 查询数据库
                    System.out.println("第一次调用:");
                    long start1 = System.currentTimeMillis();
                    userService.findById(userId);
                    long duration1 = System.currentTimeMillis() - start1;
                    System.out.println("耗时: " + duration1 + "ms\n");

                    // 第二次调用 - 从缓存获取
                    System.out.println("第二次调用(缓存):");
                    long start2 = System.currentTimeMillis();
                    userService.findById(userId);
                    long duration2 = System.currentTimeMillis() - start2;
                    System.out.println("耗时: " + duration2 + "ms\n");

                    // 性能提升
                    double improvement = ((duration1 - duration2) * 100.0) / duration1;
                    System.out.println("性能提升: " + String.format("%.2f", stats.hitRate() * 100));
                            System.out.println("  加载耗时: " + stats.averageLoadPenalty() + "ns");
                            System.out.println("  淘汰次数: " + stats.evictionCount());
                        }
                    }
                }
            }
            ---
    b.分布式缓存
        a.Redis集成
            使用Redis实现分布式缓存,支持集群部署的多实例间缓存共享。提供缓存发布订阅、缓存失效通知等功能,适合分布式系统场景。
        b.Redis缓存示例
            ---
            // Redis缓存配置
            // application.yml
            redis:
              uri: redis://localhost:6379
              caches:
                users:
                  enabled: true
                  expire-after-write: 1800s
                  charset: UTF-8
                  value-serializer: io.micronaut.jackson.serialize.JacksonObjectSerializer

                sessions:
                  enabled: true
                  expire-after-write: 3600s

            // Redis缓存服务
            @Singleton
            public class RedisCacheService {
                private final UserRepository userRepository;

                public RedisCacheService(UserRepository userRepository) {
                    this.userRepository = userRepository;
                    System.out.println("RedisCacheService初始化");
                }

                // Redis缓存查询
                @Cacheable(value = "users", cacheResolver = RedisCache.class)
                public Optional<User> findUserById(Long id) {
                    System.out.println("Redis查询用户: " + id);
                    return userRepository.findById(id);
                }

                // Redis缓存更新
                @CachePut(value = "users", parameters = {"id"})
                public User updateUser(Long id, String email) {
                    System.out.println("Redis更新用户: " + id);

                    User user = userRepository.findById(id)
                        .orElseThrow(() -> new IllegalArgumentException("用户不存在"));

                    user.setEmail(email);
                    user.setLastModified(LocalDateTime.now());

                    return userRepository.update(user);
                }

                // Redis缓存失效
                @CacheInvalidate(value = "users", parameters = {"id"})
                public void deleteUser(Long id) {
                    System.out.println("Redis删除用户: " + id);
                    userRepository.deleteById(id);
                }
            }

            // Redis发布订阅
            import io.lettuce.core.pubsub.RedisPubSubAdapter;
            import io.lettuce.core.pubsub.StatefulRedisPubSubConnection;

            @Singleton
            public class RedisPubSubService {
                private final StatefulRedisPubSubConnection<String, String> connection;

                @Inject
                public RedisPubSubService(RedisClient redisClient) {
                    this.connection = redisClient.connectPubSub();
                    setupSubscription();
                }

                private void setupSubscription() {
                    connection.addListener(new RedisPubSubAdapter<String, String>() {
                        @Override
                        public void message(String channel, String message) {
                            System.out.println("收到缓存失效消息: " + channel + " -> " + message);
                            handleCacheInvalidation(channel, message);
                        }
                    });

                    // 订阅缓存失效通道
                    connection.sync().subscribe("cache:invalidate");
                }

                private void handleCacheInvalidation(String channel, String message) {
                    // 处理缓存失效消息
                    System.out.println("  处理缓存失效: " + message);
                }

                // 发布缓存失效消息
                public void publishInvalidation(String cacheKey) {
                    System.out.println("发布缓存失效: " + cacheKey);
                    connection.sync().publish("cache:invalidate", cacheKey);
                }
            }

            // Redis集群缓存
            @Singleton
            public class RedisClusterCacheService {

                // 使用一致性哈希分布缓存
                @Cacheable(value = "users")
                public Optional<User> findUserInCluster(Long id) {
                    System.out.println("Redis集群查询: " + id);
                    // Redis Cluster自动处理数据分片
                    return Optional.empty();
                }

                // 批量操作Redis缓存
                public Map<Long, User> batchGetUsers(List<Long> ids) {
                    System.out.println("批量查询Redis: " + ids.size() + " 个用户");

                    Map<Long, User> result = new HashMap<>();

                    // 使用Pipeline批量查询
                    // 实际实现需要Redis Pipeline API

                    return result;
                }
            }
            ---

5.6 数据库迁移

01.Flyway集成
    a.迁移脚本
        a.版本化SQL脚本
            Flyway通过版本化SQL脚本管理数据库schema变更,自动追踪已执行的迁移,确保数据库结构一致性。支持可重复脚本、回调钩子等高级功能。
        b.Flyway配置示例
            ---
            // build.gradle - Flyway依赖
            dependencies {
                implementation("io.micronaut.flyway:micronaut-flyway")
                runtimeOnly("org.flywaydb:flyway-mysql")
            }

            // application.yml - Flyway配置
            datasources:
              default:
                url: jdbc:mysql://localhost:3306/mydb
                driverClassName: com.mysql.cj.jdbc.Driver
                username: root
                password: ${DB_PASSWORD}

            flyway:
              datasources:
                default:
                  enabled: true
                  # 迁移脚本位置
                  locations: classpath:db/migration
                  # 基线版本
                  baseline-version: 1
                  baseline-on-migrate: true
                  # 验证迁移脚本
                  validate-on-migrate: true
                  # 清理数据库(生产环境禁用)
                  clean-disabled: true
                  # 占位符替换
                  placeholders:
                    table_prefix: app_

            // 迁移脚本目录结构
            // src/main/resources/db/migration/
            // ├── V1__Create_users_table.sql
            // ├── V2__Add_email_index.sql
            // ├── V3__Create_products_table.sql
            // ├── V4__Add_created_at_columns.sql
            // └── R__Create_views.sql

            // V1__Create_users_table.sql - 创建用户表
            CREATE TABLE ${table_prefix}users (
                id BIGINT AUTO_INCREMENT PRIMARY KEY,
                username VARCHAR(50) NOT NULL UNIQUE,
                email VARCHAR(100) NOT NULL UNIQUE,
                password_hash VARCHAR(255) NOT NULL,
                active BOOLEAN DEFAULT TRUE,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                INDEX idx_username (username),
                INDEX idx_email (email)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

            -- 插入初始管理员用户
            INSERT INTO ${table_prefix}users (username, email, password_hash, active)
            VALUES ('admin', '[email protected]', '$2a$10$...', TRUE);

            // V2__Add_email_index.sql - 添加邮箱索引
            CREATE INDEX idx_users_email_active ON ${table_prefix}users(email, active);

            -- 添加唯一约束
            ALTER TABLE ${table_prefix}users
            ADD CONSTRAINT uk_users_username UNIQUE (username);

            // V3__Create_products_table.sql - 创建产品表
            CREATE TABLE ${table_prefix}products (
                id BIGINT AUTO_INCREMENT PRIMARY KEY,
                name VARCHAR(100) NOT NULL,
                description TEXT,
                price DECIMAL(10, 2) NOT NULL,
                stock INT NOT NULL DEFAULT 0,
                category VARCHAR(50),
                active BOOLEAN DEFAULT TRUE,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                INDEX idx_category (category),
                INDEX idx_price (price),
                INDEX idx_active (active)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

            -- 创建产品分类表
            CREATE TABLE ${table_prefix}categories (
                id BIGINT AUTO_INCREMENT PRIMARY KEY,
                name VARCHAR(50) NOT NULL UNIQUE,
                description VARCHAR(255),
                parent_id BIGINT,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                FOREIGN KEY (parent_id) REFERENCES ${table_prefix}categories(id) ON DELETE CASCADE
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

            // V4__Add_created_at_columns.sql - 添加时间戳列
            ALTER TABLE ${table_prefix}products
            ADD COLUMN deleted_at TIMESTAMP NULL,
            ADD INDEX idx_deleted_at (deleted_at);

            -- 添加软删除标记
            ALTER TABLE ${table_prefix}users
            ADD COLUMN deleted_at TIMESTAMP NULL;

            // R__Create_views.sql - 可重复脚本(视图)
            -- 活跃用户视图
            CREATE OR REPLACE VIEW v_active_users AS
            SELECT id, username, email, created_at
            FROM ${table_prefix}users
            WHERE active = TRUE AND deleted_at IS NULL;

            -- 产品统计视图
            CREATE OR REPLACE VIEW v_product_stats AS
            SELECT
                category,
                COUNT(*) as product_count,
                AVG(price) as avg_price,
                SUM(stock) as total_stock
            FROM ${table_prefix}products
            WHERE active = TRUE AND deleted_at IS NULL
            GROUP BY category;

            // Flyway监听器
            import io.micronaut.flyway.event.FlywayMigrationFinishedEvent;
            import io.micronaut.runtime.event.annotation.EventListener;

            @Singleton
            public class FlywayEventListener {

                @EventListener
                public void onMigrationFinished(FlywayMigrationFinishedEvent event) {
                    System.out.println("=== Flyway迁移完成 ===");
                    System.out.println("数据源: " + event.getDataSourceName());
                    System.out.println("迁移结果: " + event.getMigrationResult());
                    System.out.println("执行时间: " + event.getMigrationResult().totalMigrationTime + "ms");
                    System.out.println("成功迁移数: " + event.getMigrationResult().migrationsExecuted);
                }
            }

            // 编程式Flyway控制
            @Singleton
            public class FlywayService {
                private final Flyway flyway;

                public FlywayService(Flyway flyway) {
                    this.flyway = flyway;
                }

                // 获取迁移信息
                public void getMigrationInfo() {
                    System.out.println("=== 迁移信息 ===");

                    MigrationInfoService info = flyway.info();

                    for (MigrationInfo migration : info.all()) {
                        System.out.println("版本: " + migration.getVersion());
                        System.out.println("  描述: " + migration.getDescription());
                        System.out.println("  类型: " + migration.getType());
                        System.out.println("  状态: " + migration.getState());
                        System.out.println("  执行时间: " + migration.getInstalledOn());
                        System.out.println("  执行耗时: " + migration.getExecutionTime() + "ms\n");
                    }
                }

                // 验证迁移
                public boolean validateMigrations() {
                    System.out.println("验证迁移脚本...");

                    try {
                        flyway.validate();
                        System.out.println("  验证通过");
                        return true;
                    } catch (Exception e) {
                        System.err.println("  验证失败: " + e.getMessage());
                        return false;
                    }
                }

                // 修复迁移(生产环境慎用)
                public void repairMigrations() {
                    System.out.println("修复迁移记录...");
                    flyway.repair();
                    System.out.println("  修复完成");
                }
            }

            // 迁移测试
            @MicronautTest
            public class FlywayMigrationTest {

                @Inject
                FlywayService flywayService;

                @Test
                public void testMigrationsApplied() {
                    System.out.println("测试迁移是否正确应用");

                    // 验证迁移
                    assertTrue(flywayService.validateMigrations());

                    // 检查迁移信息
                    flywayService.getMigrationInfo();
                }
            }
            ---
    b.版本控制
        a.迁移版本管理
            使用版本号(V1, V2, V3...)和时间戳管理迁移脚本执行顺序,Flyway自动追踪已执行版本。支持基线迁移、跳过版本等灵活配置。
        b.版本管理示例
            ---
            // 版本号命名规范
            // V{版本号}__{描述}.sql
            // V1__Initial_schema.sql
            // V2__Add_user_roles.sql
            // V2.1__Fix_user_constraints.sql

            // 时间戳命名
            // V{YYYYMMDDHHmmss}__{描述}.sql
            // V20240101120000__Create_orders_table.sql
            // V20240102093000__Add_payment_status.sql

            // V5__Create_orders_table.sql - 订单表
            CREATE TABLE ${table_prefix}orders (
                id BIGINT AUTO_INCREMENT PRIMARY KEY,
                order_number VARCHAR(50) NOT NULL UNIQUE,
                user_id BIGINT NOT NULL,
                total_amount DECIMAL(10, 2) NOT NULL,
                status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
                payment_method VARCHAR(20),
                payment_status VARCHAR(20) DEFAULT 'UNPAID',
                shipping_address TEXT,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                paid_at TIMESTAMP NULL,
                shipped_at TIMESTAMP NULL,
                delivered_at TIMESTAMP NULL,
                INDEX idx_user_id (user_id),
                INDEX idx_order_number (order_number),
                INDEX idx_status (status),
                INDEX idx_created_at (created_at),
                FOREIGN KEY (user_id) REFERENCES ${table_prefix}users(id) ON DELETE RESTRICT
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

            -- 订单项表
            CREATE TABLE ${table_prefix}order_items (
                id BIGINT AUTO_INCREMENT PRIMARY KEY,
                order_id BIGINT NOT NULL,
                product_id BIGINT NOT NULL,
                quantity INT NOT NULL,
                unit_price DECIMAL(10, 2) NOT NULL,
                subtotal DECIMAL(10, 2) NOT NULL,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                INDEX idx_order_id (order_id),
                INDEX idx_product_id (product_id),
                FOREIGN KEY (order_id) REFERENCES ${table_prefix}orders(id) ON DELETE CASCADE,
                FOREIGN KEY (product_id) REFERENCES ${table_prefix}products(id) ON DELETE RESTRICT
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

            // V6__Add_audit_columns.sql - 添加审计列
            -- 为主要表添加审计字段
            ALTER TABLE ${table_prefix}users
            ADD COLUMN created_by VARCHAR(50),
            ADD COLUMN updated_by VARCHAR(50);

            ALTER TABLE ${table_prefix}products
            ADD COLUMN created_by VARCHAR(50),
            ADD COLUMN updated_by VARCHAR(50);

            ALTER TABLE ${table_prefix}orders
            ADD COLUMN created_by VARCHAR(50),
            ADD COLUMN updated_by VARCHAR(50),
            ADD COLUMN cancelled_at TIMESTAMP NULL,
            ADD COLUMN cancelled_by VARCHAR(50);

            // V7__Create_audit_log_table.sql - 审计日志表
            CREATE TABLE ${table_prefix}audit_logs (
                id BIGINT AUTO_INCREMENT PRIMARY KEY,
                table_name VARCHAR(50) NOT NULL,
                record_id BIGINT NOT NULL,
                action VARCHAR(20) NOT NULL,
                old_values JSON,
                new_values JSON,
                changed_by VARCHAR(50),
                changed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                ip_address VARCHAR(45),
                user_agent TEXT,
                INDEX idx_table_record (table_name, record_id),
                INDEX idx_changed_at (changed_at),
                INDEX idx_changed_by (changed_by)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

            // V8__Add_full_text_search.sql - 全文搜索索引
            -- 为产品表添加全文索引
            ALTER TABLE ${table_prefix}products
            ADD FULLTEXT INDEX ft_name_description (name, description);

            -- 创建搜索历史表
            CREATE TABLE ${table_prefix}search_history (
                id BIGINT AUTO_INCREMENT PRIMARY KEY,
                user_id BIGINT,
                search_query VARCHAR(255) NOT NULL,
                results_count INT,
                search_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                INDEX idx_user_id (user_id),
                INDEX idx_search_time (search_time),
                FOREIGN KEY (user_id) REFERENCES ${table_prefix}users(id) ON DELETE SET NULL
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

            // 迁移版本管理服务
            @Singleton
            public class MigrationVersionService {
                private final Flyway flyway;

                public MigrationVersionService(Flyway flyway) {
                    this.flyway = flyway;
                }

                // 获取当前版本
                public String getCurrentVersion() {
                    MigrationInfo current = flyway.info().current();
                    if (current != null) {
                        String version = current.getVersion().toString();
                        System.out.println("当前数据库版本: " + version);
                        return version;
                    }
                    return "未迁移";
                }

                // 获取所有待执行的迁移
                public List<String> getPendingMigrations() {
                    System.out.println("检查待执行的迁移...");

                    List<String> pending = new ArrayList<>();
                    for (MigrationInfo info : flyway.info().pending()) {
                        String migration = info.getVersion() + " - " + info.getDescription();
                        pending.add(migration);
                        System.out.println("  待执行: " + migration);
                    }

                    return pending;
                }

                // 获取已应用的迁移
                public List<String> getAppliedMigrations() {
                    System.out.println("已应用的迁移:");

                    List<String> applied = new ArrayList<>();
                    for (MigrationInfo info : flyway.info().applied()) {
                        String migration = info.getVersion() + " - " + info.getDescription();
                        applied.add(migration);
                        System.out.println("  " + migration +
                            " (执行于: " + info.getInstalledOn() + ")");
                    }

                    return applied;
                }
            }
            ---

02.Liquibase集成
    a.变更集管理
        a.XML/YAML变更日志
            Liquibase使用XML、YAML或JSON格式定义数据库变更集,提供比Flyway更丰富的抽象和数据库无关特性。支持回滚、标签、上下文等高级功能。
        b.Liquibase配置示例
            ---
            // build.gradle - Liquibase依赖
            dependencies {
                implementation("io.micronaut.liquibase:micronaut-liquibase")
            }

            // application.yml - Liquibase配置
            datasources:
              default:
                url: jdbc:mysql://localhost:3306/mydb
                driverClassName: com.mysql.cj.jdbc.Driver
                username: root
                password: ${DB_PASSWORD}

            liquibase:
              datasources:
                default:
                  enabled: true
                  # 变更日志文件
                  change-log: classpath:db/changelog/db.changelog-master.xml
                  # 执行上下文
                  contexts: dev,test
                  # 标签过滤
                  labels: feature-a,feature-b
                  # 回滚失败时不停止
                  drop-first: false

            // 变更日志目录结构
            // src/main/resources/db/changelog/
            // ├── db.changelog-master.xml
            // ├── changes/
            // │   ├── v1.0-initial-schema.xml
            // │   ├── v1.1-add-indexes.xml
            // │   └── v2.0-add-orders.xml
            // └── data/
            //     └── initial-data.xml

            // db.changelog-master.xml - 主变更日志
            <?xml version="1.0" encoding="UTF-8"?>
            <databaseChangeLog
                xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
                    http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.20.xsd">

                <!-- 包含所有变更集文件 -->
                <include file="classpath:db/changelog/changes/v1.0-initial-schema.xml"/>
                <include file="classpath:db/changelog/changes/v1.1-add-indexes.xml"/>
                <include file="classpath:db/changelog/changes/v2.0-add-orders.xml"/>
                <include file="classpath:db/changelog/data/initial-data.xml"/>
            </databaseChangeLog>

            // v1.0-initial-schema.xml - 初始schema
            <?xml version="1.0" encoding="UTF-8"?>
            <databaseChangeLog
                xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
                    http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.20.xsd">

                <!-- 创建用户表 -->
                <changeSet id="1" author="developer">
                    <createTable tableName="users">
                        <column name="id" type="BIGINT" autoIncrement="true">
                            <constraints primaryKey="true" nullable="false"/>
                        </column>
                        <column name="username" type="VARCHAR(50)">
                            <constraints unique="true" nullable="false"/>
                        </column>
                        <column name="email" type="VARCHAR(100)">
                            <constraints unique="true" nullable="false"/>
                        </column>
                        <column name="password_hash" type="VARCHAR(255)">
                            <constraints nullable="false"/>
                        </column>
                        <column name="active" type="BOOLEAN" defaultValueBoolean="true"/>
                        <column name="created_at" type="TIMESTAMP" defaultValueComputed="CURRENT_TIMESTAMP"/>
                        <column name="updated_at" type="TIMESTAMP" defaultValueComputed="CURRENT_TIMESTAMP"/>
                    </createTable>

                    <!-- 回滚操作 -->
                    <rollback>
                        <dropTable tableName="users"/>
                    </rollback>
                </changeSet>

                <!-- 创建产品表 -->
                <changeSet id="2" author="developer">
                    <createTable tableName="products">
                        <column name="id" type="BIGINT" autoIncrement="true">
                            <constraints primaryKey="true"/>
                        </column>
                        <column name="name" type="VARCHAR(100)">
                            <constraints nullable="false"/>
                        </column>
                        <column name="description" type="TEXT"/>
                        <column name="price" type="DECIMAL(10,2)">
                            <constraints nullable="false"/>
                        </column>
                        <column name="stock" type="INT" defaultValueNumeric="0"/>
                        <column name="category" type="VARCHAR(50)"/>
                        <column name="active" type="BOOLEAN" defaultValueBoolean="true"/>
                        <column name="created_at" type="TIMESTAMP" defaultValueComputed="CURRENT_TIMESTAMP"/>
                        <column name="updated_at" type="TIMESTAMP" defaultValueComputed="CURRENT_TIMESTAMP"/>
                    </createTable>

                    <rollback>
                        <dropTable tableName="products"/>
                    </rollback>
                </changeSet>
            </databaseChangeLog>

            // v1.1-add-indexes.xml - 添加索引
            <?xml version="1.0" encoding="UTF-8"?>
            <databaseChangeLog
                xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
                    http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.20.xsd">

                <!-- 为用户表添加索引 -->
                <changeSet id="3" author="developer">
                    <createIndex tableName="users" indexName="idx_username">
                        <column name="username"/>
                    </createIndex>

                    <createIndex tableName="users" indexName="idx_email">
                        <column name="email"/>
                    </createIndex>

                    <createIndex tableName="users" indexName="idx_active_created">
                        <column name="active"/>
                        <column name="created_at"/>
                    </createIndex>

                    <rollback>
                        <dropIndex tableName="users" indexName="idx_username"/>
                        <dropIndex tableName="users" indexName="idx_email"/>
                        <dropIndex tableName="users" indexName="idx_active_created"/>
                    </rollback>
                </changeSet>

                <!-- 为产品表添加索引 -->
                <changeSet id="4" author="developer">
                    <createIndex tableName="products" indexName="idx_category">
                        <column name="category"/>
                    </createIndex>

                    <createIndex tableName="products" indexName="idx_price">
                        <column name="price"/>
                    </createIndex>

                    <rollback>
                        <dropIndex tableName="products" indexName="idx_category"/>
                        <dropIndex tableName="products" indexName="idx_price"/>
                    </rollback>
                </changeSet>
            </databaseChangeLog>

            // YAML格式变更日志
            // db.changelog-master.yml
            databaseChangeLog:
              - include:
                  file: db/changelog/changes/v1.0-initial-schema.yml
              - include:
                  file: db/changelog/changes/v2.0-add-orders.yml

            // v2.0-add-orders.yml
            databaseChangeLog:
              - changeSet:
                  id: 5
                  author: developer
                  changes:
                    - createTable:
                        tableName: orders
                        columns:
                          - column:
                              name: id
                              type: BIGINT
                              autoIncrement: true
                              constraints:
                                primaryKey: true
                                nullable: false
                          - column:
                              name: order_number
                              type: VARCHAR(50)
                              constraints:
                                unique: true
                                nullable: false
                          - column:
                              name: user_id
                              type: BIGINT
                              constraints:
                                nullable: false
                                foreignKeyName: fk_orders_user
                                references: users(id)
                          - column:
                              name: total_amount
                              type: DECIMAL(10,2)
                              constraints:
                                nullable: false
                          - column:
                              name: status
                              type: VARCHAR(20)
                              defaultValue: PENDING
                          - column:
                              name: created_at
                              type: TIMESTAMP
                              defaultValueComputed: CURRENT_TIMESTAMP
                  rollback:
                    - dropTable:
                        tableName: orders

            // Liquibase服务
            @Singleton
            public class LiquibaseService {
                private final Liquibase liquibase;

                public LiquibaseService(Liquibase liquibase) {
                    this.liquibase = liquibase;
                }

                // 获取变更集状态
                public void getChangeSetStatus() {
                    System.out.println("=== Liquibase变更集状态 ===");

                    try {
                        List<ChangeSet> changeSets = liquibase.listUnrunChangeSets(
                            new Contexts(),
                            new LabelExpression()
                        );

                        System.out.println("未执行的变更集数: " + changeSets.size());

                        for (ChangeSet changeSet : changeSets) {
                            System.out.println("ID: " + changeSet.getId());
                            System.out.println("  作者: " + changeSet.getAuthor());
                            System.out.println("  文件: " + changeSet.getFilePath());
                            System.out.println("  描述: " + changeSet.getDescription());
                        }
                    } catch (Exception e) {
                        System.err.println("获取变更集状态失败: " + e.getMessage());
                    }
                }

                // 执行更新到指定标签
                public void updateToTag(String tag) {
                    System.out.println("更新数据库到标签: " + tag);

                    try {
                        liquibase.update(tag, new Contexts());
                        System.out.println("  更新完成");
                    } catch (Exception e) {
                        System.err.println("更新失败: " + e.getMessage());
                    }
                }

                // 回滚到指定标签
                public void rollbackToTag(String tag) {
                    System.out.println("回滚数据库到标签: " + tag);

                    try {
                        liquibase.rollback(tag, new Contexts());
                        System.out.println("  回滚完成");
                    } catch (Exception e) {
                        System.err.println("回滚失败: " + e.getMessage());
                    }
                }

                // 生成回滚SQL
                public String generateRollbackSQL(int count) {
                    System.out.println("生成回滚SQL (最近 " + count + " 个变更集)");

                    try {
                        StringWriter writer = new StringWriter();
                        liquibase.rollback(count, null, new Contexts(), writer);
                        return writer.toString();
                    } catch (Exception e) {
                        System.err.println("生成回滚SQL失败: " + e.getMessage());
                        return "";
                    }
                }
            }
            ---
    b.回滚策略
        a.变更回滚
            Liquibase支持定义回滚操作,可以回滚到特定版本或标签。提供回滚预览、回滚SQL生成等功能,确保数据库变更可逆。
        b.回滚策略示例
            ---
            // 定义回滚操作的变更集
            // v3.0-add-user-roles.xml
            <?xml version="1.0" encoding="UTF-8"?>
            <databaseChangeLog
                xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
                    http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.20.xsd">

                <!-- 创建角色表 -->
                <changeSet id="6" author="developer">
                    <createTable tableName="roles">
                        <column name="id" type="BIGINT" autoIncrement="true">
                            <constraints primaryKey="true"/>
                        </column>
                        <column name="name" type="VARCHAR(50)">
                            <constraints unique="true" nullable="false"/>
                        </column>
                        <column name="description" type="VARCHAR(255)"/>
                    </createTable>

                    <!-- 明确的回滚操作 -->
                    <rollback>
                        <dropTable tableName="roles"/>
                    </rollback>
                </changeSet>

                <!-- 创建用户角色关联表 -->
                <changeSet id="7" author="developer">
                    <createTable tableName="user_roles">
                        <column name="user_id" type="BIGINT">
                            <constraints nullable="false"
                                        foreignKeyName="fk_user_roles_user"
                                        references="users(id)"/>
                        </column>
                        <column name="role_id" type="BIGINT">
                            <constraints nullable="false"
                                        foreignKeyName="fk_user_roles_role"
                                        references="roles(id)"/>
                        </column>
                    </createTable>

                    <addPrimaryKey tableName="user_roles"
                                  columnNames="user_id, role_id"
                                  constraintName="pk_user_roles"/>

                    <!-- 回滚操作 -->
                    <rollback>
                        <dropTable tableName="user_roles"/>
                    </rollback>
                </changeSet>

                <!-- 插入初始角色数据 -->
                <changeSet id="8" author="developer">
                    <insert tableName="roles">
                        <column name="name" value="ADMIN"/>
                        <column name="description" value="管理员角色"/>
                    </insert>
                    <insert tableName="roles">
                        <column name="name" value="USER"/>
                        <column name="description" value="普通用户角色"/>
                    </insert>

                    <!-- 回滚:删除插入的数据 -->
                    <rollback>
                        <delete tableName="roles">
                            <where>name IN ('ADMIN', 'USER')</where>
                        </delete>
                    </rollback>
                </changeSet>

                <!-- 添加标签用于回滚 -->
                <changeSet id="9" author="developer">
                    <tagDatabase tag="version-1.0"/>
                </changeSet>
            </databaseChangeLog>

            // 使用自定义SQL的回滚
            <changeSet id="10" author="developer">
                <sql>
                    ALTER TABLE products ADD COLUMN discount DECIMAL(5,2) DEFAULT 0.00;
                    UPDATE products SET discount = 0.10 WHERE category = 'Electronics';
                </sql>

                <!-- 自定义SQL回滚 -->
                <rollback>
                    <sql>
                        ALTER TABLE products DROP COLUMN discount;
                    </sql>
                </rollback>
            </changeSet>

            // 复杂回滚操作
            <changeSet id="11" author="developer">
                <!-- 修改列类型 -->
                <modifyDataType tableName="products"
                               columnName="price"
                               newDataType="DECIMAL(12,2)"/>

                <!-- 自动生成回滚 -->
                <rollback changeSetId="11" changeSetAuthor="developer"/>
            </changeSet>

            // 回滚管理服务
            @Singleton
            public class RollbackManagementService {
                private final Liquibase liquibase;

                public RollbackManagementService(Liquibase liquibase) {
                    this.liquibase = liquibase;
                }

                // 回滚指定数量的变更集
                public void rollbackCount(int count) {
                    System.out.println("回滚最近 " + count + " 个变更集");

                    try {
                        liquibase.rollback(count, null, new Contexts());
                        System.out.println("  回滚完成");
                    } catch (Exception e) {
                        System.err.println("回滚失败: " + e.getMessage());
                    }
                }

                // 回滚到指定日期
                public void rollbackToDate(Date date) {
                    System.out.println("回滚到日期: " + date);

                    try {
                        liquibase.rollback(date, new Contexts());
                        System.out.println("  回滚完成");
                    } catch (Exception e) {
                        System.err.println("回滚失败: " + e.getMessage());
                    }
                }

                // 回滚到指定标签
                public void rollbackToTag(String tag) {
                    System.out.println("回滚到标签: " + tag);

                    try {
                        liquibase.rollback(tag, new Contexts());
                        System.out.println("  回滚完成");
                    } catch (Exception e) {
                        System.err.println("回滚失败: " + e.getMessage());
                    }
                }

                // 预览回滚SQL
                public String previewRollback(int count) {
                    System.out.println("预览回滚SQL (最近 " + count + " 个变更集)");

                    try {
                        StringWriter writer = new StringWriter();
                        liquibase.rollback(count, null, new Contexts(), writer);

                        String rollbackSQL = writer.toString();
                        System.out.println("\n回滚SQL:\n" + rollbackSQL);

                        return rollbackSQL;
                    } catch (Exception e) {
                        System.err.println("预览回滚失败: " + e.getMessage());
                        return "";
                    }
                }

                // 测试回滚(先更新再回滚)
                public void testRollback(String tag) {
                    System.out.println("测试回滚到标签: " + tag);

                    try {
                        // 1. 记录当前状态
                        System.out.println("  1. 记录当前状态");
                        String currentTag = "test-checkpoint-" + System.currentTimeMillis();
                        liquibase.tag(currentTag);

                        // 2. 执行更新
                        System.out.println("  2. 执行更新到标签: " + tag);
                        liquibase.update(tag, new Contexts());

                        // 3. 回滚到原状态
                        System.out.println("  3. 回滚到原状态");
                        liquibase.rollback(currentTag, new Contexts());

                        System.out.println("  测试回滚完成");
                    } catch (Exception e) {
                        System.err.println("测试回滚失败: " + e.getMessage());
                    }
                }
            }
            ---

03.Schema管理
    a.自动生成schema
        a.JPA自动DDL
            通过JPA的hbm2ddl.auto配置自动生成数据库schema,适合开发环境快速迭代。支持create、update、validate等模式,生产环境建议使用validate或关闭。
        b.自动DDL示例
            ---
            // application.yml - JPA自动DDL配置
            jpa:
              default:
                properties:
                  hibernate:
                    # DDL自动生成策略
                    hbm2ddl:
                      auto: update           # create | create-drop | update | validate | none
                    # SQL输出
                    show_sql: true
                    format_sql: true
                    use_sql_comments: true
                    # Schema命名策略
                    physical_naming_strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
                    implicit_naming_strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl

            // 实体定义自动生成表
            @Entity
            @Table(name = "customers",
                  indexes = {
                      @Index(name = "idx_email", columnList = "email"),
                      @Index(name = "idx_phone", columnList = "phone")
                  },
                  uniqueConstraints = {
                      @UniqueConstraint(name = "uk_customer_email", columnNames = {"email"})
                  })
            public class Customer {
                @Id
                @GeneratedValue(strategy = GenerationType.IDENTITY)
                private Long id;

                @Column(nullable = false, length = 100)
                private String name;

                @Column(nullable = false, unique = true, length = 100)
                private String email;

                @Column(length = 20)
                private String phone;

                @Embedded
                private Address address;

                @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, orphanRemoval = true)
                private List<Order> orders = new ArrayList<>();

                @Column(name = "created_at", nullable = false, updatable = false)
                @CreationTimestamp
                private LocalDateTime createdAt;

                @Column(name = "updated_at")
                @UpdateTimestamp
                private LocalDateTime updatedAt;

                // Getter和Setter省略
            }

            @Embeddable
            public class Address {
                @Column(length = 255)
                private String street;

                @Column(length = 50)
                private String city;

                @Column(length = 20)
                private String zipCode;

                @Column(length = 50)
                private String country;

                // Getter和Setter省略
            }

            // DDL生成服务
            @Singleton
            public class SchemaGenerationService {
                private final EntityManagerFactory entityManagerFactory;

                public SchemaGenerationService(EntityManagerFactory entityManagerFactory) {
                    this.entityManagerFactory = entityManagerFactory;
                }

                // 生成DDL脚本
                public void generateDDLScript() {
                    System.out.println("=== 生成DDL脚本 ===");

                    Map<String, Object> properties = new HashMap<>();
                    properties.put("javax.persistence.schema-generation.scripts.action", "create");
                    properties.put("javax.persistence.schema-generation.scripts.create-target",
                                  "target/generated-schema.sql");

                    // 触发schema生成
                    Persistence.generateSchema("default", properties);

                    System.out.println("DDL脚本已生成到: target/generated-schema.sql");
                }

                // 验证schema
                public void validateSchema() {
                    System.out.println("验证数据库Schema...");

                    SessionFactory sessionFactory =
                        entityManagerFactory.unwrap(SessionFactory.class);

                    // Hibernate会自动验证schema与实体映射的一致性
                    System.out.println("  Schema验证完成");
                }
            }

            // 环境特定配置
            // application-dev.yml - 开发环境
            jpa:
              default:
                properties:
                  hibernate:
                    hbm2ddl:
                      auto: update        # 开发环境自动更新
                    show_sql: true

            // application-prod.yml - 生产环境
            jpa:
              default:
                properties:
                  hibernate:
                    hbm2ddl:
                      auto: validate      # 生产环境只验证
                    show_sql: false

            // 初始化数据
            @Singleton
            public class DataInitializer {

                @EventListener
                public void onStartup(ServerStartupEvent event) {
                    System.out.println("=== 初始化数据 ===");
                    // 初始化逻辑
                }
            }
            ---
    b.Schema版本化
        a.迁移工具整合
            结合Flyway或Liquibase实现schema版本化管理,在生产环境使用迁移工具,开发环境可选择自动DDL。确保数据库变更可追踪、可回滚、可复现。
        b.整合示例
            ---
            // 混合使用JPA和Flyway
            // application.yml
            jpa:
              default:
                properties:
                  hibernate:
                    # 生产环境使用Flyway,验证schema
                    hbm2ddl:
                      auto: validate
                    show_sql: false

            flyway:
              datasources:
                default:
                  enabled: true
                  locations: classpath:db/migration
                  baseline-on-migrate: true

            // Schema同步服务
            @Singleton
            public class SchemaSyncService {
                private final EntityManagerFactory entityManagerFactory;
                private final Flyway flyway;

                public SchemaSyncService(EntityManagerFactory entityManagerFactory,
                                        Flyway flyway) {
                    this.entityManagerFactory = entityManagerFactory;
                    this.flyway = flyway;
                }

                // 生成迁移脚本
                public void generateMigrationScript() {
                    System.out.println("=== 生成迁移脚本 ===");

                    // 1. 生成当前实体的DDL
                    String ddl = generateEntityDDL();

                    // 2. 与现有schema对比
                    String diff = compareWithCurrentSchema(ddl);

                    // 3. 生成Flyway迁移脚本
                    if (!diff.isEmpty()) {
                        String version = getNextMigrationVersion();
                        String filename = String.format("V%s__Generated_migration.sql", version);

                        System.out.println("生成迁移文件: " + filename);
                        System.out.println("变更内容:\n" + diff);

                        // 写入迁移文件
                        saveMigrationScript(filename, diff);
                    } else {
                        System.out.println("Schema无变更");
                    }
                }

                private String generateEntityDDL() {
                    // 生成DDL逻辑
                    return "";
                }

                private String compareWithCurrentSchema(String ddl) {
                    // 对比逻辑
                    return "";
                }

                private String getNextMigrationVersion() {
                    MigrationInfo current = flyway.info().current();
                    if (current != null) {
                        String version = current.getVersion().toString();
                        int nextVersion = Integer.parseInt(version) + 1;
                        return String.valueOf(nextVersion);
                    }
                    return "1";
                }

                private void saveMigrationScript(String filename, String content) {
                    // 保存文件逻辑
                }
            }

            // CI/CD集成
            @Singleton
            public class MigrationCIService {

                // 验证迁移脚本
                public boolean validateMigrations() {
                    System.out.println("CI: 验证迁移脚本");

                    // 1. 检查迁移文件命名
                    // 2. 验证SQL语法
                    // 3. 检查是否有未提交的迁移
                    // 4. 验证回滚脚本

                    return true;
                }

                // 在测试数据库运行迁移
                public boolean testMigrations() {
                    System.out.println("CI: 测试迁移脚本");

                    // 1. 创建临时测试数据库
                    // 2. 运行所有迁移
                    // 3. 测试回滚
                    // 4. 清理测试数据库

                    return true;
                }
            }
            ---

5.7 R2DBC响应式数据访问

01.R2DBC概述
    a.核心概念
        R2DBC(Reactive Relational Database Connectivity)是响应式关系数据库连接规范,提供完全非阻塞的数据库访问能力。Micronaut Data R2DBC支持响应式流式查询,适用于高并发场景,充分利用系统资源。
    b.主要优势
        a.非阻塞I/O
            所有数据库操作都是异步非阻塞的,不会占用线程等待数据库响应,提升系统吞吐量。
        b.背压支持
            支持响应式流背压机制,消费者可以控制数据生产速率,避免内存溢出。
        c.流式处理
            支持大数据集的流式处理,逐条消费数据,内存占用低。

02.依赖配置
    a.添加依赖
        a.功能说明
            添加Micronaut Data R2DBC和数据库驱动依赖。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.data:micronaut-data-r2dbc")
                implementation("io.micronaut.r2dbc:micronaut-r2dbc-core")

                // MySQL驱动
                runtimeOnly("dev.miku:r2dbc-mysql")

                // PostgreSQL驱动
                // runtimeOnly("org.postgresql:r2dbc-postgresql")

                // H2驱动(测试用)
                // runtimeOnly("io.r2dbc:r2dbc-h2")

                annotationProcessor("io.micronaut.data:micronaut-data-processor")
            }
            ---
    b.数据源配置
        a.功能说明
            配置R2DBC数据源连接信息。
        b.配置示例
            ---
            // application.yml
            r2dbc:
              datasources:
                default:
                  url: r2dbc:mysql://localhost:3306/testdb
                  username: root
                  password: secret
                  driver: mysql
                  options:
                    # 连接池配置
                    initial-size: 5
                    max-size: 20
                    max-idle-time: 30m
                    max-acquire-time: 3s
                    max-create-connection-time: 3s
            ---

03.Repository定义
    a.响应式Repository
        a.功能说明
            继承ReactiveStreamsCrudRepository或CoroutineCrudRepository,定义响应式数据访问接口。
        b.代码示例
            ---
            import io.micronaut.data.annotation.*;
            import io.micronaut.data.model.query.builder.sql.Dialect;
            import io.micronaut.data.r2dbc.annotation.R2dbcRepository;
            import io.micronaut.data.repository.reactive.ReactiveStreamsCrudRepository;
            import reactor.core.publisher.Flux;
            import reactor.core.publisher.Mono;

            @R2dbcRepository(dialect = Dialect.MYSQL)
            public interface ProductRepository extends ReactiveStreamsCrudRepository<Product, Long> {

                // 返回Mono<Product>
                Mono<Product> findByName(String name);

                // 返��Flux<Product>
                Flux<Product> findByCategory(String category);

                // 自定义查询
                @Query("SELECT * FROM product WHERE price > :minPrice ORDER BY price")
                Flux<Product> findExpensiveProducts(Double minPrice);

                // 统计查询
                Mono<Long> countByCategory(String category);

                // 存在性检查
                Mono<Boolean> existsByName(String name);

                // 删除操作
                Mono<Long> deleteByCategory(String category);
            }
            ---
    b.实体类定义
        a.功能说明
            使用@MappedEntity定义实体类,映射到数据库表。
        b.代码示例
            ---
            import io.micronaut.data.annotation.*;
            import io.micronaut.serde.annotation.Serdeable;

            @Serdeable
            @MappedEntity("product")
            public class Product {

                @Id
                @GeneratedValue(GeneratedValue.Type.IDENTITY)
                private Long id;

                @Column(name = "name")
                private String name;

                @Column(name = "category")
                private String category;

                @Column(name = "price")
                private Double price;

                @Column(name = "stock")
                private Integer stock;

                @DateCreated
                private LocalDateTime createdAt;

                @DateUpdated
                private LocalDateTime updatedAt;

                // Constructors, Getters and Setters
                public Product() {}

                public Product(String name, String category, Double price, Integer stock) {
                    this.name = name;
                    this.category = category;
                    this.price = price;
                    this.stock = stock;
                }

                public Long getId() {
                    return id;
                }

                public void setId(Long id) {
                    this.id = id;
                }

                public String getName() {
                    return name;
                }

                public void setName(String name) {
                    this.name = name;
                }

                public String getCategory() {
                    return category;
                }

                public void setCategory(String category) {
                    this.category = category;
                }

                public Double getPrice() {
                    return price;
                }

                public void setPrice(Double price) {
                    this.price = price;
                }

                public Integer getStock() {
                    return stock;
                }

                public void setStock(Integer stock) {
                    this.stock = stock;
                }

                public LocalDateTime getCreatedAt() {
                    return createdAt;
                }

                public void setCreatedAt(LocalDateTime createdAt) {
                    this.createdAt = createdAt;
                }

                public LocalDateTime getUpdatedAt() {
                    return updatedAt;
                }

                public void setUpdatedAt(LocalDateTime updatedAt) {
                    this.updatedAt = updatedAt;
                }
            }
            ---

04.响应式Controller
    a.基本CRUD操作
        a.功能说明
            在Controller中使用响应式Repository,返回Mono或Flux。
        b.代码示例
            ---
            import io.micronaut.http.annotation.*;
            import reactor.core.publisher.Flux;
            import reactor.core.publisher.Mono;

            @Controller("/products")
            public class ProductController {

                private final ProductRepository productRepository;

                public ProductController(ProductRepository productRepository) {
                    this.productRepository = productRepository;
                }

                // 查询所有产品
                @Get
                public Flux<Product> listAll() {
                    return productRepository.findAll();
                }

                // 根据ID查询
                @Get("/{id}")
                public Mono<Product> findById(Long id) {
                    return productRepository.findById(id);
                }

                // 创建产品
                @Post
                public Mono<Product> create(@Body Product product) {
                    return productRepository.save(product);
                }

                // 更新产品
                @Put("/{id}")
                public Mono<Product> update(Long id, @Body Product product) {
                    return productRepository.findById(id)
                        .flatMap(existing -> {
                            existing.setName(product.getName());
                            existing.setPrice(product.getPrice());
                            existing.setStock(product.getStock());
                            return productRepository.update(existing);
                        });
                }

                // 删除产品
                @Delete("/{id}")
                public Mono<Void> delete(Long id) {
                    return productRepository.deleteById(id).then();
                }
            }
            ---
    b.复杂查询操作
        a.功能说明
            实现分页、排序、条件查询等复杂操作。
        b.代码示例
            ---
            import io.micronaut.data.model.Pageable;
            import io.micronaut.data.model.Page;

            @Controller("/products")
            public class ProductController {

                private final ProductRepository productRepository;

                public ProductController(ProductRepository productRepository) {
                    this.productRepository = productRepository;
                }

                // 按分类查询
                @Get("/category/{category}")
                public Flux<Product> findByCategory(String category) {
                    return productRepository.findByCategory(category);
                }

                // 查询高价产品
                @Get("/expensive")
                public Flux<Product> findExpensive(@QueryValue Double minPrice) {
                    return productRepository.findExpensiveProducts(minPrice);
                }

                // 统计分类产品数量
                @Get("/category/{category}/count")
                public Mono<Long> countByCategory(String category) {
                    return productRepository.countByCategory(category);
                }

                // 检查产品是否存在
                @Get("/exists/{name}")
                public Mono<Boolean> exists(String name) {
                    return productRepository.existsByName(name);
                }

                // 批量删除
                @Delete("/category/{category}")
                public Mono<Long> deleteByCategory(String category) {
                    return productRepository.deleteByCategory(category);
                }
            }
            ---

05.响应式事务
    a.声明式事务
        a.功能说明
            使用@TransactionalEventListener注解管理响应式事务。
        b.代码示例
            ---
            import io.micronaut.transaction.annotation.Transactional;
            import reactor.core.publisher.Mono;

            @Singleton
            public class OrderService {

                private final OrderRepository orderRepository;
                private final ProductRepository productRepository;

                public OrderService(OrderRepository orderRepository,
                                  ProductRepository productRepository) {
                    this.orderRepository = orderRepository;
                    this.productRepository = productRepository;
                }

                @Transactional
                public Mono<Order> createOrder(Order order) {
                    return productRepository.findById(order.getProductId())
                        .flatMap(product -> {
                            if (product.getStock() < order.getQuantity()) {
                                return Mono.error(new RuntimeException("库存不足"));
                            }

                            // 扣减库存
                            product.setStock(product.getStock() - order.getQuantity());

                            return productRepository.update(product)
                                .then(orderRepository.save(order));
                        });
                }

                @Transactional
                public Mono<Void> cancelOrder(Long orderId) {
                    return orderRepository.findById(orderId)
                        .flatMap(order ->
                            productRepository.findById(order.getProductId())
                                .flatMap(product -> {
                                    // 恢复库存
                                    product.setStock(product.getStock() + order.getQuantity());
                                    return productRepository.update(product);
                                })
                                .then(orderRepository.deleteById(orderId))
                        )
                        .then();
                }
            }
            ---
    b.编程式事务
        a.功能说明
            使用ReactiveTransactionOperations手动管理事务。
        b.代码示例
            ---
            import io.micronaut.transaction.reactive.ReactiveTransactionOperations;
            import reactor.core.publisher.Mono;

            @Singleton
            public class PaymentService {

                private final ReactiveTransactionOperations<Connection> transactionManager;
                private final OrderRepository orderRepository;
                private final PaymentRepository paymentRepository;

                public PaymentService(
                    ReactiveTransactionOperations<Connection> transactionManager,
                    OrderRepository orderRepository,
                    PaymentRepository paymentRepository
                ) {
                    this.transactionManager = transactionManager;
                    this.orderRepository = orderRepository;
                    this.paymentRepository = paymentRepository;
                }

                public Mono<Payment> processPayment(Long orderId, Payment payment) {
                    return transactionManager.withTransaction(status ->
                        orderRepository.findById(orderId)
                            .flatMap(order -> {
                                payment.setOrderId(orderId);
                                payment.setAmount(order.getTotalAmount());

                                return paymentRepository.save(payment)
                                    .flatMap(savedPayment -> {
                                        order.setStatus("PAID");
                                        return orderRepository.update(order)
                                            .thenReturn(savedPayment);
                                    });
                            })
                    );
                }
            }
            ---

06.流式处理
    a.大数据集处理
        a.功能说明
            使用Flux流式处理大量数据,避免一次性加载到内存。
        b.代码示例
            ---
            import reactor.core.publisher.Flux;
            import java.time.Duration;

            @Singleton
            public class ReportService {

                private final ProductRepository productRepository;

                public ReportService(ProductRepository productRepository) {
                    this.productRepository = productRepository;
                }

                // 流式导出产品数据
                public Flux<String> exportProducts() {
                    return productRepository.findAll()
                        .map(product -> String.format("%d,%s,%.2f,%d",
                            product.getId(),
                            product.getName(),
                            product.getPrice(),
                            product.getStock()
                        ))
                        .delayElements(Duration.ofMillis(10)); // 控制速率
                }

                // 批量处理
                public Mono<Long> updatePrices(Double multiplier) {
                    return productRepository.findAll()
                        .buffer(100) // 每批100条
                        .flatMap(batch ->
                            Flux.fromIterable(batch)
                                .flatMap(product -> {
                                    product.setPrice(product.getPrice() * multiplier);
                                    return productRepository.update(product);
                                })
                                .collectList()
                        )
                        .count();
                }
            }
            ---
    b.背压控制
        a.功能说明
            使用背压操作符控制数据流速率。
        b.代码示例
            ---
            import reactor.core.publisher.Flux;
            import reactor.core.scheduler.Schedulers;

            @Controller("/stream")
            public class StreamController {

                private final ProductRepository productRepository;

                public StreamController(ProductRepository productRepository) {
                    this.productRepository = productRepository;
                }

                @Get(value = "/products", produces = "text/event-stream")
                public Flux<Product> streamProducts() {
                    return productRepository.findAll()
                        .onBackpressureBuffer(1000) // 缓冲区大小
                        .publishOn(Schedulers.boundedElastic())
                        .delayElements(Duration.ofMillis(100)); // 限流
                }

                @Get(value = "/products/drop", produces = "text/event-stream")
                public Flux<Product> streamWithDrop() {
                    return productRepository.findAll()
                        .onBackpressureDrop() // 丢弃超出处理能力的数据
                        .publishOn(Schedulers.boundedElastic());
                }

                @Get(value = "/products/latest", produces = "text/event-stream")
                public Flux<Product> streamLatest() {
                    return productRepository.findAll()
                        .onBackpressureLatest() // 只保留最新数据
                        .publishOn(Schedulers.boundedElastic());
                }
            }
            ---

07.性能优化
    a.连接池配置
        a.功能说明
            优化R2DBC连接池参数,提升并发性能。
        b.配置示例
            ---
            // application.yml
            r2dbc:
              datasources:
                default:
                  url: r2dbc:mysql://localhost:3306/testdb
                  username: root
                  password: secret
                  options:
                    # 初始连接数
                    initial-size: 10
                    # 最大连接数
                    max-size: 50
                    # 最大空闲时间
                    max-idle-time: 30m
                    # 获取连接超时
                    max-acquire-time: 3s
                    # 创建连接超时
                    max-create-connection-time: 3s
                    # 连接验证查询
                    validation-query: SELECT 1
                    # 连接验证深度
                    validation-depth: LOCAL
            ---
    b.批量操作
        a.功能说明
            使用批量操作减少数据库往返次数。
        b.代码示例
            ---
            import reactor.core.publisher.Flux;
            import reactor.core.publisher.Mono;

            @Singleton
            public class BatchService {

                private final ProductRepository productRepository;

                public BatchService(ProductRepository productRepository) {
                    this.productRepository = productRepository;
                }

                // 批量插入
                public Mono<Long> batchInsert(List<Product> products) {
                    return Flux.fromIterable(products)
                        .buffer(100) // 每批100条
                        .flatMap(batch ->
                            productRepository.saveAll(batch).collectList()
                        )
                        .count();
                }

                // 批量更新
                public Mono<Long> batchUpdate(List<Product> products) {
                    return Flux.fromIterable(products)
                        .buffer(100)
                        .flatMap(batch ->
                            productRepository.updateAll(batch).collectList()
                        )
                        .count();
                }

                // 批量删除
                public Mono<Void> batchDelete(List<Long> ids) {
                    return Flux.fromIterable(ids)
                        .buffer(100)
                        .flatMap(batch ->
                            productRepository.deleteAll(
                                productRepository.findAllById(batch)
                            )
                        )
                        .then();
                }
            }
            ---
    c.查询优化
        a.功能说明
            使用索引、避免N+1查询等优化技巧。
        b.代码示例
            ---
            import io.micronaut.data.annotation.Join;

            @R2dbcRepository(dialect = Dialect.MYSQL)
            public interface OrderRepository extends ReactiveStreamsCrudRepository<Order, Long> {

                // 使用JOIN避免N+1查询
                @Join(value = "product", type = Join.Type.FETCH)
                Flux<Order> findAll();

                @Join(value = "product", type = Join.Type.FETCH)
                Mono<Order> findById(Long id);

                // 使用索引字段查询
                @Query("SELECT * FROM orders WHERE user_id = :userId AND status = :status")
                Flux<Order> findByUserIdAndStatus(Long userId, String status);

                // 只查询需要的字段
                @Query("SELECT id, total_amount, status FROM orders WHERE user_id = :userId")
                Flux<OrderSummary> findSummaryByUserId(Long userId);
            }

            // DTO投影
            @Introspected
            public class OrderSummary {
                private Long id;
                private Double totalAmount;
                private String status;

                // Getters and Setters
            }
            ---

6 高级特性

6.1 反应式编程

01.反应式编程概述
    a.定义与特点
        Micronaut原生支持反应式编程模型,基于Reactive Streams规范,提供非阻塞异步处理能力。通过响应式流处理,应用可以高效处理大量并发请求,充分利用系统资源,避免线程阻塞导致的性能瓶颈。
    b.核心优势
        a.资源利用率
            采用事件驱动模型,少量线程即可处理大量并发连接,显著降低内存占用和上下文切换开销。
        b.背压支持
            实现Reactive Streams背压机制,生产者根据消费者处理能力动态调整数据发送速率,防止系统过载。
        c.组合能力
            提供丰富的操作符,支持流的转换、过滤、合并等操作,简化复杂异步逻辑的实现。

02.Reactor集成
    a.依赖配置
        a.功能说明
            Micronaut默认集成Project Reactor,提供Mono和Flux两种核心响应式类型,分别表示0-1个元素和0-N个元素的异步序列。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.reactor:micronaut-reactor")
                implementation("io.projectreactor:reactor-core")
            }
            ---
    b.基础使用
        a.Mono示例
            a.功能说明
                Mono表示包含0或1个元素的异步序列,适用于单个结果的异步操作,如数据库查询单条记录、HTTP请求等场景。
            b.代码示例
                ---
                import io.micronaut.http.annotation.Controller;
                import io.micronaut.http.annotation.Get;
                import reactor.core.publisher.Mono;
                import java.time.Duration;

                @Controller("/reactive")
                public class ReactiveController {

                    // 返回单个用户信息
                    @Get("/user/{id}")
                    public Mono<User> getUser(Long id) {
                        return Mono.fromCallable(() -> {
                            // 模拟数据库查询
                            Thread.sleep(100);
                            return new User(id, "User" + id, "user" + id + "@example.com");
                        })
                        .subscribeOn(Schedulers.boundedElastic())
                        .timeout(Duration.ofSeconds(5));
                    }

                    // 延迟响应示例
                    @Get("/delayed")
                    public Mono<String> delayedResponse() {
                        return Mono.just("Response")
                            .delayElement(Duration.ofSeconds(2))
                            .map(s -> s + " after 2 seconds");
                    }
                }
                ---
        b.Flux示例
            a.功能说明
                Flux表示包含0到N个元素的异步序列,适用于流式数据处理,如分页查询、实时数据推送、文件流处理等场景。
            b.代码示例
                ---
                import reactor.core.publisher.Flux;
                import java.time.Duration;

                @Controller("/stream")
                public class StreamController {

                    // 流式返回用户列表
                    @Get("/users")
                    public Flux<User> streamUsers() {
                        return Flux.range(1, 10)
                            .delayElements(Duration.ofMillis(100))
                            .map(i -> new User(
                                Long.valueOf(i),
                                "User" + i,
                                "user" + i + "@example.com"
                            ));
                    }

                    // 服务器推送事件(SSE)
                    @Get(value = "/events", produces = MediaType.TEXT_EVENT_STREAM)
                    public Flux<ServerSentEvent<String>> streamEvents() {
                        return Flux.interval(Duration.ofSeconds(1))
                            .map(seq -> ServerSentEvent.<String>builder()
                                .id(String.valueOf(seq))
                                .data("Event " + seq)
                                .build());
                    }

                    // 无限流示例
                    @Get(value = "/infinite", produces = MediaType.TEXT_EVENT_STREAM)
                    public Flux<Long> infiniteStream() {
                        return Flux.interval(Duration.ofMillis(500))
                            .take(Duration.ofSeconds(10));
                    }
                }
                ---

03.RxJava集成
    a.依赖配置
        a.功能说明
            Micronaut同时支持RxJava 2和RxJava 3,提供Single、Maybe、Observable、Flowable等响应式类型,与Reactor互补。
        b.配置示例
            ---
            // build.gradle - RxJava 3
            dependencies {
                implementation("io.micronaut.rxjava3:micronaut-rxjava3")
                implementation("io.reactivex.rxjava3:rxjava:3.1.5")
            }
            ---
    b.RxJava使用
        a.Single和Maybe
            a.功能说明
                Single表示恰好一个元素的异步序列,Maybe表示0或1个元素,适用于可能为空的查询结果。
            b.代码示例
                ---
                import io.micronaut.http.annotation.Controller;
                import io.micronaut.http.annotation.Get;
                import io.reactivex.rxjava3.core.Single;
                import io.reactivex.rxjava3.core.Maybe;
                import io.reactivex.rxjava3.schedulers.Schedulers;

                @Controller("/rx")
                public class RxController {

                    // Single示例:必定返回结果
                    @Get("/count")
                    public Single<Long> getCount() {
                        return Single.fromCallable(() -> {
                            // 模拟计数查询
                            Thread.sleep(50);
                            return 100L;
                        }).subscribeOn(Schedulers.io());
                    }

                    // Maybe示例:可能为空
                    @Get("/find/{id}")
                    public Maybe<User> findUser(Long id) {
                        return Maybe.fromCallable(() -> {
                            if (id > 100) {
                                return null; // 未找到
                            }
                            return new User(id, "User" + id, "user" + id + "@example.com");
                        }).subscribeOn(Schedulers.io());
                    }
                }
                ---
        b.Observable和Flowable
            a.功能说明
                Observable用于简单的多元素流,Flowable支持背压控制,适用于高吞吐量场景。
            b.代码示例
                ---
                import io.reactivex.rxjava3.core.Observable;
                import io.reactivex.rxjava3.core.Flowable;
                import io.reactivex.rxjava3.core.BackpressureStrategy;

                @Controller("/rx-stream")
                public class RxStreamController {

                    // Observable示例
                    @Get("/items")
                    public Observable<Item> streamItems() {
                        return Observable.range(1, 20)
                            .map(i -> new Item(i, "Item " + i))
                            .delay(100, TimeUnit.MILLISECONDS);
                    }

                    // Flowable示例:支持背压
                    @Get(value = "/data", produces = MediaType.TEXT_EVENT_STREAM)
                    public Flowable<String> streamData() {
                        return Flowable.create(emitter -> {
                            for (int i = 0; i < 1000; i++) {
                                if (emitter.isCancelled()) {
                                    break;
                                }
                                emitter.onNext("Data " + i);
                                Thread.sleep(10);
                            }
                            emitter.onComplete();
                        }, BackpressureStrategy.BUFFER)
                        .subscribeOn(Schedulers.io());
                    }
                }
                ---

04.响应式HTTP客户端
    a.声明式客户端
        a.功能说明
            Micronaut的HTTP客户端原生支持响应式类型,可直接返回Mono、Flux、Single等,实现非阻塞的远程调用。
        b.代码示例
            ---
            import io.micronaut.http.annotation.Get;
            import io.micronaut.http.client.annotation.Client;
            import reactor.core.publisher.Mono;
            import reactor.core.publisher.Flux;

            @Client("https://api.example.com")
            public interface ApiClient {

                // 响应式单个结果
                @Get("/user/{id}")
                Mono<User> getUser(Long id);

                // 响应式列表
                @Get("/users")
                Flux<User> listUsers();

                // RxJava类型
                @Get("/count")
                Single<Long> getCount();
            }

            // 使用示例
            @Controller("/api")
            public class ApiController {

                private final ApiClient apiClient;

                public ApiController(ApiClient apiClient) {
                    this.apiClient = apiClient;
                }

                @Get("/proxy/user/{id}")
                public Mono<User> proxyGetUser(Long id) {
                    return apiClient.getUser(id)
                        .timeout(Duration.ofSeconds(3))
                        .onErrorResume(e -> Mono.just(
                            new User(id, "Fallback", "[email protected]")
                        ));
                }

                @Get("/proxy/users")
                public Flux<User> proxyListUsers() {
                    return apiClient.listUsers()
                        .take(10)
                        .filter(user -> user.getId() > 5);
                }
            }
            ---
    b.组合多个请求
        a.功能说明
            响应式编程的核心优势在于轻松组合多个异步操作,实现并行请求、依赖请求等复杂场景。
        b.代码示例
            ---
            @Controller("/combined")
            public class CombinedController {

                private final ApiClient apiClient;
                private final OrderClient orderClient;

                public CombinedController(ApiClient apiClient, OrderClient orderClient) {
                    this.apiClient = apiClient;
                    this.orderClient = orderClient;
                }

                // 并行请求多个服务
                @Get("/dashboard/{userId}")
                public Mono<Dashboard> getDashboard(Long userId) {
                    Mono<User> userMono = apiClient.getUser(userId);
                    Mono<List<Order>> ordersMono = orderClient.getUserOrders(userId)
                        .collectList();
                    Mono<Long> countMono = orderClient.getOrderCount(userId);

                    return Mono.zip(userMono, ordersMono, countMono)
                        .map(tuple -> new Dashboard(
                            tuple.getT1(),
                            tuple.getT2(),
                            tuple.getT3()
                        ));
                }

                // 依赖请求:先获取用户,再获取订单
                @Get("/user-orders/{userId}")
                public Flux<Order> getUserOrders(Long userId) {
                    return apiClient.getUser(userId)
                        .flatMapMany(user -> orderClient.getUserOrders(user.getId()));
                }

                // 错误处理和重试
                @Get("/resilient/{userId}")
                public Mono<User> getResilientUser(Long userId) {
                    return apiClient.getUser(userId)
                        .retry(3)
                        .timeout(Duration.ofSeconds(5))
                        .onErrorResume(TimeoutException.class, e ->
                            Mono.just(new User(userId, "Timeout", "[email protected]"))
                        )
                        .onErrorResume(e ->
                            Mono.just(new User(userId, "Error", "[email protected]"))
                        );
                }
            }
            ---

05.响应式数据访问
    a.R2DBC集成
        a.功能说明
            R2DBC(Reactive Relational Database Connectivity)是响应式关系数据库驱动规范,Micronaut Data支持R2DBC实现完全非阻塞的数据库访问。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.data:micronaut-data-r2dbc")
                implementation("io.r2dbc:r2dbc-postgresql:0.8.13.RELEASE")
                runtimeOnly("org.postgresql:postgresql")
            }

            // application.yml
            r2dbc:
              datasources:
                default:
                  url: r2dbc:postgresql://localhost:5432/mydb
                  username: user
                  password: pass
                  max-size: 10
            ---
        c.Repository定义
            ---
            import io.micronaut.data.annotation.Repository;
            import io.micronaut.data.repository.reactive.ReactorCrudRepository;
            import reactor.core.publisher.Mono;
            import reactor.core.publisher.Flux;

            @Repository
            public interface UserRepository extends ReactorCrudRepository<User, Long> {

                // 响应式查询方法
                Mono<User> findByEmail(String email);

                Flux<User> findByNameContaining(String name);

                Mono<Long> countByAgeGreaterThan(Integer age);

                // 自定义查询
                @Query("SELECT * FROM users WHERE created_at > :date")
                Flux<User> findRecentUsers(LocalDateTime date);
            }

            // 使用示例
            @Controller("/db-users")
            public class DbUserController {

                private final UserRepository userRepository;

                public DbUserController(UserRepository userRepository) {
                    this.userRepository = userRepository;
                }

                @Get("/{id}")
                public Mono<User> getUser(Long id) {
                    return userRepository.findById(id);
                }

                @Get("/search")
                public Flux<User> searchUsers(String name) {
                    return userRepository.findByNameContaining(name);
                }

                @Post
                public Mono<User> createUser(@Body User user) {
                    return userRepository.save(user);
                }

                @Delete("/{id}")
                public Mono<Void> deleteUser(Long id) {
                    return userRepository.deleteById(id);
                }
            }
            ---
    b.MongoDB响应式驱动
        a.功能说明
            Micronaut支持MongoDB响应式驱动,提供完全异步的文档数据库访问能力。
        b.代码示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.mongodb:micronaut-mongo-reactive")
            }

            // application.yml
            mongodb:
              uri: mongodb://localhost:27017/mydb

            // Repository定义
            import io.micronaut.data.mongodb.annotation.MongoRepository;
            import io.micronaut.data.repository.reactive.ReactorCrudRepository;

            @MongoRepository
            public interface ProductRepository extends ReactorCrudRepository<Product, String> {

                Flux<Product> findByCategory(String category);

                Mono<Product> findByName(String name);

                Flux<Product> findByPriceBetween(Double min, Double max);
            }

            // 使用示例
            @Controller("/products")
            public class ProductController {

                private final ProductRepository productRepository;

                public ProductController(ProductRepository productRepository) {
                    this.productRepository = productRepository;
                }

                @Get
                public Flux<Product> listProducts() {
                    return productRepository.findAll();
                }

                @Get("/category/{category}")
                public Flux<Product> getByCategory(String category) {
                    return productRepository.findByCategory(category);
                }

                @Post
                public Mono<Product> createProduct(@Body Product product) {
                    return productRepository.save(product);
                }
            }
            ---

6.2 消息驱动

01.消息驱动架构
    a.核心概念
        消息驱动架构通过异步消息传递实现服务间解耦,提升系统的可扩展性和容错能力。Micronaut提供统一的消息抽象层,支持多种消息中间件,包括Kafka、RabbitMQ、NATS等,简化消息驱动应用的开发。
    b.主要优势
        a.异步解耦
            生产者和消费者通过消息队列解耦,无需直接依赖,提升系统灵活性和可维护性。
        b.削峰填谷
            消息队列缓冲突发流量,消费者按自身处理能力消费消息,避免系统过载。
        c.可靠传递
            消息持久化和确认机制保证消息不丢失,支持事务和重试策略。

02.Kafka集成
    a.依赖配置
        a.功能说明
            Micronaut Kafka模块提供声明式的生产者和消费者注解,简化Kafka客户端的使用,支持响应式流处理。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.kafka:micronaut-kafka")
            }

            // application.yml
            kafka:
              bootstrap:
                servers: localhost:9092
              producers:
                default:
                  key-serializer: org.apache.kafka.common.serialization.StringSerializer
                  value-serializer: org.apache.kafka.common.serialization.StringSerializer
              consumers:
                default:
                  key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
                  value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
                  group-id: micronaut-group
                  auto-offset-reset: earliest
            ---
    b.消息生产者
        a.同步生产者
            a.功能说明
                使用@KafkaClient注解定义生产者接口,Micronaut自动生成实现类,支持同步和异步发送消息。
            b.代码示例
                ---
                import io.micronaut.configuration.kafka.annotation.KafkaClient;
                import io.micronaut.configuration.kafka.annotation.KafkaKey;
                import io.micronaut.configuration.kafka.annotation.Topic;

                @KafkaClient
                public interface OrderProducer {

                    // 发送消息到指定主题
                    @Topic("orders")
                    void sendOrder(@KafkaKey String orderId, Order order);

                    // 发送带分区键的消息
                    @Topic("orders")
                    void sendOrderWithKey(@KafkaKey String key, Order order);
                }

                // 使用示例
                @Controller("/orders")
                public class OrderController {

                    private final OrderProducer orderProducer;

                    public OrderController(OrderProducer orderProducer) {
                        this.orderProducer = orderProducer;
                    }

                    @Post
                    public HttpResponse<String> createOrder(@Body Order order) {
                        String orderId = UUID.randomUUID().toString();
                        order.setId(orderId);
                        orderProducer.sendOrder(orderId, order);
                        return HttpResponse.ok("Order created: " + orderId);
                    }
                }
                ---
        b.响应式生产者
            a.功能说明
                生产者方法可以返回响应式类型,实现完全非阻塞的消息发送,适用于高吞吐量场景。
            b.代码示例
                ---
                import reactor.core.publisher.Mono;
                import org.apache.kafka.clients.producer.RecordMetadata;

                @KafkaClient
                public interface ReactiveOrderProducer {

                    // 返回Mono,异步发送
                    @Topic("orders")
                    Mono<RecordMetadata> sendOrder(@KafkaKey String orderId, Order order);

                    // 批量发送
                    @Topic("orders")
                    Flux<RecordMetadata> sendOrders(Flux<Order> orders);
                }

                // 使用示例
                @Controller("/reactive-orders")
                public class ReactiveOrderController {

                    private final ReactiveOrderProducer orderProducer;

                    public ReactiveOrderController(ReactiveOrderProducer orderProducer) {
                        this.orderProducer = orderProducer;
                    }

                    @Post
                    public Mono<HttpResponse<String>> createOrder(@Body Order order) {
                        String orderId = UUID.randomUUID().toString();
                        order.setId(orderId);

                        return orderProducer.sendOrder(orderId, order)
                            .map(metadata -> HttpResponse.ok(
                                "Order sent to partition " + metadata.partition() +
                                " at offset " + metadata.offset()
                            ))
                            .onErrorResume(e -> Mono.just(
                                HttpResponse.serverError("Failed to send order: " + e.getMessage())
                            ));
                    }

                    @Post("/batch")
                    public Mono<HttpResponse<String>> createOrders(@Body List<Order> orders) {
                        return orderProducer.sendOrders(Flux.fromIterable(orders))
                            .collectList()
                            .map(results -> HttpResponse.ok(
                                "Sent " + results.size() + " orders"
                            ));
                    }
                }
                ---
    c.消息消费者
        a.基础消费者
            a.功能说明
                使用@KafkaListener注解定义消费者,自动订阅主题并处理消息,支持多种消息确认模式。
            b.代码示例
                ---
                import io.micronaut.configuration.kafka.annotation.KafkaListener;
                import io.micronaut.configuration.kafka.annotation.OffsetReset;
                import io.micronaut.configuration.kafka.annotation.Topic;
                import io.micronaut.messaging.annotation.MessageBody;
                import io.micronaut.messaging.annotation.MessageHeader;
                import org.slf4j.Logger;
                import org.slf4j.LoggerFactory;

                @KafkaListener(
                    groupId = "order-processor",
                    offsetReset = OffsetReset.EARLIEST
                )
                public class OrderConsumer {

                    private static final Logger LOG = LoggerFactory.getLogger(OrderConsumer.class);

                    // 消费单条消息
                    @Topic("orders")
                    public void processOrder(@MessageBody Order order,
                                            @MessageHeader("kafka_key") String key,
                                            @MessageHeader("kafka_offset") long offset) {
                        LOG.info("Processing order {} at offset {}", order.getId(), offset);
                        // 处理订单逻辑
                        processOrderLogic(order);
                    }

                    private void processOrderLogic(Order order) {
                        // 业务处理
                        LOG.info("Order processed: {}", order);
                    }
                }
                ---
        b.批量消费者
            a.功能说明
                消费者可以批量接收消息,提高处理效率,适用于批处理场景。
            b.代码示例
                ---
                import io.micronaut.configuration.kafka.annotation.KafkaListener;
                import io.micronaut.configuration.kafka.annotation.Topic;
                import java.util.List;

                @KafkaListener(
                    groupId = "batch-processor",
                    batch = true
                )
                public class BatchOrderConsumer {

                    private static final Logger LOG = LoggerFactory.getLogger(BatchOrderConsumer.class);

                    // 批量消费消息
                    @Topic("orders")
                    public void processBatch(List<Order> orders) {
                        LOG.info("Processing batch of {} orders", orders.size());

                        orders.forEach(order -> {
                            // 批量处理逻辑
                            LOG.info("Processing order: {}", order.getId());
                        });

                        LOG.info("Batch processing completed");
                    }
                }
                ---
        c.响应式消费者
            a.功能说明
                消费者方法可以返回响应式类型,实现背压控制和流式处理。
            b.代码示例
                ---
                import reactor.core.publisher.Mono;

                @KafkaListener(groupId = "reactive-processor")
                public class ReactiveOrderConsumer {

                    private static final Logger LOG = LoggerFactory.getLogger(ReactiveOrderConsumer.class);

                    @Topic("orders")
                    public Mono<Void> processOrder(@MessageBody Order order) {
                        return Mono.fromRunnable(() -> {
                            LOG.info("Reactive processing order: {}", order.getId());
                        })
                        .then(saveToDatabase(order))
                        .then(sendNotification(order))
                        .doOnError(e -> LOG.error("Error processing order", e))
                        .onErrorResume(e -> Mono.empty());
                    }

                    private Mono<Void> saveToDatabase(Order order) {
                        return Mono.fromRunnable(() -> {
                            // 保存到数据库
                            LOG.info("Saved order to database: {}", order.getId());
                        });
                    }

                    private Mono<Void> sendNotification(Order order) {
                        return Mono.fromRunnable(() -> {
                            // 发送通知
                            LOG.info("Notification sent for order: {}", order.getId());
                        });
                    }
                }
                ---

03.RabbitMQ集成
    a.依赖配置
        a.功能说明
            Micronaut RabbitMQ模块提供AMQP协议支持,实现可靠的消息传递和灵活的路由机制。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.rabbitmq:micronaut-rabbitmq")
            }

            // application.yml
            rabbitmq:
              uri: amqp://guest:guest@localhost:5672
              exchanges:
                - name: orders-exchange
                  type: topic
              queues:
                - name: orders-queue
                  durable: true
              bindings:
                - exchange: orders-exchange
                  queue: orders-queue
                  routing-key: order.*
            ---
    b.消息生产者
        a.功能说明
            使用@RabbitClient注解定义生产者,支持交换机、路由键等AMQP特性。
        b.代码示例
            ---
            import io.micronaut.rabbitmq.annotation.RabbitClient;
            import io.micronaut.rabbitmq.annotation.RabbitProperty;

            @RabbitClient("orders-exchange")
            public interface RabbitOrderProducer {

                // 发送到指定路由键
                void send(@RabbitProperty("routingKey") String routingKey, Order order);

                // 发送带优先级的消息
                void sendWithPriority(
                    @RabbitProperty("routingKey") String routingKey,
                    @RabbitProperty("priority") int priority,
                    Order order
                );
            }

            // 使用示例
            @Controller("/rabbit-orders")
            public class RabbitOrderController {

                private final RabbitOrderProducer producer;

                public RabbitOrderController(RabbitOrderProducer producer) {
                    this.producer = producer;
                }

                @Post
                public HttpResponse<String> createOrder(@Body Order order) {
                    producer.send("order.created", order);
                    return HttpResponse.ok("Order sent to RabbitMQ");
                }

                @Post("/urgent")
                public HttpResponse<String> createUrgentOrder(@Body Order order) {
                    producer.sendWithPriority("order.urgent", 10, order);
                    return HttpResponse.ok("Urgent order sent");
                }
            }
            ---
    c.消息消费者
        a.功能说明
            使用@RabbitListener注解定义消费者,支持消息确认、拒绝、重新入队等操作。
        b.代码示例
            ---
            import io.micronaut.rabbitmq.annotation.Queue;
            import io.micronaut.rabbitmq.annotation.RabbitListener;
            import com.rabbitmq.client.Channel;
            import io.micronaut.messaging.Acknowledgement;

            @RabbitListener
            public class RabbitOrderConsumer {

                private static final Logger LOG = LoggerFactory.getLogger(RabbitOrderConsumer.class);

                // 自动确认模式
                @Queue("orders-queue")
                public void receive(Order order) {
                    LOG.info("Received order: {}", order.getId());
                    processOrder(order);
                }

                // 手动确认模式
                @Queue(value = "orders-queue", acknowledge = "MANUAL")
                public void receiveManual(Order order, Acknowledgement acknowledgement) {
                    try {
                        LOG.info("Processing order: {}", order.getId());
                        processOrder(order);
                        acknowledgement.ack();
                    } catch (Exception e) {
                        LOG.error("Error processing order", e);
                        acknowledgement.nack(true); // 重新入队
                    }
                }

                private void processOrder(Order order) {
                    // 业务处理逻辑
                    LOG.info("Order processed successfully: {}", order.getId());
                }
            }
            ---

04.NATS集成
    a.依赖配置
        a.功能说明
            NATS是轻量级高性能消息系统,Micronaut提供NATS集成,适用于微服务间的快速通信。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.nats:micronaut-nats")
            }

            // application.yml
            nats:
              addresses:
                - nats://localhost:4222
              max-reconnect: 5
            ---
    b.发布订阅模式
        a.功能说明
            NATS支持发布订阅模式,实现一对多的消息分发。
        b.代码示例
            ---
            import io.micronaut.nats.annotation.NatsClient;
            import io.micronaut.nats.annotation.Subject;

            // 生产者
            @NatsClient
            public interface EventPublisher {

                @Subject("events.user")
                void publishUserEvent(UserEvent event);

                @Subject("events.order")
                void publishOrderEvent(OrderEvent event);
            }

            // 消费者
            import io.micronaut.nats.annotation.NatsListener;

            @NatsListener
            public class EventSubscriber {

                private static final Logger LOG = LoggerFactory.getLogger(EventSubscriber.class);

                @Subject("events.user")
                public void onUserEvent(UserEvent event) {
                    LOG.info("Received user event: {}", event);
                }

                @Subject("events.order")
                public void onOrderEvent(OrderEvent event) {
                    LOG.info("Received order event: {}", event);
                }

                // 通配符订阅
                @Subject("events.*")
                public void onAnyEvent(String subject, byte[] data) {
                    LOG.info("Received event on subject: {}", subject);
                }
            }
            ---
    c.请求响应模式
        a.功能说明
            NATS支持请求响应模式,实现同步RPC调用。
        b.代码示例
            ---
            // 客户端
            @NatsClient
            public interface UserService {

                @Subject("user.get")
                User getUser(Long userId);

                @Subject("user.create")
                User createUser(User user);
            }

            // 服务端
            @NatsListener
            public class UserServiceImpl {

                private static final Logger LOG = LoggerFactory.getLogger(UserServiceImpl.class);

                @Subject("user.get")
                public User getUser(Long userId) {
                    LOG.info("Getting user: {}", userId);
                    return new User(userId, "User" + userId, "[email protected]");
                }

                @Subject("user.create")
                public User createUser(User user) {
                    LOG.info("Creating user: {}", user.getName());
                    user.setId(System.currentTimeMillis());
                    return user;
                }
            }

            // 使用示例
            @Controller("/nats-users")
            public class NatsUserController {

                private final UserService userService;

                public NatsUserController(UserService userService) {
                    this.userService = userService;
                }

                @Get("/{id}")
                public User getUser(Long id) {
                    return userService.getUser(id);
                }

                @Post
                public User createUser(@Body User user) {
                    return userService.createUser(user);
                }
            }
            ---

05.消息序列化
    a.JSON序列化
        a.功能说明
            Micronaut默认使用Jackson进行JSON序列化,支持自定义序列化配置。
        b.配置示例
            ---
            // application.yml
            jackson:
              serialization:
                indent-output: true
              deserialization:
                fail-on-unknown-properties: false

            // 自定义序列化器
            import com.fasterxml.jackson.databind.ObjectMapper;
            import com.fasterxml.jackson.databind.SerializationFeature;
            import io.micronaut.context.annotation.Factory;
            import io.micronaut.context.annotation.Replaces;
            import jakarta.inject.Singleton;

            @Factory
            public class JacksonConfiguration {

                @Singleton
                @Replaces(ObjectMapper.class)
                public ObjectMapper objectMapper() {
                    ObjectMapper mapper = new ObjectMapper();
                    mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
                    mapper.findAndRegisterModules();
                    return mapper;
                }
            }
            ---
    b.自定义序列化器
        a.功能说明
            可以为Kafka、RabbitMQ等消息系统配置自定义序列化器,支持Avro、Protobuf等格式。
        b.代码示例
            ---
            // Kafka自定义序列化器
            import org.apache.kafka.common.serialization.Serializer;
            import org.apache.kafka.common.serialization.Deserializer;

            public class OrderSerializer implements Serializer<Order> {

                private final ObjectMapper objectMapper = new ObjectMapper();

                @Override
                public byte[] serialize(String topic, Order order) {
                    try {
                        return objectMapper.writeValueAsBytes(order);
                    } catch (Exception e) {
                        throw new RuntimeException("Failed to serialize order", e);
                    }
                }
            }

            public class OrderDeserializer implements Deserializer<Order> {

                private final ObjectMapper objectMapper = new ObjectMapper();

                @Override
                public Order deserialize(String topic, byte[] data) {
                    try {
                        return objectMapper.readValue(data, Order.class);
                    } catch (Exception e) {
                        throw new RuntimeException("Failed to deserialize order", e);
                    }
                }
            }

            // 配置使用
            // application.yml
            kafka:
              producers:
                default:
                  value-serializer: com.example.OrderSerializer
              consumers:
                default:
                  value-deserializer: com.example.OrderDeserializer
            ---

6.3 分布式追踪

01.分布式追踪概述
    a.核心概念
        分布式追踪通过记录请求在微服务系统中的完整调用链路,帮助开发者理解系统行为、定位性能瓶颈和排查故障。Micronaut集成OpenTelemetry和Zipkin等主流追踪系统,提供自动化的链路追踪能力,无需侵入业务代码。
    b.主要优势
        a.全链路可视化
            追踪系统记录请求从入口到出口的完整路径,包括服务调用关系、耗时分布和错误信息,提供直观的调用链视图。
        b.性能分析
            通过分析每个服务节点的响应时间,快速识别性能瓶颈,优化关键路径,提升系统整体性能。
        c.故障定位
            当系统出现异常时,追踪数据帮助快速定位问题发生的具体服务和调用环节,缩短故障排查时间。

02.OpenTelemetry集成
    a.依赖配置
        a.功能说明
            OpenTelemetry是云原生计算基金会的可观测性标准,Micronaut提供原生支持,自动采集追踪、指标和日志数据。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.tracing:micronaut-tracing-opentelemetry")
                implementation("io.opentelemetry:opentelemetry-exporter-zipkin")
            }

            // application.yml
            tracing:
              enabled: true
              zipkin:
                enabled: true
                url: http://localhost:9411
                sampler:
                  probability: 0.1
            otel:
              service:
                name: order-service
              traces:
                exporter: zipkin
            ---
    b.自动追踪
        a.HTTP请求追踪
            a.功能说明
                Micronaut自动为所有HTTP请求创建追踪Span,记录请求方法、路径、状态码和响应时间,无需手动埋点。
            b.代码示例
                ---
                import io.micronaut.http.annotation.Controller;
                import io.micronaut.http.annotation.Get;
                import io.micronaut.http.client.HttpClient;
                import io.micronaut.http.client.annotation.Client;
                import jakarta.inject.Inject;

                @Controller("/orders")
                public class OrderController {

                    @Inject
                    @Client("http://inventory-service")
                    private HttpClient inventoryClient;

                    // 自动追踪HTTP请求
                    @Get("/{id}")
                    public Order getOrder(Long id) {
                        // 调用下游服务,自动传播追踪上下文
                        String inventory = inventoryClient.toBlocking()
                            .retrieve("/inventory/" + id);

                        return new Order(id, "Order-" + id, inventory);
                    }
                }
                ---
        b.数据库操作追踪
            a.功能说明
                集成JDBC和R2DBC驱动,自动追踪数据库查询操作,记录SQL语句、执行时间和影响行数。
            b.代码示例
                ---
                import io.micronaut.data.annotation.Repository;
                import io.micronaut.data.jdbc.annotation.JdbcRepository;
                import io.micronaut.data.model.query.builder.sql.Dialect;
                import io.micronaut.data.repository.CrudRepository;

                @JdbcRepository(dialect = Dialect.MYSQL)
                public interface OrderRepository extends CrudRepository<Order, Long> {

                    // 数据库查询自动追踪
                    List<Order> findByStatus(String status);

                    // 复杂查询也会自动追踪
                    @Query("SELECT * FROM orders WHERE user_id = :userId AND status = :status")
                    List<Order> findUserOrders(Long userId, String status);
                }

                // 使用示例
                @Controller("/orders")
                public class OrderController {

                    private final OrderRepository orderRepository;

                    public OrderController(OrderRepository orderRepository) {
                        this.orderRepository = orderRepository;
                    }

                    @Get("/pending")
                    public List<Order> getPendingOrders() {
                        // 数据库操作自动记录到追踪链路
                        return orderRepository.findByStatus("PENDING");
                    }
                }
                ---
    c.自定义追踪
        a.手动创建Span
            a.功能说明
                在关键业务逻辑中手动创建Span,记录自定义操作的执行时间和上下文信息。
            b.代码示例
                ---
                import io.opentelemetry.api.trace.Span;
                import io.opentelemetry.api.trace.Tracer;
                import io.opentelemetry.context.Scope;
                import jakarta.inject.Inject;
                import jakarta.inject.Singleton;

                @Singleton
                public class OrderService {

                    @Inject
                    private Tracer tracer;

                    public Order processOrder(Order order) {
                        // 创建自定义Span
                        Span span = tracer.spanBuilder("processOrder")
                            .setAttribute("order.id", order.getId())
                            .setAttribute("order.amount", order.getAmount())
                            .startSpan();

                        try (Scope scope = span.makeCurrent()) {
                            // 业务逻辑
                            validateOrder(order);
                            calculateTotal(order);
                            saveOrder(order);

                            span.addEvent("Order processed successfully");
                            return order;
                        } catch (Exception e) {
                            span.recordException(e);
                            span.setAttribute("error", true);
                            throw e;
                        } finally {
                            span.end();
                        }
                    }

                    private void validateOrder(Order order) {
                        Span span = tracer.spanBuilder("validateOrder").startSpan();
                        try (Scope scope = span.makeCurrent()) {
                            // 验证逻辑
                            if (order.getAmount() <= 0) {
                                throw new IllegalArgumentException("Invalid amount");
                            }
                        } finally {
                            span.end();
                        }
                    }

                    private void calculateTotal(Order order) {
                        // 计算逻辑
                    }

                    private void saveOrder(Order order) {
                        // 保存逻辑
                    }
                }
                ---
        b.添加标签和事件
            a.功能说明
                为Span添加自定义标签和事件,记录业务相关的元数据和关键操作节点。
            b.代码示例
                ---
                import io.opentelemetry.api.trace.Span;
                import io.opentelemetry.api.common.Attributes;
                import io.opentelemetry.api.common.AttributeKey;

                @Singleton
                public class PaymentService {

                    @Inject
                    private Tracer tracer;

                    public PaymentResult processPayment(Payment payment) {
                        Span span = Span.current();

                        // 添加业务标签
                        span.setAttribute("payment.method", payment.getMethod());
                        span.setAttribute("payment.amount", payment.getAmount());
                        span.setAttribute("user.id", payment.getUserId());

                        // 记录关键事件
                        span.addEvent("Payment validation started");

                        if (validatePayment(payment)) {
                            span.addEvent("Payment validated",
                                Attributes.of(
                                    AttributeKey.stringKey("validation.result"), "success"
                                ));

                            // 调用支付网关
                            span.addEvent("Calling payment gateway");
                            PaymentResult result = callPaymentGateway(payment);

                            span.setAttribute("payment.status", result.getStatus());
                            span.addEvent("Payment completed");

                            return result;
                        } else {
                            span.addEvent("Payment validation failed");
                            span.setAttribute("error", true);
                            throw new PaymentException("Validation failed");
                        }
                    }

                    private boolean validatePayment(Payment payment) {
                        return payment.getAmount() > 0 && payment.getMethod() != null;
                    }

                    private PaymentResult callPaymentGateway(Payment payment) {
                        return new PaymentResult("SUCCESS", payment.getAmount());
                    }
                }
                ---

03.Zipkin集成
    a.依赖配置
        a.功能说明
            Zipkin是广泛使用的分布式追踪系统,Micronaut提供开箱即用的集成支持。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.tracing:micronaut-tracing-zipkin")
            }

            // application.yml
            tracing:
              zipkin:
                enabled: true
                url: http://localhost:9411
                sampler:
                  probability: 1.0
                http:
                  path: /api/v2/spans
            ---
    b.追踪上报
        a.HTTP上报
            a.功能说明
                配置Zipkin服务端地址后,Micronaut自动通过HTTP POST请求上报追踪数据。
            b.配置示例
                ---
                // application.yml
                tracing:
                  zipkin:
                    enabled: true
                    url: http://zipkin-server:9411
                    http:
                      path: /api/v2/spans
                      connect-timeout: 1s
                      read-timeout: 10s
                    sampler:
                      probability: 0.1
                micronaut:
                  application:
                    name: order-service
                ---
        b.消息队列上报
            a.功能说明
                支持通过Kafka上报追踪数据,避免直接依赖Zipkin服务。
            b.配置示例
                ---
                // build.gradle
                dependencies {
                    implementation("io.micronaut.tracing:micronaut-tracing-zipkin")
                    implementation("io.micronaut.kafka:micronaut-kafka")
                }

                // application.yml
                tracing:
                  zipkin:
                    enabled: true
                    kafka:
                      enabled: true
                      topic: zipkin
                kafka:
                  bootstrap:
                    servers: localhost:9092
                ---

04.追踪最佳实践
    a.采样策略
        a.功能说明
            合理配置采样率,平衡追踪覆盖率和系统性能开销。
        b.配置示例
            ---
            // application.yml
            tracing:
              zipkin:
                sampler:
                  # 固定概率采样:10%的请求
                  probability: 0.1

            # 自定义采样器
            import io.micronaut.context.annotation.Factory;
            import io.micronaut.tracing.brave.sampler.TraceSampler;
            import brave.sampler.Sampler;
            import jakarta.inject.Singleton;

            @Factory
            public class SamplerConfiguration {

                @Singleton
                public Sampler customSampler() {
                    // 速率限制采样:每秒最多100个追踪
                    return Sampler.create(0.1f);
                }
            }
            ---
    b.敏感信息处理
        a.功能说明
            追踪数据中避免记录敏感信息,或在上报前进行脱敏处理。
        b.代码示例
            ---
            import io.micronaut.tracing.annotation.NewSpan;
            import io.micronaut.tracing.annotation.SpanTag;

            @Singleton
            public class UserService {

                // 使用@NewSpan创建追踪
                @NewSpan("getUserInfo")
                public User getUserInfo(
                    @SpanTag("user.id") Long userId,
                    String password  // 不添加@SpanTag,避免记录密码
                ) {
                    // 业务逻辑
                    return userRepository.findById(userId);
                }

                // 脱敏处理
                @NewSpan("processPayment")
                public void processPayment(
                    @SpanTag("card.last4") String cardLast4,  // 只记录后4位
                    String fullCardNumber  // 完整卡号不记录
                ) {
                    // 支付处理
                }
            }
            ---
    c.性能优化
        a.异步上报
            a.功能说明
                追踪数据采用异步方式上报,避免阻塞业务请求。
            b.配置示例
                ---
                // application.yml
                tracing:
                  zipkin:
                    enabled: true
                    url: http://localhost:9411
                    http:
                      # 异步发送配置
                      message-timeout: 1s
                      close-timeout: 1s
                      # 批量发送
                      max-requests: 64
                      queue-size: 1000
                ---
        b.本地缓存
            a.功能说明
                当追踪系统不可用时,追踪数据暂存本地,避免数据丢失。
            b.配置示例
                ---
                // application.yml
                tracing:
                  zipkin:
                    enabled: true
                    url: http://localhost:9411
                    http:
                      # 连接失败时的重试策略
                      connect-timeout: 1s
                      read-timeout: 10s
                    # 本地队列配置
                    sender:
                      type: http
                      queue-size: 10000
                ---

6.4 服务发现

01.服务发现概述
    a.核心概念
        服务发现是微服务架构的关键组件,负责动态管理服务实例的注册和查询。Micronaut支持多种服务发现机制,包括Consul、Eureka、Kubernetes等,提供自动注册、健康检查和负载均衡能力,简化微服务间的通信。
    b.主要优势
        a.动态服务管理
            服务实例启动时自动注册到注册中心,停止时自动注销,客户端无需维护静态服务列表,支持服务的弹性伸缩。
        b.健康检查
            注册中心定期检查服务实例的健康状态,自动剔除不健康的实例,确保客户端只调用可用的服务。
        c.负载均衡
            客户端从注册中心获取多个服务实例,通过负载均衡算法分发请求,提升系统的可用性和性能。

02.Consul集成
    a.依赖配置
        a.功能说明
            Consul是HashiCorp开发的服务网格解决方案,提供服务发现、健康检查、KV存储等功能,Micronaut提供原生支持。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.discovery:micronaut-discovery-client")
            }

            // application.yml
            consul:
              client:
                registration:
                  enabled: true
                defaultZone: "${CONSUL_HOST:localhost}:${CONSUL_PORT:8500}"
            micronaut:
              application:
                name: order-service
            ---
    b.服务注册
        a.自动注册
            a.功能说明
                Micronaut应用启动时自动向Consul注册服务实例,包括服务名称、IP地址、端口和元数据。
            b.配置示例
                ---
                // application.yml
                consul:
                  client:
                    registration:
                      enabled: true
                      # 服务注册配置
                      prefer-ip-address: true
                      ip-address: ${HOSTNAME:localhost}
                      port: ${SERVER_PORT:8080}
                      # 健康检查配置
                      check:
                        enabled: true
                        interval: 10s
                        http: true
                        path: /health
                      # 服务标签
                      tags:
                        - version=1.0
                        - environment=production
                    defaultZone: localhost:8500
                micronaut:
                  application:
                    name: order-service
                ---
        b.手动注册
            a.功能说明
                通过编程方式手动控制服务注册和注销,适用于特殊场景。
            b.代码示例
                ---
                import io.micronaut.discovery.ServiceInstance;
                import io.micronaut.discovery.consul.ConsulClient;
                import io.micronaut.discovery.consul.client.v1.CatalogEntry;
                import io.micronaut.discovery.consul.client.v1.NewServiceEntry;
                import jakarta.inject.Inject;
                import jakarta.inject.Singleton;

                @Singleton
                public class ServiceRegistration {

                    @Inject
                    private ConsulClient consulClient;

                    public void registerService() {
                        NewServiceEntry entry = new NewServiceEntry(
                            "order-service",
                            "order-service-1",
                            "localhost",
                            8080
                        );
                        entry.setTags(Arrays.asList("version=1.0", "region=us-east"));

                        // 配置健康检查
                        NewServiceEntry.Check check = new NewServiceEntry.Check();
                        check.setHttp("http://localhost:8080/health");
                        check.setInterval("10s");
                        entry.setCheck(check);

                        consulClient.register(entry);
                    }

                    public void deregisterService(String serviceId) {
                        consulClient.deregister(serviceId);
                    }
                }
                ---
    c.服务发现
        a.声明式客户端
            a.功能说明
                使用@Client注解声明式调用远程服务,Micronaut自动从Consul查询服务实例并进行负载均衡。
            b.代码示例
                ---
                import io.micronaut.http.annotation.Get;
                import io.micronaut.http.client.annotation.Client;

                // 通过服务名称调用
                @Client("inventory-service")
                public interface InventoryClient {

                    @Get("/inventory/{productId}")
                    Inventory getInventory(Long productId);

                    @Get("/inventory/check/{productId}")
                    boolean checkStock(Long productId);
                }

                // 使用示例
                @Controller("/orders")
                public class OrderController {

                    private final InventoryClient inventoryClient;

                    public OrderController(InventoryClient inventoryClient) {
                        this.inventoryClient = inventoryClient;
                    }

                    @Post
                    public HttpResponse<Order> createOrder(@Body Order order) {
                        // 自动服务发现和负载均衡
                        boolean inStock = inventoryClient.checkStock(order.getProductId());

                        if (inStock) {
                            Inventory inventory = inventoryClient.getInventory(order.getProductId());
                            order.setInventoryInfo(inventory);
                            return HttpResponse.ok(order);
                        } else {
                            return HttpResponse.badRequest();
                        }
                    }
                }
                ---
        b.编程式发现
            a.功能说明
                通过DiscoveryClient API编程式查询服务实例,获取更多控制权。
            b.代码示例
                ---
                import io.micronaut.discovery.DiscoveryClient;
                import io.micronaut.discovery.ServiceInstance;
                import io.micronaut.http.client.HttpClient;
                import jakarta.inject.Inject;
                import jakarta.inject.Singleton;
                import reactor.core.publisher.Flux;

                @Singleton
                public class ServiceDiscoveryExample {

                    @Inject
                    private DiscoveryClient discoveryClient;

                    public void discoverServices() {
                        // 获取所有服务名称
                        Flux<String> serviceIds = Flux.from(discoveryClient.getServiceIds());
                        serviceIds.subscribe(serviceId -> {
                            System.out.println("Found service: " + serviceId);
                        });

                        // 获取特定服务的所有实例
                        Flux<ServiceInstance> instances = Flux.from(
                            discoveryClient.getInstances("order-service")
                        );

                        instances.subscribe(instance -> {
                            System.out.println("Service instance: " +
                                instance.getId() + " at " +
                                instance.getHost() + ":" +
                                instance.getPort());
                        });
                    }

                    public String callService(String serviceName, String path) {
                        // 获取服务实例
                        ServiceInstance instance = Flux.from(
                            discoveryClient.getInstances(serviceName)
                        ).blockFirst();

                        if (instance != null) {
                            String url = "http://" + instance.getHost() + ":" +
                                instance.getPort() + path;

                            HttpClient client = HttpClient.create(instance.getURI().toURL());
                            return client.toBlocking().retrieve(path);
                        }

                        throw new RuntimeException("Service not found: " + serviceName);
                    }
                }
                ---

03.Eureka集成
    a.依赖配置
        a.功能说明
            Eureka是Netflix开源的服务注册中心,广泛应用于Spring Cloud生态,Micronaut提供兼容支持。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.discovery:micronaut-discovery-client")
            }

            // application.yml
            eureka:
              client:
                registration:
                  enabled: true
                defaultZone: "${EUREKA_HOST:localhost}:${EUREKA_PORT:8761}/eureka"
            micronaut:
              application:
                name: payment-service
            ---
    b.服务注册配置
        a.功能说明
            配置Eureka客户端的注册参数,包括实例ID、租约续期时间等。
        b.配置示例
            ---
            // application.yml
            eureka:
              client:
                registration:
                  enabled: true
                  prefer-ip-address: true
                  # 实例配置
                  instance-id: ${micronaut.application.name}:${random.value}
                  lease-renewal-interval: 30s
                  lease-expiration-duration: 90s
                  # 元数据
                  metadata:
                    version: 1.0.0
                    region: us-west
                defaultZone: http://localhost:8761/eureka
              instance:
                hostname: ${HOSTNAME:localhost}
                port: ${SERVER_PORT:8080}
            ---
    c.服务调用
        a.功能说明
            通过服务名称调用Eureka注册的服务,支持客户端负载均衡。
        b.代码示例
            ---
            import io.micronaut.http.annotation.Get;
            import io.micronaut.http.annotation.Post;
            import io.micronaut.http.client.annotation.Client;

            @Client("payment-service")
            public interface PaymentClient {

                @Post("/payments")
                PaymentResult processPayment(@Body Payment payment);

                @Get("/payments/{id}")
                Payment getPayment(Long id);
            }

            // 使用示例
            @Controller("/checkout")
            public class CheckoutController {

                private final PaymentClient paymentClient;

                public CheckoutController(PaymentClient paymentClient) {
                    this.paymentClient = paymentClient;
                }

                @Post
                public HttpResponse<CheckoutResult> checkout(@Body CheckoutRequest request) {
                    Payment payment = new Payment(
                        request.getAmount(),
                        request.getPaymentMethod()
                    );

                    // 调用支付服务
                    PaymentResult result = paymentClient.processPayment(payment);

                    if ("SUCCESS".equals(result.getStatus())) {
                        return HttpResponse.ok(new CheckoutResult(true, result.getTransactionId()));
                    } else {
                        return HttpResponse.badRequest(new CheckoutResult(false, null));
                    }
                }
            }
            ---

04.Kubernetes服务发现
    a.依赖配置
        a.功能说明
            在Kubernetes环境中,Micronaut可以直接使用Kubernetes API进行服务发现,无需额外的注册中心。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.kubernetes:micronaut-kubernetes-discovery-client")
            }

            // application.yml
            kubernetes:
              client:
                discovery:
                  enabled: true
                  mode: service
                  namespace: default
            micronaut:
              application:
                name: user-service
            ---
    b.服务发现配置
        a.���能说明
            配置Kubernetes服务发现的命名空间、标签选择器等参数。
        b.配置示例
            ---
            // application.yml
            kubernetes:
              client:
                discovery:
                  enabled: true
                  mode: service
                  namespace: production
                  # 标签选择器
                  labels:
                    app: microservices
                    tier: backend
                  # 包含的服务
                  includes:
                    - order-service
                    - inventory-service
                  # 排除的服务
                  excludes:
                    - legacy-service
            ---
    c.服务调用
        a.功能说明
            通过Kubernetes Service名称调用服务,Micronaut自动解析为Pod IP地址。
        b.代码示例
            ---
            import io.micronaut.http.annotation.Get;
            import io.micronaut.http.client.annotation.Client;

            // 使用Kubernetes Service名称
            @Client("http://user-service")
            public interface UserClient {

                @Get("/users/{id}")
                User getUser(Long id);

                @Get("/users/search")
                List<User> searchUsers(String query);
            }

            // 使用示例
            @Controller("/profile")
            public class ProfileController {

                private final UserClient userClient;

                public ProfileController(UserClient userClient) {
                    this.userClient = userClient;
                }

                @Get("/{userId}")
                public User getUserProfile(Long userId) {
                    // Kubernetes自动解析服务名称
                    return userClient.getUser(userId);
                }
            }
            ---

05.负载均衡策略
    a.内置策略
        a.轮询策略
            a.功能说明
                默认的负载均衡策略,按顺序轮流调用服务实例。
            b.配置示例
                ---
                // application.yml
                micronaut:
                  http:
                    client:
                      load-balancer:
                        # 轮询策略(默认)
                        strategy: round-robin
                ---
        b.随机策略
            a.功能说明
                随机选择服务实例,适用于实例性能相近的场景。
            b.配置示例
                ---
                // application.yml
                micronaut:
                  http:
                    client:
                      load-balancer:
                        strategy: random
                ---
    b.自定义策略
        a.功能说明
            实现LoadBalancer接口,自定义负载均衡算法,如加权轮询、最少连接等。
        b.代码示例
            ---
            import io.micronaut.context.annotation.Requires;
            import io.micronaut.discovery.ServiceInstance;
            import io.micronaut.http.client.loadbalance.DiscoveryClientLoadBalancer;
            import io.micronaut.http.client.loadbalance.ServiceInstanceList;
            import jakarta.inject.Singleton;
            import reactor.core.publisher.Flux;

            @Singleton
            @Requires(property = "micronaut.http.client.load-balancer.strategy", value = "weighted")
            public class WeightedLoadBalancer extends DiscoveryClientLoadBalancer {

                public WeightedLoadBalancer(ServiceInstanceList serviceInstanceList) {
                    super(serviceInstanceList);
                }

                @Override
                public Flux<ServiceInstance> select(Object discriminator) {
                    return Flux.from(serviceInstanceList.getInstances())
                        .collectList()
                        .flatMapMany(instances -> {
                            if (instances.isEmpty()) {
                                return Flux.empty();
                            }

                            // 根据权重选择实例
                            ServiceInstance selected = selectByWeight(instances);
                            return Flux.just(selected);
                        });
                }

                private ServiceInstance selectByWeight(List<ServiceInstance> instances) {
                    int totalWeight = instances.stream()
                        .mapToInt(i -> getWeight(i))
                        .sum();

                    int random = new Random().nextInt(totalWeight);
                    int currentWeight = 0;

                    for (ServiceInstance instance : instances) {
                        currentWeight += getWeight(instance);
                        if (random < currentWeight) {
                            return instance;
                        }
                    }

                    return instances.get(0);
                }

                private int getWeight(ServiceInstance instance) {
                    return instance.getMetadata()
                        .get("weight")
                        .map(Integer::parseInt)
                        .orElse(1);
                }
            }
            ---

6.5 配置中心集成

01.配置中心概述
    a.核心概念
        配置中心提供集中化的配置管理,支持配置的动态更新、版本控制和环境隔离。Micronaut支持多种配置中心,包括Consul、Spring Cloud Config、AWS Parameter Store等,实现配置与代码的分离,简化多环境部署和配置管理。
    b.主要优势
        a.集中管理
            所有服务的配置集中存储在配置中心,统一管理和维护,避免配置分散在各个服务中,降低管理复杂度。
        b.动态更新
            配置变更后无需重启服务即可生效,支持热更新,提升系统的灵活性和可维护性。
        c.环境隔离
            不同环境使用不同的配置,如开发、测试、生产环境,通过命名空间或标签实现配置隔离。

02.Consul配置中心
    a.依赖配置
        a.功能说明
            Consul的KV存储可以作为配置中心,Micronaut自动从Consul加载配置,支持配置的动态刷新。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.discovery:micronaut-discovery-client")
            }

            // bootstrap.yml
            micronaut:
              application:
                name: order-service
              config-client:
                enabled: true
            consul:
              client:
                config:
                  enabled: true
                  format: YAML
                  path: /config
                defaultZone: localhost:8500
            ---
    b.配置存储
        a.功能说明
            在Consul KV存储中按照约定的路径存储配置,Micronaut自动加载对应的配置。
        b.配置示例
            ---
            # Consul KV路径结构
            /config/application/data          # 所有应用共享配置
            /config/order-service/data        # order-service专属配置
            /config/order-service,prod/data   # order-service生产环境配置

            # 配置内容示例(YAML格式)
            # /config/order-service/data
            datasources:
              default:
                url: jdbc:mysql://localhost:3306/orders
                username: root
                password: secret
                driver-class-name: com.mysql.cj.jdbc.Driver

            kafka:
              bootstrap:
                servers: localhost:9092

            # 使用配置
            import io.micronaut.context.annotation.Value;
            import jakarta.inject.Singleton;

            @Singleton
            public class DatabaseConfig {

                @Value("${datasources.default.url}")
                private String dbUrl;

                @Value("${datasources.default.username}")
                private String dbUsername;

                public void printConfig() {
                    System.out.println("Database URL: " + dbUrl);
                    System.out.println("Database User: " + dbUsername);
                }
            }
            ---
    c.动态刷新
        a.功能说明
            配置变更后,Micronaut自动检测并刷新配置,使用@Refreshable注解的Bean会重新创建。
        b.代码示例
            ---
            import io.micronaut.context.annotation.ConfigurationProperties;
            import io.micronaut.runtime.context.scope.Refreshable;

            @Refreshable
            @ConfigurationProperties("app")
            public class AppConfig {

                private String name;
                private int maxConnections;
                private boolean debugMode;

                // Getters and Setters
                public String getName() {
                    return name;
                }

                public void setName(String name) {
                    this.name = name;
                }

                public int getMaxConnections() {
                    return maxConnections;
                }

                public void setMaxConnections(int maxConnections) {
                    this.maxConnections = maxConnections;
                }

                public boolean isDebugMode() {
                    return debugMode;
                }

                public void setDebugMode(boolean debugMode) {
                    this.debugMode = debugMode;
                }
            }

            // 使用配置
            @Controller("/config")
            public class ConfigController {

                private final AppConfig appConfig;

                public ConfigController(AppConfig appConfig) {
                    this.appConfig = appConfig;
                }

                @Get("/current")
                public Map<String, Object> getCurrentConfig() {
                    return Map.of(
                        "name", appConfig.getName(),
                        "maxConnections", appConfig.getMaxConnections(),
                        "debugMode", appConfig.isDebugMode()
                    );
                }
            }
            ---

03.Spring Cloud Config集成
    a.依赖配置
        a.功能说明
            Spring Cloud Config是广泛使用的配置中心,Micronaut提供兼容支持,可以复用现有的Config Server。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.spring:micronaut-spring-cloud-config-client")
            }

            // bootstrap.yml
            micronaut:
              application:
                name: payment-service
              config-client:
                enabled: true
            spring:
              cloud:
                config:
                  enabled: true
                  uri: http://localhost:8888
                  # 配置文件名称
                  name: ${micronaut.application.name}
                  # 环境
                  profile: production
                  # 分支
                  label: master
                  # 失败快速启动
                  fail-fast: true
                  # 重试配置
                  retry:
                    max-attempts: 6
                    initial-interval: 1000
            ---
    b.配置文件
        a.功能说明
            在Config Server的Git仓库中存储配置文件,按照应用名称和环境组织。
        b.配置示例
            ---
            # Git仓库结构
            config-repo/
              ├── application.yml              # 所有应用共享
              ├── payment-service.yml          # payment-service默认配置
              ├── payment-service-dev.yml      # 开发环境
              ├── payment-service-prod.yml     # 生产环境

            # payment-service-prod.yml
            server:
              port: 8080

            datasources:
              default:
                url: jdbc:postgresql://prod-db:5432/payments
                username: ${DB_USER}
                password: ${DB_PASSWORD}

            security:
              jwt:
                secret: ${JWT_SECRET}
                expiration: 3600

            # 使用配置
            import io.micronaut.context.annotation.ConfigurationProperties;

            @ConfigurationProperties("security.jwt")
            public class JwtConfig {

                private String secret;
                private int expiration;

                public String getSecret() {
                    return secret;
                }

                public void setSecret(String secret) {
                    this.secret = secret;
                }

                public int getExpiration() {
                    return expiration;
                }

                public void setExpiration(int expiration) {
                    this.expiration = expiration;
                }
            }
            ---
    c.配置刷新
        a.功能说明
            通过RefreshEvent触发配置刷新,或使用/refresh端点手动刷新。
        b.代码示例
            ---
            import io.micronaut.context.event.ApplicationEventPublisher;
            import io.micronaut.runtime.context.scope.refresh.RefreshEvent;
            import io.micronaut.http.annotation.Controller;
            import io.micronaut.http.annotation.Post;
            import jakarta.inject.Inject;

            @Controller("/admin")
            public class AdminController {

                @Inject
                private ApplicationEventPublisher<RefreshEvent> eventPublisher;

                // 手动触发配置刷新
                @Post("/refresh")
                public String refreshConfig() {
                    eventPublisher.publishEvent(new RefreshEvent());
                    return "Configuration refreshed";
                }
            }

            // 监听配置刷新事件
            import io.micronaut.context.event.ApplicationEventListener;
            import io.micronaut.runtime.context.scope.refresh.RefreshEvent;
            import jakarta.inject.Singleton;

            @Singleton
            public class ConfigRefreshListener implements ApplicationEventListener<RefreshEvent> {

                @Override
                public void onApplicationEvent(RefreshEvent event) {
                    System.out.println("Configuration refreshed at: " + System.currentTimeMillis());
                    // 执行刷新后的逻辑
                }
            }
            ---

04.AWS Parameter Store集成
    a.依赖配置
        a.功能说明
            AWS Systems Manager Parameter Store提供安全的配置和密钥管理,Micronaut支持从Parameter Store加载配置。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.aws:micronaut-aws-parameter-store")
            }

            // bootstrap.yml
            micronaut:
              application:
                name: user-service
              config-client:
                enabled: true
            aws:
              client:
                system-manager:
                  parameterstore:
                    enabled: true
                    # 参数路径前缀
                    path: /config/user-service
                    # 是否使用安全字符串
                    use-secure-strings: true
              region: us-east-1
            ---
    b.参数存储
        a.功能说明
            在AWS Parameter Store中按照层级路径存储参数,支持普通字符串和加密字符串。
        b.配置示例
            ---
            # AWS Parameter Store参数结构
            /config/user-service/database/url
            /config/user-service/database/username
            /config/user-service/database/password  # SecureString类型

            # 使用AWS CLI创建参数
            aws ssm put-parameter \
              --name "/config/user-service/database/url" \
              --value "jdbc:mysql://prod-db:3306/users" \
              --type "String"

            aws ssm put-parameter \
              --name "/config/user-service/database/password" \
              --value "secret-password" \
              --type "SecureString"

            # 在代码中使用
            import io.micronaut.context.annotation.Value;
            import jakarta.inject.Singleton;

            @Singleton
            public class DatabaseService {

                @Value("${database.url}")
                private String dbUrl;

                @Value("${database.username}")
                private String dbUsername;

                @Value("${database.password}")
                private String dbPassword;

                public void connect() {
                    System.out.println("Connecting to: " + dbUrl);
                    // 使用加密的密码连接数据库
                }
            }
            ---
    c.动态配置
        a.功能说明
            Parameter Store支持配置的版本管理和动态更新,Micronaut可以定期轮询获取最新配置。
        b.配置示例
            ---
            // bootstrap.yml
            aws:
              client:
                system-manager:
                  parameterstore:
                    enabled: true
                    path: /config/user-service
                    # 启用自动刷新
                    watch: true
                    # 刷新间隔
                    watch-delay: 60s

            # 使用@Refreshable注解
            import io.micronaut.runtime.context.scope.Refreshable;
            import io.micronaut.context.annotation.ConfigurationProperties;

            @Refreshable
            @ConfigurationProperties("feature")
            public class FeatureConfig {

                private boolean newFeatureEnabled;
                private int maxRetries;

                public boolean isNewFeatureEnabled() {
                    return newFeatureEnabled;
                }

                public void setNewFeatureEnabled(boolean newFeatureEnabled) {
                    this.newFeatureEnabled = newFeatureEnabled;
                }

                public int getMaxRetries() {
                    return maxRetries;
                }

                public void setMaxRetries(int maxRetries) {
                    this.maxRetries = maxRetries;
                }
            }
            ---

05.配置最佳实践
    a.敏感信息管理
        a.功能说明
            敏感信息如密码、密钥应使用加密存储,避免明文配置。
        b.代码示例
            ---
            # 使用环境变量
            datasources:
              default:
                url: jdbc:mysql://localhost:3306/db
                username: ${DB_USER}
                password: ${DB_PASSWORD}

            # 使用Consul加密
            # 在Consul中存储加密后的值
            consul kv put /config/order-service/db-password "encrypted:AES:base64value"

            # 使用AWS Secrets Manager
            // build.gradle
            dependencies {
                implementation("io.micronaut.aws:micronaut-aws-secretsmanager")
            }

            // bootstrap.yml
            aws:
              client:
                secrets-manager:
                  enabled: true
              region: us-east-1

            # 在代码中使用
            import io.micronaut.context.annotation.Value;

            @Singleton
            public class SecretService {

                @Value("${/secret/database/password}")
                private String dbPassword;

                public void useSecret() {
                    // 自动从Secrets Manager获取密钥
                    System.out.println("Using secret: " + dbPassword);
                }
            }
            ---
    b.配置优先级
        a.功能说明
            Micronaut支持多种配置源,按照优先级合并配置,高优先级覆盖低优先级。
        b.配置示例
            ---
            # 配置优先级(从高到低)
            # 1. 命令行参数
            java -jar app.jar --server.port=9090

            # 2. 系统属性
            java -Dserver.port=9090 -jar app.jar

            # 3. 环境变量
            export SERVER_PORT=9090

            # 4. 配置中心(Consul/Config Server)
            # 5. application.yml
            # 6. application-{env}.yml

            # 配置合并示例
            import io.micronaut.context.env.Environment;
            import jakarta.inject.Inject;
            import jakarta.inject.Singleton;

            @Singleton
            public class ConfigService {

                @Inject
                private Environment environment;

                public void printConfigSources() {
                    environment.getPropertySources().forEach(source -> {
                        System.out.println("Config source: " + source.getName());
                    });
                }

                public String getProperty(String key) {
                    return environment.getProperty(key, String.class).orElse("default");
                }
            }
            ---
    c.配置验证
        a.功能说明
            使用Bean Validation验证配置的有效性,启动时检查配置错误。
        b.代码示例
            ---
            import io.micronaut.context.annotation.ConfigurationProperties;
            import jakarta.validation.constraints.Min;
            import jakarta.validation.constraints.NotBlank;
            import jakarta.validation.constraints.Pattern;

            @ConfigurationProperties("app")
            public class ValidatedConfig {

                @NotBlank(message = "Application name is required")
                private String name;

                @Min(value = 1, message = "Max connections must be at least 1")
                private int maxConnections;

                @Pattern(regexp = "^(dev|test|prod)$", message = "Invalid environment")
                private String environment;

                // Getters and Setters
                public String getName() {
                    return name;
                }

                public void setName(String name) {
                    this.name = name;
                }

                public int getMaxConnections() {
                    return maxConnections;
                }

                public void setMaxConnections(int maxConnections) {
                    this.maxConnections = maxConnections;
                }

                public String getEnvironment() {
                    return environment;
                }

                public void setEnvironment(String environment) {
                    this.environment = environment;
                }
            }

            // 配置验证失败时,应用启动会抛出异常
            // application.yml
            app:
              name: ""  # 验证失败:name不能为空
              max-connections: 0  # 验证失败:必须至少为1
              environment: "invalid"  # 验证失败:必须是dev/test/prod
            ---

6.6 安全认证

01.安全认证概述
    a.核心概念
        Micronaut Security提供全面的安全认证和授权功能,支持JWT、OAuth 2.0、LDAP等多种认证方式,内置CSRF防护、会话管理等安全特性,简化应用的安全实现。
    b.主要优势
        a.多种认证方式
            支持基于Token的认证、基于Session的认证、OAuth 2.0社交登录等多种认证机制,满足不同场景需求。
        b.声明式安全
            使用注解声明式配置安全规则,如@Secured、@RolesAllowed等,代码简洁清晰,易于维护。
        c.细粒度授权
            支持基于角色和权限的访问控制,可以精确控制到方法级别的访问权限。

02.JWT认证
    a.依赖配置
        a.功能说明
            JWT是无状态的Token认证方式,适用于微服务和移动应用,Micronaut提供完整的JWT支持。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.security:micronaut-security-jwt")
            }

            // application.yml
            micronaut:
              security:
                enabled: true
                token:
                  jwt:
                    enabled: true
                    signatures:
                      secret:
                        generator:
                          secret: "${JWT_SECRET:pleaseChangeThisSecretKey}"
                          jws-algorithm: HS256
                    generator:
                      access-token:
                        expiration: 3600
            ---
    b.用户认证
        a.功能说明
            实现AuthenticationProvider接口,自定义用户认证逻辑,验证用户名和密码。
        b.代码示例
            ---
            import io.micronaut.http.HttpRequest;
            import io.micronaut.security.authentication.*;
            import io.reactivex.rxjava3.core.Flowable;
            import jakarta.inject.Singleton;
            import org.reactivestreams.Publisher;

            @Singleton
            public class CustomAuthenticationProvider implements AuthenticationProvider<HttpRequest<?>> {

                @Override
                public Publisher<AuthenticationResponse> authenticate(
                    HttpRequest<?> httpRequest,
                    AuthenticationRequest<?, ?> authenticationRequest
                ) {
                    String username = authenticationRequest.getIdentity().toString();
                    String password = authenticationRequest.getSecret().toString();

                    // 验证用户名和密码
                    if ("admin".equals(username) && "password".equals(password)) {
                        return Flowable.just(
                            AuthenticationResponse.success(
                                username,
                                List.of("ROLE_ADMIN", "ROLE_USER")
                            )
                        );
                    } else if ("user".equals(username) && "password".equals(password)) {
                        return Flowable.just(
                            AuthenticationResponse.success(
                                username,
                                List.of("ROLE_USER")
                            )
                        );
                    }

                    return Flowable.just(
                        AuthenticationResponse.failure(
                            AuthenticationFailureReason.CREDENTIALS_DO_NOT_MATCH
                        )
                    );
                }
            }
            ---
    c.登录端点
        a.功能说明
            创建登录端点,接收用户凭证并返回JWT Token。
        b.代码示例
            ---
            import io.micronaut.http.annotation.Body;
            import io.micronaut.http.annotation.Controller;
            import io.micronaut.http.annotation.Post;
            import io.micronaut.security.annotation.Secured;
            import io.micronaut.security.rules.SecurityRule;

            @Controller("/auth")
            @Secured(SecurityRule.IS_ANONYMOUS)
            public class AuthController {

                // 登录端点由Micronaut Security自动提供
                // POST /login
                // {
                //   "username": "admin",
                //   "password": "password"
                // }
                // 返回:
                // {
                //   "username": "admin",
                //   "roles": ["ROLE_ADMIN", "ROLE_USER"],
                //   "access_token": "eyJhbGciOiJIUzI1NiJ9...",
                //   "token_type": "Bearer",
                //   "expires_in": 3600
                // }
            }

            // 受保护的端点
            import io.micronaut.security.authentication.Authentication;

            @Controller("/api")
            public class SecureController {

                @Get("/profile")
                @Secured(SecurityRule.IS_AUTHENTICATED)
                public Map<String, Object> getProfile(Authentication authentication) {
                    return Map.of(
                        "username", authentication.getName(),
                        "roles", authentication.getRoles()
                    );
                }

                @Get("/admin")
                @Secured("ROLE_ADMIN")
                public String adminOnly() {
                    return "Admin access granted";
                }

                @Get("/user")
                @Secured({"ROLE_USER", "ROLE_ADMIN"})
                public String userAccess() {
                    return "User access granted";
                }
            }
            ---
    d.Token刷新
        a.功能说明
            实现Token刷新机制,延长用户会话时间,无需重新登录。
        b.代码示例
            ---
            // application.yml
            micronaut:
              security:
                token:
                  jwt:
                    generator:
                      refresh-token:
                        enabled: true
                        secret: "${JWT_REFRESH_SECRET:anotherSecretKey}"

            // 刷新Token端点
            import io.micronaut.http.annotation.Post;
            import io.micronaut.http.annotation.Body;
            import io.micronaut.security.annotation.Secured;
            import io.micronaut.security.rules.SecurityRule;
            import io.micronaut.security.token.jwt.generator.JwtTokenGenerator;
            import io.micronaut.security.token.jwt.validator.JwtTokenValidator;

            @Controller("/auth")
            public class TokenController {

                private final JwtTokenGenerator tokenGenerator;

                public TokenController(JwtTokenGenerator tokenGenerator) {
                    this.tokenGenerator = tokenGenerator;
                }

                @Post("/refresh")
                @Secured(SecurityRule.IS_ANONYMOUS)
                public Map<String, Object> refresh(@Body Map<String, String> request) {
                    String refreshToken = request.get("refresh_token");

                    // 验证refresh token并生成新的access token
                    // 实际实现需要验证refresh token的有效性
                    Optional<String> newToken = tokenGenerator.generateToken(
                        Map.of("username", "user", "roles", List.of("ROLE_USER"))
                    );

                    if (newToken.isPresent()) {
                        return Map.of(
                            "access_token", newToken.get(),
                            "token_type", "Bearer",
                            "expires_in", 3600
                        );
                    }

                    throw new RuntimeException("Invalid refresh token");
                }
            }
            ---

03.OAuth 2.0集成
    a.依赖配置
        a.功能说明
            Micronaut支持OAuth 2.0授权码流程,可以集成Google、GitHub、Facebook等第三方登录。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.security:micronaut-security-oauth2")
            }

            // application.yml
            micronaut:
              security:
                oauth2:
                  enabled: true
                  clients:
                    google:
                      client-id: ${GOOGLE_CLIENT_ID}
                      client-secret: ${GOOGLE_CLIENT_SECRET}
                      scopes:
                        - email
                        - profile
                    github:
                      client-id: ${GITHUB_CLIENT_ID}
                      client-secret: ${GITHUB_CLIENT_SECRET}
                      scopes:
                        - user:email
                        - read:user
            ---
    b.OAuth登录
        a.功能说明
            配置OAuth 2.0登录端点,用户通过第三方平台完成认证。
        b.代码示例
            ---
            import io.micronaut.http.annotation.Controller;
            import io.micronaut.http.annotation.Get;
            import io.micronaut.security.annotation.Secured;
            import io.micronaut.security.rules.SecurityRule;
            import io.micronaut.security.authentication.Authentication;

            @Controller
            public class OAuthController {

                // OAuth登录端点由Micronaut自动提供
                // GET /oauth/login/google  - 跳转到Google登录
                // GET /oauth/login/github  - 跳转到GitHub登录

                // OAuth回调端点
                // GET /oauth/callback/google
                // GET /oauth/callback/github

                @Get("/")
                @Secured(SecurityRule.IS_ANONYMOUS)
                public String home() {
                    return """
                        <html>
                        <body>
                            <h1>Login</h1>
                            <a href="/oauth/login/google">Login with Google</a><br>
                            <a href="/oauth/login/github">Login with GitHub</a>
                        </body>
                        </html>
                        """;
                }

                @Get("/dashboard")
                @Secured(SecurityRule.IS_AUTHENTICATED)
                public Map<String, Object> dashboard(Authentication authentication) {
                    return Map.of(
                        "message", "Welcome to dashboard",
                        "user", authentication.getName(),
                        "attributes", authentication.getAttributes()
                    );
                }
            }
            ---
    c.自定义用户映射
        a.功能说明
            OAuth认证成功后,将第三方用户信息映射到应用的用户模型。
        b.代码示例
            ---
            import io.micronaut.context.annotation.Replaces;
            import io.micronaut.security.oauth2.endpoint.authorization.state.State;
            import io.micronaut.security.oauth2.endpoint.token.response.OauthAuthenticationMapper;
            import io.micronaut.security.oauth2.endpoint.token.response.TokenResponse;
            import io.micronaut.security.authentication.AuthenticationResponse;
            import jakarta.inject.Named;
            import jakarta.inject.Singleton;
            import org.reactivestreams.Publisher;
            import reactor.core.publisher.Mono;

            @Singleton
            @Named("google")
            public class GoogleUserMapper implements OauthAuthenticationMapper {

                @Override
                public Publisher<AuthenticationResponse> createAuthenticationResponse(
                    TokenResponse tokenResponse,
                    State state
                ) {
                    // 从tokenResponse获取用户信息
                    Map<String, Object> claims = tokenResponse.getClaims();
                    String email = (String) claims.get("email");
                    String name = (String) claims.get("name");

                    // 创建应用用户
                    return Mono.just(
                        AuthenticationResponse.success(
                            email,
                            List.of("ROLE_USER"),
                            Map.of(
                                "name", name,
                                "email", email,
                                "provider", "google"
                            )
                        )
                    );
                }
            }
            ---

04.基于角色的访问控制
    a.方法级安全
        a.功能说明
            使用@Secured注解保护方法,限制只有特定角色的用户才能访问。
        b.代码示例
            ---
            import io.micronaut.http.annotation.*;
            import io.micronaut.security.annotation.Secured;
            import io.micronaut.security.rules.SecurityRule;
            import jakarta.annotation.security.RolesAllowed;

            @Controller("/orders")
            public class OrderController {

                // 允许所有认证用户访问
                @Get
                @Secured(SecurityRule.IS_AUTHENTICATED)
                public List<Order> listOrders() {
                    return orderService.findAll();
                }

                // 只允许ADMIN角色访问
                @Delete("/{id}")
                @Secured("ROLE_ADMIN")
                public HttpResponse<?> deleteOrder(Long id) {
                    orderService.delete(id);
                    return HttpResponse.noContent();
                }

                // 允许多个角色访问
                @Put("/{id}")
                @Secured({"ROLE_ADMIN", "ROLE_MANAGER"})
                public Order updateOrder(Long id, @Body Order order) {
                    return orderService.update(id, order);
                }

                // 使用JSR-250注解
                @Post
                @RolesAllowed({"ADMIN", "USER"})
                public Order createOrder(@Body Order order) {
                    return orderService.create(order);
                }

                // 允许匿名访问
                @Get("/public")
                @Secured(SecurityRule.IS_ANONYMOUS)
                public String publicEndpoint() {
                    return "Public access";
                }
            }
            ---
    b.表达式安全
        a.功能说明
            使用SpEL表��式实现复杂的访问控制逻辑。
        b.代码示例
            ---
            import io.micronaut.security.annotation.Secured;
            import io.micronaut.security.authentication.Authentication;

            @Controller("/documents")
            public class DocumentController {

                // 自定义安全规则
                @Get("/{id}")
                @Secured("#{authentication.name == #id or hasRole('ADMIN')}")
                public Document getDocument(Long id, Authentication authentication) {
                    return documentService.findById(id);
                }

                // 基于方法参数的安全检查
                @Put("/{id}")
                public Document updateDocument(
                    Long id,
                    @Body Document document,
                    Authentication authentication
                ) {
                    // 检查用户是否有权限修改文档
                    Document existing = documentService.findById(id);

                    if (!existing.getOwnerId().equals(authentication.getName()) &&
                        !authentication.getRoles().contains("ROLE_ADMIN")) {
                        throw new ForbiddenException("Access denied");
                    }

                    return documentService.update(id, document);
                }
            }
            ---

05.安全最佳实践
    a.密码加密
        a.功能说明
            使用BCrypt等强加密算法存储密码,避免明文存储。
        b.代码示例
            ---
            import io.micronaut.security.authentication.providers.PasswordEncoder;
            import jakarta.inject.Singleton;
            import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

            @Singleton
            public class UserService {

                private final PasswordEncoder passwordEncoder;

                public UserService(PasswordEncoder passwordEncoder) {
                    this.passwordEncoder = passwordEncoder;
                }

                public User registerUser(String username, String rawPassword) {
                    // 加密密码
                    String encodedPassword = passwordEncoder.encode(rawPassword);

                    User user = new User();
                    user.setUsername(username);
                    user.setPassword(encodedPassword);

                    return userRepository.save(user);
                }

                public boolean verifyPassword(String rawPassword, String encodedPassword) {
                    return passwordEncoder.matches(rawPassword, encodedPassword);
                }
            }
            ---
    b.CSRF防护
        a.功能说明
            启用CSRF防护,防止跨站请求伪造攻击。
        b.配置示例
            ---
            // application.yml
            micronaut:
              security:
                csrf:
                  enabled: true
                  # CSRF Token生成策略
                  token-generator-class: io.micronaut.security.token.jwt.generator.DefaultJwtTokenGenerator

            // 在表单中包含CSRF Token
            import io.micronaut.http.annotation.Controller;
            import io.micronaut.http.annotation.Get;
            import io.micronaut.security.csrf.CsrfToken;

            @Controller("/form")
            public class FormController {

                @Get
                public String showForm(CsrfToken csrfToken) {
                    return """
                        <form method="POST" action="/submit">
                            <input type="hidden" name="_csrf" value="%s">
                            <input type="text" name="data">
                            <button type="submit">Submit</button>
                        </form>
                        """.formatted(csrfToken.getToken());
                }
            }
            ---
    c.安全头配置
        a.功能说明
            配置HTTP安全头,增强应用的安全性。
        b.配置示例
            ---
            // application.yml
            micronaut:
              security:
                enabled: true
                # 安全头配置
                intercept-url-map:
                  - pattern: /**
                    http-method: GET
                    access:
                      - isAnonymous()
                # X-Frame-Options
                x-frame-options:
                  enabled: true
                  mode: DENY
                # X-Content-Type-Options
                x-content-type-options:
                  enabled: true
                # X-XSS-Protection
                x-xss-protection:
                  enabled: true
                  mode: block
            ---

6.7 GraphQL支持

01.GraphQL概述
    a.核心概念
        GraphQL是一种API查询语言,客户端可以精确指定需要的数据字段,避免过度获取或获取不足的问题。Micronaut提供GraphQL集成,支持Schema定义、查询解析和订阅功能,简化GraphQL API的开发。
    b.主要优势
        a.精确数据获取
            客户端通过查询语句明确指定需要的字段,服务端只返回请求的数据,减少网络传输和数据处理开销。
        b.强类型系统
            GraphQL Schema定义了完整的类型系统,提供自动化的文档生成和类型验证,提升API的可维护性。
        c.单一端点
            所有查询通过单一HTTP端点处理,简化API设计和客户端集成,支持批量查询和嵌套查询。

02.GraphQL集成
    a.依赖配置
        a.功能说明
            Micronaut支持GraphQL Java实现,提供注解驱动的Schema定义和查询解析。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.graphql:micronaut-graphql")
            }

            // application.yml
            graphql:
              enabled: true
              path: /graphql
              graphiql:
                enabled: true
                path: /graphiql
            ---
    b.Schema定义
        a.功能说明
            使用GraphQL SDL定义Schema,描述API的类型、查询和变更操作。
        b.配置示例
            ---
            // src/main/resources/schema.graphqls
            type Query {
                # 查询单个用户
                user(id: ID!): User
                # 查询所有用户
                users: [User!]!
                # 查询订单
                order(id: ID!): Order
                # 查询用户的订单列表
                userOrders(userId: ID!): [Order!]!
            }

            type Mutation {
                # 创建用户
                createUser(input: CreateUserInput!): User!
                # 更新用户
                updateUser(id: ID!, input: UpdateUserInput!): User!
                # 删除用户
                deleteUser(id: ID!): Boolean!
                # 创建订单
                createOrder(input: CreateOrderInput!): Order!
            }

            type User {
                id: ID!
                username: String!
                email: String!
                orders: [Order!]!
                createdAt: String!
            }

            type Order {
                id: ID!
                userId: ID!
                user: User!
                productName: String!
                quantity: Int!
                totalAmount: Float!
                status: OrderStatus!
                createdAt: String!
            }

            enum OrderStatus {
                PENDING
                CONFIRMED
                SHIPPED
                DELIVERED
                CANCELLED
            }

            input CreateUserInput {
                username: String!
                email: String!
                password: String!
            }

            input UpdateUserInput {
                username: String
                email: String
            }

            input CreateOrderInput {
                userId: ID!
                productName: String!
                quantity: Int!
                totalAmount: Float!
            }
            ---

03.查询解析器
    a.Query实现
        a.功能说明
            实现GraphQL查询解析器,处理客户端的查询请求。
        b.代码示例
            ---
            import graphql.schema.DataFetcher;
            import graphql.schema.DataFetchingEnvironment;
            import io.micronaut.graphql.annotations.GraphQLQuery;
            import jakarta.inject.Singleton;

            @Singleton
            public class UserQueryResolver {

                private final UserService userService;

                public UserQueryResolver(UserService userService) {
                    this.userService = userService;
                }

                @GraphQLQuery
                public User user(Long id) {
                    return userService.findById(id);
                }

                @GraphQLQuery
                public List<User> users() {
                    return userService.findAll();
                }

                @GraphQLQuery
                public List<Order> userOrders(Long userId) {
                    return orderService.findByUserId(userId);
                }
            }

            @Singleton
            public class OrderQueryResolver {

                private final OrderService orderService;

                public OrderQueryResolver(OrderService orderService) {
                    this.orderService = orderService;
                }

                @GraphQLQuery
                public Order order(Long id) {
                    return orderService.findById(id);
                }
            }
            ---
    b.Mutation实现
        a.功能说明
            实现GraphQL变更解析器,处理数据的创建、更新和删除操作。
        b.代码示例
            ---
            import io.micronaut.graphql.annotations.GraphQLMutation;
            import jakarta.inject.Singleton;

            @Singleton
            public class UserMutationResolver {

                private final UserService userService;

                public UserMutationResolver(UserService userService) {
                    this.userService = userService;
                }

                @GraphQLMutation
                public User createUser(CreateUserInput input) {
                    User user = new User();
                    user.setUsername(input.getUsername());
                    user.setEmail(input.getEmail());
                    user.setPassword(input.getPassword());

                    return userService.create(user);
                }

                @GraphQLMutation
                public User updateUser(Long id, UpdateUserInput input) {
                    User user = userService.findById(id);

                    if (input.getUsername() != null) {
                        user.setUsername(input.getUsername());
                    }
                    if (input.getEmail() != null) {
                        user.setEmail(input.getEmail());
                    }

                    return userService.update(user);
                }

                @GraphQLMutation
                public Boolean deleteUser(Long id) {
                    userService.delete(id);
                    return true;
                }
            }

            @Singleton
            public class OrderMutationResolver {

                private final OrderService orderService;

                public OrderMutationResolver(OrderService orderService) {
                    this.orderService = orderService;
                }

                @GraphQLMutation
                public Order createOrder(CreateOrderInput input) {
                    Order order = new Order();
                    order.setUserId(input.getUserId());
                    order.setProductName(input.getProductName());
                    order.setQuantity(input.getQuantity());
                    order.setTotalAmount(input.getTotalAmount());
                    order.setStatus(OrderStatus.PENDING);

                    return orderService.create(order);
                }
            }
            ---
    c.字���解析器
        a.功能说明
            实现嵌套字段的解析器,处理对象关联查询。
        b.代码示例
            ---
            import graphql.schema.DataFetcher;
            import graphql.schema.DataFetchingEnvironment;
            import io.micronaut.graphql.annotations.GraphQLDataFetcher;
            import jakarta.inject.Singleton;

            @Singleton
            public class UserFieldResolver {

                private final OrderService orderService;

                public UserFieldResolver(OrderService orderService) {
                    this.orderService = orderService;
                }

                // 解析User.orders字段
                @GraphQLDataFetcher("User.orders")
                public List<Order> orders(DataFetchingEnvironment env) {
                    User user = env.getSource();
                    return orderService.findByUserId(user.getId());
                }
            }

            @Singleton
            public class OrderFieldResolver {

                private final UserService userService;

                public OrderFieldResolver(UserService userService) {
                    this.userService = userService;
                }

                // 解析Order.user字段
                @GraphQLDataFetcher("Order.user")
                public User user(DataFetchingEnvironment env) {
                    Order order = env.getSource();
                    return userService.findById(order.getUserId());
                }
            }
            ---

04.GraphQL查询示例
    a.基础查询
        a.功能说明
            客户端发送GraphQL查询,精确指定需要的字段。
        b.查询示例
            ---
            # 查询单个用户
            query {
              user(id: "1") {
                id
                username
                email
              }
            }

            # 查询用户及其订单
            query {
              user(id: "1") {
                id
                username
                email
                orders {
                  id
                  productName
                  quantity
                  totalAmount
                  status
                }
              }
            }

            # 查询多个资源
            query {
              users {
                id
                username
              }
              order(id: "100") {
                id
                productName
                user {
                  username
                }
              }
            }
            ---
    b.变更操作
        a.功能说明
            使用Mutation执行数据的创建、更新和删除操作。
        b.查询示例
            ---
            # 创建用户
            mutation {
              createUser(input: {
                username: "john_doe"
                email: "[email protected]"
                password: "secret123"
              }) {
                id
                username
                email
                createdAt
              }
            }

            # 更新用户
            mutation {
              updateUser(id: "1", input: {
                username: "john_updated"
                email: "[email protected]"
              }) {
                id
                username
                email
              }
            }

            # 创建订单
            mutation {
              createOrder(input: {
                userId: "1"
                productName: "Laptop"
                quantity: 1
                totalAmount: 999.99
              }) {
                id
                productName
                status
                user {
                  username
                }
              }
            }
            ---
    c.查询变量
        a.功能说明
            使用变量参数化查询,提高查询的复用性和安全性。
        b.查询示例
            ---
            # 查询定义
            query GetUser($userId: ID!) {
              user(id: $userId) {
                id
                username
                email
                orders {
                  id
                  productName
                  totalAmount
                }
              }
            }

            # 变量
            {
              "userId": "1"
            }

            # 创建用户Mutation
            mutation CreateUser($input: CreateUserInput!) {
              createUser(input: $input) {
                id
                username
                email
              }
            }

            # 变量
            {
              "input": {
                "username": "jane_doe",
                "email": "[email protected]",
                "password": "password123"
              }
            }
            ---

05.高级特性
    a.DataLoader
        a.功能说明
            使用DataLoader解决N+1查询问题,批量加载关联数据,提升查询性能。
        b.代码示例
            ---
            import org.dataloader.DataLoader;
            import org.dataloader.DataLoaderRegistry;
            import io.micronaut.context.annotation.Factory;
            import jakarta.inject.Singleton;

            @Factory
            public class DataLoaderFactory {

                @Singleton
                public DataLoaderRegistry dataLoaderRegistry(UserService userService) {
                    DataLoaderRegistry registry = new DataLoaderRegistry();

                    // 用户DataLoader
                    DataLoader<Long, User> userLoader = DataLoader.newDataLoader(
                        userIds -> CompletableFuture.supplyAsync(() ->
                            userService.findByIds(userIds)
                        )
                    );

                    registry.register("userLoader", userLoader);
                    return registry;
                }
            }

            // 在字段解析器中使用
            @Singleton
            public class OrderFieldResolver {

                @GraphQLDataFetcher("Order.user")
                public CompletableFuture<User> user(DataFetchingEnvironment env) {
                    Order order = env.getSource();
                    DataLoader<Long, User> userLoader = env.getDataLoader("userLoader");
                    return userLoader.load(order.getUserId());
                }
            }
            ---
    b.订阅支持
        a.功能说明
            实现GraphQL订阅,支持实时数据推送。
        b.代码示例
            ---
            // Schema定义
            type Subscription {
                orderCreated: Order!
                orderStatusChanged(orderId: ID!): Order!
            }

            // 订阅解析器
            import io.micronaut.graphql.annotations.GraphQLSubscription;
            import org.reactivestreams.Publisher;
            import reactor.core.publisher.Flux;

            @Singleton
            public class OrderSubscriptionResolver {

                private final Flux<Order> orderStream;

                public OrderSubscriptionResolver() {
                    this.orderStream = Flux.create(emitter -> {
                        // 订阅订单创建事件
                    });
                }

                @GraphQLSubscription
                public Publisher<Order> orderCreated() {
                    return orderStream;
                }

                @GraphQLSubscription
                public Publisher<Order> orderStatusChanged(Long orderId) {
                    return orderStream.filter(order ->
                        order.getId().equals(orderId)
                    );
                }
            }

            // 客户端订阅
            subscription {
              orderCreated {
                id
                productName
                status
                user {
                  username
                }
              }
            }
            ---
    c.错误处理
        a.功能说明
            自定义GraphQL错误处理,提供友好的错误信息。
        b.代码示例
            ---
            import graphql.GraphQLError;
            import graphql.GraphqlErrorBuilder;
            import graphql.schema.DataFetchingEnvironment;
            import io.micronaut.graphql.errors.GraphQLErrorHandler;
            import jakarta.inject.Singleton;

            @Singleton
            public class CustomErrorHandler implements GraphQLErrorHandler {

                @Override
                public GraphQLError handleException(
                    DataFetchingEnvironment environment,
                    Throwable exception
                ) {
                    if (exception instanceof NotFoundException) {
                        return GraphqlErrorBuilder.newError(environment)
                            .message("Resource not found: " + exception.getMessage())
                            .errorType(ErrorType.NOT_FOUND)
                            .build();
                    }

                    if (exception instanceof ValidationException) {
                        return GraphqlErrorBuilder.newError(environment)
                            .message("Validation failed: " + exception.getMessage())
                            .errorType(ErrorType.VALIDATION_ERROR)
                            .build();
                    }

                    return GraphqlErrorBuilder.newError(environment)
                        .message("Internal server error")
                        .errorType(ErrorType.INTERNAL_ERROR)
                        .build();
                }
            }
            ---

6.8 GraalVM原生镜像

01.GraalVM概述
    a.核心概念
        GraalVM原生镜像将Java应用编译为本地可执行文件,实现毫秒级启动时间和极低的内存占用。Micronaut专为GraalVM优化,通过编译时依赖注入和反射元数据生成,简化原生镜像的构建过程。
    b.主要优势
        a.快速启动
            原生镜像启动时间从秒级降低到毫秒级,适用于Serverless和容器化场景,显著提升应用的响应速度。
        b.低内存占用
            原生镜像的内存占用比JVM应用减少50%-80%,降低基础设施成本,提升资源利用率。
        c.即时性能
            无需JVM预热,应用启动即达到峰值性能,避免传统JVM的冷启动问题。

02.环境准备
    a.GraalVM安装
        a.功能说明
            安装GraalVM和Native Image工具,配置环境变量。
        b.安装步骤
            ---
            # 下载GraalVM
            # https://www.graalvm.org/downloads/

            # macOS/Linux安装
            export GRAALVM_HOME=/path/to/graalvm
            export PATH=$GRAALVM_HOME/bin:$PATH

            # 安装Native Image
            gu install native-image

            # 验证安装
            java -version
            native-image --version

            # Windows安装
            # 1. 下载GraalVM Windows版本
            # 2. 解压到目录,如 C:\graalvm
            # 3. 设置环境变量
            #    GRAALVM_HOME=C:\graalvm
            #    PATH=%GRAALVM_HOME%\bin;%PATH%
            # 4. 安装Native Image
            gu.cmd install native-image
            ---
    b.项目配置
        a.功能说明
            配置Gradle或Maven项目,添加GraalVM Native Image插件。
        b.配置示例
            ---
            // build.gradle
            plugins {
                id("io.micronaut.application") version "4.0.0"
                id("io.micronaut.graalvm") version "4.0.0"
            }

            graalvmNative {
                binaries {
                    main {
                        imageName = "micronaut-app"
                        mainClass = "com.example.Application"
                        buildArgs.add("--verbose")
                        buildArgs.add("-H:+ReportExceptionStackTraces")
                    }
                }
            }

            // Maven配置
            <plugin>
                <groupId>org.graalvm.buildtools</groupId>
                <artifactId>native-maven-plugin</artifactId>
                <version>0.9.28</version>
                <configuration>
                    <imageName>micronaut-app</imageName>
                    <mainClass>com.example.Application</mainClass>
                    <buildArgs>
                        <buildArg>--verbose</buildArg>
                        <buildArg>-H:+ReportExceptionStackTraces</buildArg>
                    </buildArgs>
                </configuration>
            </plugin>
            ---

03.构建原生镜像
    a.本地构建
        a.功能说明
            使用Gradle或Maven命令构建原生镜像。
        b.构建命令
            ---
            # Gradle构建
            ./gradlew nativeCompile

            # Maven构建
            ./mvnw package -Dpackaging=native-image

            # 构建输出
            # build/native/nativeCompile/micronaut-app

            # 运行原生镜像
            ./build/native/nativeCompile/micronaut-app

            # 查看启动时间和内存占用
            time ./build/native/nativeCompile/micronaut-app

            # 输出示例
            # Startup completed in 23ms
            # Memory: 15MB
            ---
    b.Docker构建
        a.功能说明
            使用Docker多阶段构建创建原生镜像容器。
        b.Dockerfile示例
            ---
            # Dockerfile
            FROM ghcr.io/graalvm/graalvm-ce:ol8-java17-22.3.0 AS builder

            WORKDIR /app
            COPY . .

            # 安装Native Image
            RUN gu install native-image

            # 构建原生镜像
            RUN ./gradlew nativeCompile

            # 运行阶段
            FROM oraclelinux:8-slim

            WORKDIR /app

            # 复制原生镜像
            COPY --from=builder /app/build/native/nativeCompile/micronaut-app .

            # 暴露端口
            EXPOSE 8080

            # 运行应用
            ENTRYPOINT ["./micronaut-app"]

            # 构建Docker镜像
            docker build -t micronaut-native:latest .

            # 运行容器
            docker run -p 8080:8080 micronaut-native:latest

            # 查看容器资源占用
            docker stats
            ---
    c.CI/CD集成
        a.功能说明
            在CI/CD流水线中自动构建原生镜像。
        b.GitHub Actions示例
            ---
            # .github/workflows/native-image.yml
            name: Build Native Image

            on:
              push:
                branches: [ main ]

            jobs:
              build:
                runs-on: ubuntu-latest

                steps:
                  - uses: actions/checkout@v3

                  - name: Setup GraalVM
                    uses: graalvm/setup-graalvm@v1
                    with:
                      version: '22.3.0'
                      java-version: '17'
                      components: 'native-image'

                  - name: Build Native Image
                    run: ./gradlew nativeCompile

                  - name: Test Native Image
                    run: |
                      ./build/native/nativeCompile/micronaut-app &
                      sleep 5
                      curl http://localhost:8080/health

                  - name: Upload Artifact
                    uses: actions/upload-artifact@v3
                    with:
                      name: native-image
                      path: build/native/nativeCompile/micronaut-app
            ---

04.反射配置
    a.自动配置
        a.功能说明
            Micronaut自动生成反射配置,无需手动配置大部分反射使用。
        b.配置示例
            ---
            // Micronaut自动处理的反射
            // - @Controller、@Service等注解的类
            // - @ConfigurationProperties配置类
            // - @Introspected注解的类

            // 需要手动配置的反射
            // - 第三方库的反射使用
            // - 动态类加载
            // - JNI调用

            // src/main/resources/META-INF/native-image/reflect-config.json
            [
              {
                "name": "com.example.DynamicClass",
                "allDeclaredConstructors": true,
                "allPublicConstructors": true,
                "allDeclaredMethods": true,
                "allPublicMethods": true,
                "allDeclaredFields": true,
                "allPublicFields": true
              }
            ]
            ---
    b.手动配置
        a.功能说明
            为第三方库或动态加载的类添加反射配置。
        b.代码示例
            ---
            import io.micronaut.core.annotation.Introspected;
            import io.micronaut.core.annotation.ReflectiveAccess;

            // 使用@Introspected注解
            @Introspected
            public class User {
                private Long id;
                private String username;
                private String email;

                // Getters and Setters
            }

            // 使用@ReflectiveAccess注解
            @ReflectiveAccess
            public class DynamicService {

                public void dynamicMethod() {
                    // 动态调用的方法
                }
            }

            // 编程式注册反射
            import io.micronaut.context.annotation.Factory;
            import io.micronaut.core.annotation.TypeHint;
            import jakarta.inject.Singleton;

            @Factory
            public class ReflectionConfiguration {

                @Singleton
                @TypeHint(
                    value = {ThirdPartyClass.class},
                    accessType = {TypeHint.AccessType.ALL_DECLARED_CONSTRUCTORS,
                                  TypeHint.AccessType.ALL_DECLARED_METHODS}
                )
                public ThirdPartyClass thirdPartyBean() {
                    return new ThirdPartyClass();
                }
            }
            ---

05.性能优化
    a.构建优化
        a.功能说明
            配置Native Image构建参数,优化镜像大小和性能。
        b.配置示例
            ---
            // build.gradle
            graalvmNative {
                binaries {
                    main {
                        buildArgs.addAll([
                            // 优化级别
                            "-O3",
                            // 启用G1 GC
                            "--gc=G1",
                            // 静态链接
                            "--static",
                            // 压缩
                            "-H:+CompressedReferences",
                            // 移除未使用代码
                            "-H:+RemoveUnusedSymbols",
                            // 优化字符串
                            "-H:+OptimizeStringConcat",
                            // 内存配置
                            "-J-Xmx8g"
                        ])
                    }
                }
            }
            ---
    b.运行时优化
        a.功能说明
            配置原生镜像的运行时参数,优化内存和性能。
        b.配置示例
            ---
            # 运行时参数
            ./micronaut-app \
              -Xmx128m \
              -Xms128m \
              -XX:MaxDirectMemorySize=64m

            # 环境变量配置
            export MICRONAUT_ENVIRONMENTS=prod
            export JAVA_OPTS="-Xmx128m -Xms128m"

            # Docker运行配置
            docker run \
              -p 8080:8080 \
              -m 256m \
              --cpus 0.5 \
              -e MICRONAUT_ENVIRONMENTS=prod \
              micronaut-native:latest
            ---
    c.监控和诊断
        a.功能说明
            启用原生镜像的监控和诊断功能。
        b.配置示例
            ---
            // build.gradle
            graalvmNative {
                binaries {
                    main {
                        buildArgs.addAll([
                            // 启用监控
                            "--enable-monitoring=heapdump,jfr,jvmstat",
                            // 启用诊断
                            "-H:+AllowVMInspection",
                            // 生成调试信息
                            "-H:+SourceLevelDebug",
                            // 生成性能报告
                            "-H:+DashboardAll",
                            "-H:DashboardDump=dashboard.bgv"
                        ])
                    }
                }
            }

            # 运行时启用JFR
            ./micronaut-app -XX:StartFlightRecording=filename=recording.jfr

            # 生成堆转储
            kill -SIGUSR1 <pid>
            ---

06.常见问题
    a.类初始化问题
        a.功能说明
            配置类的初始化时机,解决构建时初始化错误。
        b.配置示例
            ---
            // src/main/resources/META-INF/native-image/native-image.properties
            Args = --initialize-at-build-time=com.example.StaticClass \
                   --initialize-at-run-time=com.example.DynamicClass

            // 或在build.gradle中配置
            graalvmNative {
                binaries {
                    main {
                        buildArgs.add("--initialize-at-build-time=com.example.StaticClass")
                        buildArgs.add("--initialize-at-run-time=com.example.DynamicClass")
                    }
                }
            }
            ---
    b.资源文件访问
        a.功能说明
            配置资源文件的访问,确保原生镜像能正确加载资源。
        b.配置示例
            ---
            // src/main/resources/META-INF/native-image/resource-config.json
            {
              "resources": {
                "includes": [
                  {"pattern": "application.yml"},
                  {"pattern": "application-*.yml"},
                  {"pattern": "logback.xml"},
                  {"pattern": "META-INF/.*"},
                  {"pattern": "templates/.*\\.html"}
                ]
              }
            }

            // 或使用@ResourceHint注解
            import io.micronaut.core.annotation.ResourceHint;

            @ResourceHint(
                patterns = {
                    "application.yml",
                    "templates/*.html"
                }
            )
            public class Application {
                public static void main(String[] args) {
                    Micronaut.run(Application.class, args);
                }
            }
            ---
    c.第三方库兼容性
        a.功能说明
            处理第三方库的GraalVM兼容性问题。
        b.解决方案
            ---
            # 检查库的GraalVM兼���性
            # https://www.graalvm.org/native-image/libraries-and-frameworks/

            # 常见不兼容库的替代方案
            # - CGLIB → Micronaut AOP
            # - Javassist → ByteBuddy
            # - ASM动态生成 → 编译时生成

            # 添加第三方库的配置
            // build.gradle
            dependencies {
                // 使用GraalVM兼容的库版本
                implementation("org.postgresql:postgresql:42.5.0")

                // 添加GraalVM元数据
                implementation("org.graalvm.buildtools:graalvm-reachability-metadata:0.9.28")
            }

            # 使用Tracing Agent生成配置
            java -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image \
                 -jar build/libs/app.jar

            # 运行测试生成配置
            ./gradlew test -Pagent
            ---

7 实战应用

7.1 项目创建与配置

01.项目创建
    a.使用Micronaut Launch
        a.功能说明
            Micronaut Launch是官方的项目生成器,提供Web界面和CLI工具,快速创建项目脚手架。
        b.使用步骤
            ---
            # Web界面创建
            # 访问 https://micronaut.io/launch/
            # 1. 选择应用类型:Application, CLI, Function等
            # 2. 选择Java版本:17, 21
            # 3. 选择构建工具:Gradle或Maven
            # 4. 选择语言:Java, Kotlin, Groovy
            # 5. 添加特性:Data JPA, Security JWT, Kafka等
            # 6. 下载项目压缩包

            # CLI工具创建
            # 安装Micronaut CLI
            sdk install micronaut

            # 创建项目
            mn create-app com.example.demo \
              --features=data-jpa,security-jwt,kafka \
              --build=gradle \
              --lang=java \
              --jdk=17

            # 创建微服务项目
            mn create-app com.example.order-service \
              --features=discovery-consul,tracing-zipkin,graalvm \
              --build=gradle

            # 创建函数项目
            mn create-function com.example.lambda \
              --features=aws-lambda \
              --build=gradle
            ---
    b.项目结构
        a.功能说明
            Micronaut项目遵循标准的Maven/Gradle项目结构,���码组织清晰。
        b.目录结构
            ---
            order-service/
            ├── src/
            │   ├── main/
            │   │   ├── java/
            │   │   │   └── com/example/
            │   │   │       ├── Application.java          # 应用入口
            │   │   │       ├── controller/               # 控制器
            │   │   │       │   └── OrderController.java
            │   │   │       ├── service/                  # 业务逻辑
            │   │   │       │   └── OrderService.java
            │   │   │       ├── repository/               # 数据访问
            │   │   │       │   └── OrderRepository.java
            │   │   │       ├── domain/                   # 领域模型
            │   │   │       │   └── Order.java
            │   │   │       └── config/                   # 配置类
            │   │   │           └── DatabaseConfig.java
            │   │   └── resources/
            │   │       ├── application.yml               # 主配置文件
            │   │       ├── application-dev.yml           # 开发环境配置
            │   │       ├── application-prod.yml          # 生产环境配置
            │   │       └── logback.xml                   # 日志配置
            │   └── test/
            │       ├── java/
            │       │   └── com/example/
            │       │       └── OrderControllerTest.java
            │       └── resources/
            │           └── application-test.yml
            ├── build.gradle                              # Gradle构建文件
            ├── settings.gradle
            ├── gradle.properties
            └── Dockerfile                                # Docker配置
            ---

02.基础配置
    a.应用配置
        a.功能说明
            配置应用的基本信息,包括名称、端口、环境等。
        b.配置示例
            ---
            // application.yml
            micronaut:
              application:
                name: order-service
              server:
                port: 8080
                context-path: /api
              # 环境配置
              environments:
                default: dev

            # 服务器配置
            netty:
              default:
                allocator:
                  max-order: 3

            # 日志配置
            logger:
              levels:
                com.example: DEBUG
                io.micronaut: INFO
            ---
    b.数据源配置
        a.功能说明
            配置数据库连接,支持多数据源和连接池。
        b.配置示例
            ---
            // application.yml
            datasources:
              default:
                url: jdbc:mysql://localhost:3306/orders?serverTimezone=UTC
                driverClassName: com.mysql.cj.jdbc.Driver
                username: root
                password: ${DB_PASSWORD:secret}
                dialect: MYSQL
                # 连接池配置
                maximum-pool-size: 10
                minimum-idle: 2
                connection-timeout: 30000
                idle-timeout: 600000
                max-lifetime: 1800000

            # JPA配置
            jpa:
              default:
                properties:
                  hibernate:
                    hbm2ddl:
                      auto: update
                    show_sql: true
                    format_sql: true

            # 使用配置
            import io.micronaut.data.annotation.Repository;
            import io.micronaut.data.jpa.repository.JpaRepository;

            @Repository
            public interface OrderRepository extends JpaRepository<Order, Long> {
                List<Order> findByStatus(String status);
            }
            ---
    c.环境配置
        a.功能说明
            为不同环境配置不同的参数,如开发、测试、生产环境。
        b.配置示例
            ---
            // application-dev.yml
            micronaut:
              server:
                port: 8080

            datasources:
              default:
                url: jdbc:mysql://localhost:3306/orders_dev

            logger:
              levels:
                com.example: DEBUG

            // application-prod.yml
            micronaut:
              server:
                port: 80

            datasources:
              default:
                url: jdbc:mysql://prod-db:3306/orders
                maximum-pool-size: 50

            logger:
              levels:
                com.example: WARN

            # 启动时指定环境
            java -jar app.jar -Dmicronaut.environments=prod

            # 或使用环境变量
            export MICRONAUT_ENVIRONMENTS=prod
            java -jar app.jar
            ---

03.依赖管理
    a.核心依赖
        a.功能说明
            添加Micronaut核心依赖和常用模块。
        b.配置示例
            ---
            // build.gradle
            plugins {
                id("io.micronaut.application") version "4.0.0"
            }

            version = "1.0.0"
            group = "com.example"

            repositories {
                mavenCentral()
            }

            dependencies {
                // Micronaut核心
                implementation("io.micronaut:micronaut-runtime")
                implementation("io.micronaut:micronaut-http-server-netty")
                implementation("io.micronaut:micronaut-validation")

                // 数据访问
                implementation("io.micronaut.data:micronaut-data-jpa")
                implementation("io.micronaut.sql:micronaut-jdbc-hikari")
                runtimeOnly("mysql:mysql-connector-java")

                // 安全
                implementation("io.micronaut.security:micronaut-security-jwt")

                // 服务发现
                implementation("io.micronaut.discovery:micronaut-discovery-client")

                // 日志
                runtimeOnly("ch.qos.logback:logback-classic")

                // 测试
                testImplementation("io.micronaut.test:micronaut-test-junit5")
                testImplementation("org.junit.jupiter:junit-jupiter-api")
                testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
            }

            application {
                mainClass.set("com.example.Application")
            }

            java {
                sourceCompatibility = JavaVersion.VERSION_17
                targetCompatibility = JavaVersion.VERSION_17
            }
            ---
    b.版本管理
        a.功能说明
            使用BOM统一管理依赖版本,避免版本冲突。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                // 使用Micronaut BOM
                implementation(platform("io.micronaut.platform:micronaut-platform:4.0.0"))

                // 无需指定版本
                implementation("io.micronaut:micronaut-runtime")
                implementation("io.micronaut.data:micronaut-data-jpa")
                implementation("io.micronaut.security:micronaut-security-jwt")
            }

            // gradle.properties
            micronautVersion=4.0.0
            ---

04.应用入口
    a.主类定义
        a.功能说明
            定义应用的主类和启动方法。
        b.代码示例
            ---
            package com.example;

            import io.micronaut.runtime.Micronaut;

            public class Application {

                public static void main(String[] args) {
                    Micronaut.run(Application.class, args);
                }
            }

            // 自定义启动配置
            import io.micronaut.context.ApplicationContext;
            import io.micronaut.runtime.Micronaut;

            public class Application {

                public static void main(String[] args) {
                    Micronaut.build(args)
                        .mainClass(Application.class)
                        .banner(false)  // 禁用启动横幅
                        .start();
                }
            }
            ---
    b.启动监听器
        a.功能说明
            监听应用启动和关闭事件,执行初始化和清理逻辑。
        b.代码示例
            ---
            import io.micronaut.context.event.ApplicationEventListener;
            import io.micronaut.context.event.StartupEvent;
            import io.micronaut.context.event.ShutdownEvent;
            import jakarta.inject.Singleton;
            import org.slf4j.Logger;
            import org.slf4j.LoggerFactory;

            @Singleton
            public class ApplicationStartupListener implements ApplicationEventListener<StartupEvent> {

                private static final Logger LOG = LoggerFactory.getLogger(ApplicationStartupListener.class);

                @Override
                public void onApplicationEvent(StartupEvent event) {
                    LOG.info("Application started successfully");
                    LOG.info("Server running on port: {}", event.getSource().getEnvironment().getProperty("micronaut.server.port", Integer.class).orElse(8080));

                    // 执行初始化逻辑
                    initializeCache();
                    loadConfiguration();
                }

                private void initializeCache() {
                    LOG.info("Initializing cache...");
                }

                private void loadConfiguration() {
                    LOG.info("Loading configuration...");
                }
            }

            @Singleton
            public class ApplicationShutdownListener implements ApplicationEventListener<ShutdownEvent> {

                private static final Logger LOG = LoggerFactory.getLogger(ApplicationShutdownListener.class);

                @Override
                public void onApplicationEvent(ShutdownEvent event) {
                    LOG.info("Application shutting down...");

                    // 执行清理逻辑
                    closeConnections();
                    flushCache();
                }

                private void closeConnections() {
                    LOG.info("Closing database connections...");
                }

                private void flushCache() {
                    LOG.info("Flushing cache...");
                }
            }
            ---

05.开发工具
    a.热重载
        a.功能说明
            配置自动重载,提升开发效率。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                developmentOnly("io.micronaut:micronaut-runtime")
            }

            // 启用自动重载
            micronaut {
                runtime("netty")
                processing {
                    incremental(true)
                    annotations("com.example.*")
                }
            }

            # 运行开发模式
            ./gradlew run --continuous

            # 或使用IDE插件
            # IntelliJ IDEA: Micronaut插件
            # VS Code: Micronaut扩展
            ---
    b.API文档
        a.功能说明
            集成OpenAPI/Swagger,自动生成API文档。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.openapi:micronaut-openapi")
                annotationProcessor("io.micronaut.openapi:micronaut-openapi")
            }

            // application.yml
            micronaut:
              router:
                static-resources:
                  swagger:
                    paths: classpath:META-INF/swagger
                    mapping: /swagger/**
                  swagger-ui:
                    paths: classpath:META-INF/swagger/views/swagger-ui
                    mapping: /swagger-ui/**

            # 访问Swagger UI
            # http://localhost:8080/swagger-ui/

            // 在Controller中添加文档注解
            import io.swagger.v3.oas.annotations.Operation;
            import io.swagger.v3.oas.annotations.tags.Tag;

            @Controller("/orders")
            @Tag(name = "Order Management")
            public class OrderController {

                @Get("/{id}")
                @Operation(summary = "Get order by ID", description = "Returns a single order")
                public Order getOrder(Long id) {
                    return orderService.findById(id);
                }
            }
            ---

7.2 RESTful API开发

01.控制器开发
    a.基础控制器
        a.功能说明
            使用@Controller注解定义RESTful API端点,处理HTTP请求。
        b.代码示例
            ---
            import io.micronaut.http.annotation.*;
            import io.micronaut.http.HttpResponse;
            import jakarta.inject.Inject;

            @Controller("/api/orders")
            public class OrderController {

                @Inject
                private OrderService orderService;

                @Get
                public List<Order> listOrders() {
                    return orderService.findAll();
                }

                @Get("/{id}")
                public Order getOrder(Long id) {
                    return orderService.findById(id)
                        .orElseThrow(() -> new NotFoundException("Order not found"));
                }

                @Post
                public HttpResponse<Order> createOrder(@Body Order order) {
                    Order created = orderService.create(order);
                    return HttpResponse.created(created);
                }

                @Put("/{id}")
                public Order updateOrder(Long id, @Body Order order) {
                    return orderService.update(id, order);
                }

                @Delete("/{id}")
                public HttpResponse<?> deleteOrder(Long id) {
                    orderService.delete(id);
                    return HttpResponse.noContent();
                }
            }
            ---
    b.参数绑定
        a.功能说明
            自动绑定路径参数、查询参数、请求体等。
        b.代码示例
            ---
            @Controller("/api/products")
            public class ProductController {

                // 路径参数
                @Get("/{id}")
                public Product getProduct(@PathVariable Long id) {
                    return productService.findById(id);
                }

                // 查询参数
                @Get("/search")
                public List<Product> searchProducts(
                    @QueryValue String keyword,
                    @QueryValue(defaultValue = "0") int page,
                    @QueryValue(defaultValue = "10") int size
                ) {
                    return productService.search(keyword, page, size);
                }

                // 请求头
                @Get("/user-products")
                public List<Product> getUserProducts(
                    @Header("Authorization") String token
                ) {
                    String userId = extractUserId(token);
                    return productService.findByUserId(userId);
                }

                // Cookie
                @Get("/preferences")
                public Map<String, Object> getPreferences(
                    @CookieValue("session-id") String sessionId
                ) {
                    return preferenceService.getBySession(sessionId);
                }
            }
            ---

02.数据验证
    a.Bean Validation
        a.功能说明
            使用JSR-380注解验证请求数据。
        b.代码示例
            ---
            import jakarta.validation.constraints.*;

            public class CreateOrderRequest {

                @NotBlank(message = "Product name is required")
                @Size(min = 3, max = 100)
                private String productName;

                @NotNull
                @Min(value = 1, message = "Quantity must be at least 1")
                @Max(value = 1000)
                private Integer quantity;

                @NotNull
                @DecimalMin(value = "0.01")
                private BigDecimal price;

                @Email(message = "Invalid email format")
                private String customerEmail;

                @Pattern(regexp = "^\\+?[1-9]\\d{1,14}$", message = "Invalid phone number")
                private String phoneNumber;

                // Getters and Setters
            }

            @Controller("/api/orders")
            public class OrderController {

                @Post
                public HttpResponse<Order> createOrder(@Valid @Body CreateOrderRequest request) {
                    Order order = orderService.create(request);
                    return HttpResponse.created(order);
                }
            }
            ---
    b.自定义验证器
        a.功能说明
            实现自定义验证逻辑。
        b.代码示例
            ---
            import jakarta.validation.Constraint;
            import jakarta.validation.ConstraintValidator;
            import jakarta.validation.ConstraintValidatorContext;
            import jakarta.validation.Payload;
            import java.lang.annotation.*;

            @Target({ElementType.FIELD, ElementType.PARAMETER})
            @Retention(RetentionPolicy.RUNTIME)
            @Constraint(validatedBy = OrderStatusValidator.class)
            public @interface ValidOrderStatus {
                String message() default "Invalid order status";
                Class<?>[] groups() default {};
                Class<? extends Payload>[] payload() default {};
            }

            public class OrderStatusValidator implements ConstraintValidator<ValidOrderStatus, String> {

                private static final Set<String> VALID_STATUSES = Set.of(
                    "PENDING", "CONFIRMED", "SHIPPED", "DELIVERED", "CANCELLED"
                );

                @Override
                public boolean isValid(String value, ConstraintValidatorContext context) {
                    return value != null && VALID_STATUSES.contains(value.toUpperCase());
                }
            }

            // 使用自定义验证器
            public class UpdateOrderRequest {

                @ValidOrderStatus
                private String status;

                // Getters and Setters
            }
            ---

03.异常处理
    a.全局异常处理
        a.功能说明
            使用@Error注解处理全局异常。
        b.代码示例
            ---
            import io.micronaut.http.HttpRequest;
            import io.micronaut.http.HttpResponse;
            import io.micronaut.http.annotation.Error;
            import io.micronaut.http.annotation.Controller;
            import io.micronaut.http.hateoas.JsonError;

            @Controller
            public class GlobalExceptionHandler {

                @Error(global = true, exception = NotFoundException.class)
                public HttpResponse<JsonError> handleNotFound(HttpRequest request, NotFoundException e) {
                    JsonError error = new JsonError(e.getMessage())
                        .link("self", request.getUri());

                    return HttpResponse.notFound(error);
                }

                @Error(global = true, exception = ValidationException.class)
                public HttpResponse<JsonError> handleValidation(HttpRequest request, ValidationException e) {
                    JsonError error = new JsonError("Validation failed: " + e.getMessage());
                    return HttpResponse.badRequest(error);
                }

                @Error(global = true)
                public HttpResponse<JsonError> handleGeneric(HttpRequest request, Throwable e) {
                    JsonError error = new JsonError("Internal server error");
                    return HttpResponse.serverError(error);
                }
            }
            ---
    b.自定义异常
        a.功能说明
            定义业务异常类型。
        b.代码示例
            ---
            public class NotFoundException extends RuntimeException {
                public NotFoundException(String message) {
                    super(message);
                }
            }

            public class BusinessException extends RuntimeException {
                private final String errorCode;

                public BusinessException(String errorCode, String message) {
                    super(message);
                    this.errorCode = errorCode;
                }

                public String getErrorCode() {
                    return errorCode;
                }
            }

            // 异常处理器
            @Error(exception = BusinessException.class)
            public HttpResponse<Map<String, Object>> handleBusinessException(
                HttpRequest request,
                BusinessException e
            ) {
                Map<String, Object> error = Map.of(
                    "code", e.getErrorCode(),
                    "message", e.getMessage(),
                    "path", request.getPath()
                );

                return HttpResponse.badRequest(error);
            }
            ---

04.响应处理
    a.JSON响应
        a.功能说明
            自动序列化对象为JSON响应。
        b.代码示例
            ---
            @Controller("/api/users")
            public class UserController {

                @Get("/{id}")
                public User getUser(Long id) {
                    // 自动序列化为JSON
                    return userService.findById(id);
                }

                @Get
                public HttpResponse<List<User>> listUsers() {
                    List<User> users = userService.findAll();
                    return HttpResponse.ok(users)
                        .header("X-Total-Count", String.valueOf(users.size()));
                }

                // 自定义响应状态
                @Post
                public HttpResponse<User> createUser(@Body User user) {
                    User created = userService.create(user);
                    return HttpResponse.created(created)
                        .header("Location", "/api/users/" + created.getId());
                }
            }
            ---
    b.分页响应
        a.功能说明
            实现分页查询和响应。
        b.代码示例
            ---
            import io.micronaut.data.model.Page;
            import io.micronaut.data.model.Pageable;

            @Controller("/api/orders")
            public class OrderController {

                @Get
                public HttpResponse<Page<Order>> listOrders(
                    @QueryValue(defaultValue = "0") int page,
                    @QueryValue(defaultValue = "20") int size,
                    @QueryValue(defaultValue = "id,desc") String sort
                ) {
                    Pageable pageable = Pageable.from(page, size);
                    Page<Order> orders = orderService.findAll(pageable);

                    return HttpResponse.ok(orders)
                        .header("X-Total-Count", String.valueOf(orders.getTotalSize()))
                        .header("X-Total-Pages", String.valueOf(orders.getTotalPages()));
                }
            }

            // 自定义分页响应
            public class PageResponse<T> {
                private List<T> content;
                private int page;
                private int size;
                private long total;
                private int totalPages;

                // Constructor, Getters and Setters
            }

            @Get("/custom-page")
            public PageResponse<Order> customPage(Pageable pageable) {
                Page<Order> page = orderService.findAll(pageable);

                return new PageResponse<>(
                    page.getContent(),
                    page.getPageNumber(),
                    page.getSize(),
                    page.getTotalSize(),
                    page.getTotalPages()
                );
            }
            ---

05.API版本控制
    a.URL版本控制
        a.功能说明
            通过URL路径实现API版本控制。
        b.代码示例
            ---
            @Controller("/api/v1/orders")
            public class OrderControllerV1 {

                @Get("/{id}")
                public OrderV1 getOrder(Long id) {
                    return orderService.findByIdV1(id);
                }
            }

            @Controller("/api/v2/orders")
            public class OrderControllerV2 {

                @Get("/{id}")
                public OrderV2 getOrder(Long id) {
                    return orderService.findByIdV2(id);
                }
            }
            ---
    b.Header版本控制
        a.功能说明
            通过请求头实现API版本控制。
        b.代码示例
            ---
            @Controller("/api/orders")
            public class OrderController {

                @Get(value = "/{id}", produces = "application/vnd.api.v1+json")
                public OrderV1 getOrderV1(Long id) {
                    return orderService.findByIdV1(id);
                }

                @Get(value = "/{id}", produces = "application/vnd.api.v2+json")
                public OrderV2 getOrderV2(Long id) {
                    return orderService.findByIdV2(id);
                }
            }

            // 客户端请求
            // GET /api/orders/1
            // Accept: application/vnd.api.v1+json
            ---

7.3 微服务架构实践

01.服务拆分
    a.拆分原则
        a.功能说明
            按照业务领域和职责边界拆分微服务,遵循单一职责原则。
        b.拆分示例
            ---
            # 电商系统微服务拆分
            order-service/          # 订单服务
              - 订单创建
              - 订单查询
              - 订单状态管理

            inventory-service/      # 库存服务
              - 库存查询
              - 库存扣减
              - 库存补充

            payment-service/        # 支付服务
              - 支付处理
              - 退款处理
              - 支付查询

            user-service/           # 用户服务
              - 用户注册
              - 用户认证
              - 用户信息管理

            notification-service/   # 通知服务
              - 邮件通知
              - 短信通知
              - 推送通知
            ---
    b.服务通信
        a.同步通信
            a.功能说明
                使用HTTP客户端进行服务间同步调用。
            b.代码示例
                ---
                // 订单服务调用库存服务
                import io.micronaut.http.client.annotation.Client;
                import io.micronaut.http.annotation.Get;
                import io.micronaut.http.annotation.Post;

                @Client("inventory-service")
                public interface InventoryClient {

                    @Get("/inventory/{productId}")
                    Inventory getInventory(Long productId);

                    @Post("/inventory/reserve")
                    boolean reserveInventory(@Body ReserveRequest request);
                }

                @Service
                public class OrderService {

                    @Inject
                    private InventoryClient inventoryClient;

                    @Inject
                    private PaymentClient paymentClient;

                    public Order createOrder(CreateOrderRequest request) {
                        // 1. 检查库存
                        Inventory inventory = inventoryClient.getInventory(request.getProductId());
                        if (inventory.getQuantity() < request.getQuantity()) {
                            throw new BusinessException("INSUFFICIENT_INVENTORY", "库存不足");
                        }

                        // 2. 预留库存
                        boolean reserved = inventoryClient.reserveInventory(
                            new ReserveRequest(request.getProductId(), request.getQuantity())
                        );

                        if (!reserved) {
                            throw new BusinessException("RESERVE_FAILED", "库存预留失败");
                        }

                        // 3. 创建订单
                        Order order = new Order();
                        order.setProductId(request.getProductId());
                        order.setQuantity(request.getQuantity());
                        order.setStatus("PENDING");

                        return orderRepository.save(order);
                    }
                }
                ---
        b.异步通信
            a.功能说明
                使用消息队列实现服务间异步通信。
            b.代码示例
                ---
                // 订单服务发布订单创建事件
                import io.micronaut.configuration.kafka.annotation.KafkaClient;
                import io.micronaut.configuration.kafka.annotation.Topic;

                @KafkaClient
                public interface OrderEventProducer {

                    @Topic("order-events")
                    void publishOrderCreated(OrderCreatedEvent event);
                }

                @Service
                public class OrderService {

                    @Inject
                    private OrderEventProducer eventProducer;

                    public Order createOrder(CreateOrderRequest request) {
                        Order order = orderRepository.save(new Order(request));

                        // 发布事件
                        OrderCreatedEvent event = new OrderCreatedEvent(
                            order.getId(),
                            order.getUserId(),
                            order.getTotalAmount()
                        );
                        eventProducer.publishOrderCreated(event);

                        return order;
                    }
                }

                // 通知服务消费订单事件
                import io.micronaut.configuration.kafka.annotation.KafkaListener;
                import io.micronaut.configuration.kafka.annotation.Topic;

                @KafkaListener(groupId = "notification-service")
                public class OrderEventConsumer {

                    @Inject
                    private NotificationService notificationService;

                    @Topic("order-events")
                    public void onOrderCreated(OrderCreatedEvent event) {
                        // 发送订单确认邮件
                        notificationService.sendOrderConfirmation(
                            event.getUserId(),
                            event.getOrderId()
                        );
                    }
                }
                ---

02.服务编排
    a.Saga模式
        a.功能说明
            使用Saga模式管理分布式事务,确保数据一致性。
        b.代码示例
            ---
            @Service
            public class OrderSagaOrchestrator {

                @Inject
                private InventoryClient inventoryClient;

                @Inject
                private PaymentClient paymentClient;

                @Inject
                private OrderRepository orderRepository;

                public Order executeOrderSaga(CreateOrderRequest request) {
                    Order order = null;
                    boolean inventoryReserved = false;
                    boolean paymentProcessed = false;

                    try {
                        // Step 1: 创建订单
                        order = new Order(request);
                        order.setStatus("PENDING");
                        order = orderRepository.save(order);

                        // Step 2: 预留库存
                        inventoryReserved = inventoryClient.reserveInventory(
                            new ReserveRequest(order.getProductId(), order.getQuantity())
                        );

                        if (!inventoryReserved) {
                            throw new SagaException("库存预留失败");
                        }

                        // Step 3: 处理支付
                        PaymentResult paymentResult = paymentClient.processPayment(
                            new PaymentRequest(order.getId(), order.getTotalAmount())
                        );

                        if (!"SUCCESS".equals(paymentResult.getStatus())) {
                            throw new SagaException("支付失败");
                        }

                        paymentProcessed = true;

                        // Step 4: 确认订单
                        order.setStatus("CONFIRMED");
                        order = orderRepository.update(order);

                        return order;

                    } catch (Exception e) {
                        // 补偿操作
                        if (paymentProcessed) {
                            paymentClient.refund(order.getId());
                        }

                        if (inventoryReserved) {
                            inventoryClient.releaseInventory(
                                new ReleaseRequest(order.getProductId(), order.getQuantity())
                            );
                        }

                        if (order != null) {
                            order.setStatus("CANCELLED");
                            orderRepository.update(order);
                        }

                        throw new BusinessException("ORDER_FAILED", "订单创建失败: " + e.getMessage());
                    }
                }
            }
            ---
    b.事件驱动编排
        a.功能说明
            使用事件驱动方式编排服务流程。
        b.代码示例
            ---
            // 订单服务
            @Service
            public class OrderService {

                @Inject
                private OrderEventProducer eventProducer;

                public Order createOrder(CreateOrderRequest request) {
                    Order order = orderRepository.save(new Order(request));

                    // 发布订单创建事件
                    eventProducer.publishOrderCreated(new OrderCreatedEvent(order));

                    return order;
                }

                @KafkaListener(groupId = "order-service")
                @Topic("payment-events")
                public void onPaymentCompleted(PaymentCompletedEvent event) {
                    Order order = orderRepository.findById(event.getOrderId()).orElseThrow();
                    order.setStatus("PAID");
                    orderRepository.update(order);

                    // 发布订单已支付事件
                    eventProducer.publishOrderPaid(new OrderPaidEvent(order));
                }
            }

            // 库存服务
            @KafkaListener(groupId = "inventory-service")
            public class InventoryEventConsumer {

                @Topic("order-events")
                public void onOrderCreated(OrderCreatedEvent event) {
                    // 预留库存
                    boolean reserved = inventoryService.reserve(
                        event.getProductId(),
                        event.getQuantity()
                    );

                    if (reserved) {
                        eventProducer.publishInventoryReserved(
                            new InventoryReservedEvent(event.getOrderId())
                        );
                    } else {
                        eventProducer.publishInventoryReserveFailed(
                            new InventoryReserveFailedEvent(event.getOrderId())
                        );
                    }
                }

                @Topic("order-events")
                public void onOrderPaid(OrderPaidEvent event) {
                    // 扣减库存
                    inventoryService.deduct(event.getProductId(), event.getQuantity());
                }
            }
            ---

03.服务治理
    a.熔断器
        a.功能说明
            使用Resilience4j实现熔断器模式,防止故障扩散。
        b.代码示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.resilience4j:micronaut-resilience4j")
            }

            // application.yml
            resilience4j:
              circuitbreaker:
                instances:
                  inventory-service:
                    failure-rate-threshold: 50
                    wait-duration-in-open-state: 10s
                    sliding-window-size: 10

            // 使用熔断器
            import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;

            @Service
            public class OrderService {

                @Inject
                private InventoryClient inventoryClient;

                @CircuitBreaker(name = "inventory-service", fallbackMethod = "getInventoryFallback")
                public Inventory getInventory(Long productId) {
                    return inventoryClient.getInventory(productId);
                }

                public Inventory getInventoryFallback(Long productId, Exception e) {
                    // 降级逻辑:返回默认库存信息
                    return new Inventory(productId, 0, "服务暂时不可用");
                }
            }
            ---
    b.限流
        a.功能说明
            实现API限流,保护服务不被过载。
        b.代码示例
            ---
            // application.yml
            resilience4j:
              ratelimiter:
                instances:
                  order-api:
                    limit-for-period: 100
                    limit-refresh-period: 1s
                    timeout-duration: 0s

            // 使用限流器
            import io.github.resilience4j.ratelimiter.annotation.RateLimiter;

            @Controller("/api/orders")
            public class OrderController {

                @Post
                @RateLimiter(name = "order-api")
                public HttpResponse<Order> createOrder(@Body CreateOrderRequest request) {
                    Order order = orderService.createOrder(request);
                    return HttpResponse.created(order);
                }
            }
            ---

04.配置管理
    a.集中配置
        a.功能说明
            使用配置中心管理所有微服务的配置。
        b.配置示例
            ---
            // bootstrap.yml
            micronaut:
              application:
                name: order-service
              config-client:
                enabled: true

            consul:
              client:
                config:
                  enabled: true
                  format: YAML
                defaultZone: localhost:8500

            # Consul配置结构
            /config/application/data          # 所有服务共享
            /config/order-service/data        # 订单服务专属
            /config/order-service,prod/data   # 生产环境配置
            ---
    b.配置刷新
        a.功能说明
            支持配置动态刷新,无需重启服务。
        b.代码示例
            ---
            import io.micronaut.runtime.context.scope.Refreshable;
            import io.micronaut.context.annotation.ConfigurationProperties;

            @Refreshable
            @ConfigurationProperties("order")
            public class OrderConfig {

                private int maxOrdersPerDay;
                private BigDecimal minOrderAmount;

                // Getters and Setters
            }

            @Service
            public class OrderService {

                @Inject
                private OrderConfig orderConfig;

                public void validateOrder(Order order) {
                    if (order.getTotalAmount().compareTo(orderConfig.getMinOrderAmount()) < 0) {
                        throw new ValidationException("订单金额低于最小限制");
                    }
                }
            }
            ---

05.监控和追踪
    a.分布式追踪
        a.功能说明
            使用Zipkin追踪跨服务调用链路。
        b.配置示例
            ---
            // application.yml
            tracing:
              zipkin:
                enabled: true
                url: http://zipkin:9411
                sampler:
                  probability: 0.1

            # 自动追踪HTTP调用
            @Client("inventory-service")
            public interface InventoryClient {
                @Get("/inventory/{id}")
                Inventory getInventory(Long id);  // 自动追踪
            }
            ---
    b.健康检查
        a.功能说明
            实现健康检查端点,监控服务状态。
        b.代码示例
            ---
            // application.yml
            endpoints:
              health:
                enabled: true
                sensitive: false

            // 自定义健康检查
            import io.micronaut.management.health.indicator.HealthIndicator;
            import io.micronaut.management.health.indicator.HealthResult;
            import org.reactivestreams.Publisher;
            import reactor.core.publisher.Mono;

            @Singleton
            public class DatabaseHealthIndicator implements HealthIndicator {

                @Inject
                private DataSource dataSource;

                @Override
                public Publisher<HealthResult> getResult() {
                    return Mono.fromCallable(() -> {
                        try (Connection conn = dataSource.getConnection()) {
                            boolean isValid = conn.isValid(5);
                            return isValid ?
                                HealthResult.builder("database").status(HealthStatus.UP).build() :
                                HealthResult.builder("database").status(HealthStatus.DOWN).build();
                        } catch (Exception e) {
                            return HealthResult.builder("database")
                                .status(HealthStatus.DOWN)
                                .exception(e)
                                .build();
                        }
                    });
                }
            }
            ---

7.4 性能调优

01.JVM调优
    a.内存配置
        a.功能说明
            优化JVM堆内存和垃圾回收器配置,提升应用性能。
        b.配置示例
            ---
            # 启动参数
            java -Xms512m -Xmx2g \
                 -XX:+UseG1GC \
                 -XX:MaxGCPauseMillis=200 \
                 -XX:+ParallelRefProcEnabled \
                 -jar app.jar

            # Docker配置
            docker run -m 2g \
                       -e JAVA_OPTS="-Xms512m -Xmx2g -XX:+UseG1GC" \
                       micronaut-app

            # Kubernetes配置
            resources:
              requests:
                memory: "512Mi"
                cpu: "500m"
              limits:
                memory: "2Gi"
                cpu: "2000m"
            ---
    b.GC调优
        a.功能说明
            选择合适的垃圾回收器并优化GC参数。
        b.配置示例
            ---
            # G1 GC配置(推荐)
            -XX:+UseG1GC
            -XX:MaxGCPauseMillis=200
            -XX:G1HeapRegionSize=16m
            -XX:InitiatingHeapOccupancyPercent=45

            # ZGC配置(低延迟)
            -XX:+UseZGC
            -XX:ZCollectionInterval=5
            -XX:ZAllocationSpikeTolerance=2

            # GC日志
            -Xlog:gc*:file=gc.log:time,uptime,level,tags
            ---

02.数据库优化
    a.连接池配置
        a.功能说明
            优化数据库连接池参数,提升数据库访问性能。
        b.配置示例
            ---
            // application.yml
            datasources:
              default:
                url: jdbc:mysql://localhost:3306/db
                maximum-pool-size: 20
                minimum-idle: 5
                connection-timeout: 30000
                idle-timeout: 600000
                max-lifetime: 1800000
                connection-test-query: SELECT 1
                leak-detection-threshold: 60000
            ---
    b.查询优化
        a.功能说明
            优化数据库查询,使用索引和批量操作。
        b.代码示例
            ---
            @Repository
            public interface OrderRepository extends JpaRepository<Order, Long> {

                // 使用索引字段查询
                @Query("SELECT o FROM Order o WHERE o.userId = :userId AND o.status = :status")
                List<Order> findByUserIdAndStatus(Long userId, String status);

                // 批量查询
                @Query("SELECT o FROM Order o WHERE o.id IN :ids")
                List<Order> findByIds(List<Long> ids);

                // 分页查询
                Page<Order> findByStatus(String status, Pageable pageable);

                // 使用DTO投影
                @Query("SELECT new com.example.dto.OrderSummary(o.id, o.totalAmount, o.status) " +
                       "FROM Order o WHERE o.userId = :userId")
                List<OrderSummary> findOrderSummaries(Long userId);
            }

            // 批量插入
            @Service
            public class OrderService {

                @Transactional
                public void batchInsert(List<Order> orders) {
                    int batchSize = 100;
                    for (int i = 0; i < orders.size(); i++) {
                        orderRepository.save(orders.get(i));
                        if (i % batchSize == 0) {
                            entityManager.flush();
                            entityManager.clear();
                        }
                    }
                }
            }
            ---

03.缓存优化
    a.本地缓存
        a.功能说明
            使用Caffeine实现本地缓存,减少数据库访问。
        b.代码示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.cache:micronaut-cache-caffeine")
            }

            // application.yml
            micronaut:
              caches:
                products:
                  maximum-size: 1000
                  expire-after-write: 10m
                users:
                  maximum-size: 500
                  expire-after-access: 30m

            // 使用缓存
            import io.micronaut.cache.annotation.Cacheable;
            import io.micronaut.cache.annotation.CacheInvalidate;

            @Service
            public class ProductService {

                @Cacheable("products")
                public Product findById(Long id) {
                    return productRepository.findById(id).orElseThrow();
                }

                @CacheInvalidate("products")
                public Product update(Long id, Product product) {
                    return productRepository.update(product);
                }
            }
            ---
    b.分布式缓存
        a.功能说明
            使用Redis实现分布式缓存。
        b.代码示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.redis:micronaut-redis-lettuce")
            }

            // application.yml
            redis:
              uri: redis://localhost:6379
              caches:
                orders:
                  expire-after-write: 1h

            // 使用Redis缓存
            @Service
            public class OrderService {

                @Inject
                private RedisCommands<String, String> redis;

                public Order findById(Long id) {
                    String cacheKey = "order:" + id;
                    String cached = redis.get(cacheKey);

                    if (cached != null) {
                        return objectMapper.readValue(cached, Order.class);
                    }

                    Order order = orderRepository.findById(id).orElseThrow();
                    redis.setex(cacheKey, 3600, objectMapper.writeValueAsString(order));

                    return order;
                }
            }
            ---

04.HTTP优化
    a.连接池配置
        a.功能说明
            优化HTTP客户端连接池配置。
        b.配置示例
            ---
            // application.yml
            micronaut:
              http:
                client:
                  pool:
                    enabled: true
                    max-connections: 50
                    max-pending-acquires: 100
                  read-timeout: 10s
                  connect-timeout: 5s
            ---
    b.响应压缩
        a.功能说明
            启用HTTP响应压缩,减少网络传输。
        b.配置示例
            ---
            // application.yml
            micronaut:
              server:
                netty:
                  compression:
                    enabled: true
                    mime-types:
                      - application/json
                      - text/html
                    threshold: 1024
            ---

05.异步处理
    a.响应式编程
        a.功能说明
            使用响应式编程提升并发处理能力。
        b.代码示例
            ---
            import reactor.core.publisher.Mono;
            import reactor.core.publisher.Flux;

            @Controller("/api/orders")
            public class OrderController {

                @Get("/{id}")
                public Mono<Order> getOrder(Long id) {
                    return Mono.fromCallable(() -> orderService.findById(id));
                }

                @Get
                public Flux<Order> listOrders() {
                    return Flux.fromIterable(orderService.findAll());
                }

                @Post
                public Mono<HttpResponse<Order>> createOrder(@Body Order order) {
                    return Mono.fromCallable(() -> orderService.create(order))
                        .map(HttpResponse::created);
                }
            }
            ---
    b.线程池配置
        a.功能说明
            配置异步任务线程池。
        b.配置示例
            ---
            // application.yml
            micronaut:
              executors:
                io:
                  type: fixed
                  n-threads: 75
                scheduled:
                  type: scheduled
                  core-pool-size: 2

            // 使用异步执行
            import io.micronaut.scheduling.annotation.Async;

            @Service
            public class NotificationService {

                @Async
                public void sendEmail(String to, String subject, String body) {
                    // 异步发送邮件
                }

                @Async("io")
                public void processLargeFile(String filePath) {
                    // 使用IO线程池处理文件
                }
            }
            ---

7.5 监控与日志

01.日志配置
    a.Logback配置
        a.功能说明
            配置Logback日志框架,实现日志分级和输出。
        b.配置示例
            ---
            // src/main/resources/logback.xml
            <configuration>
                <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
                    <encoder>
                        <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
                    </encoder>
                </appender>

                <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
                    <file>logs/application.log</file>
                    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                        <fileNamePattern>logs/application-%d{yyyy-MM-dd}.log</fileNamePattern>
                        <maxHistory>30</maxHistory>
                    </rollingPolicy>
                    <encoder>
                        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
                    </encoder>
                </appender>

                <logger name="com.example" level="DEBUG"/>
                <logger name="io.micronaut" level="INFO"/>
                <logger name="io.netty" level="WARN"/>

                <root level="INFO">
                    <appender-ref ref="STDOUT"/>
                    <appender-ref ref="FILE"/>
                </root>
            </configuration>

            // 在代码中使用
            import org.slf4j.Logger;
            import org.slf4j.LoggerFactory;

            @Service
            public class OrderService {

                private static final Logger LOG = LoggerFactory.getLogger(OrderService.class);

                public Order createOrder(Order order) {
                    LOG.debug("Creating order: {}", order);

                    try {
                        Order created = orderRepository.save(order);
                        LOG.info("Order created successfully: {}", created.getId());
                        return created;
                    } catch (Exception e) {
                        LOG.error("Failed to create order", e);
                        throw e;
                    }
                }
            }
            ---
    b.结构化日志
        a.功能说明
            使用JSON格式输出结构化日志,便于日志分析。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                implementation("net.logstash.logback:logstash-logback-encoder:7.3")
            }

            // logback.xml
            <appender name="JSON" class="ch.qos.logback.core.ConsoleAppender">
                <encoder class="net.logstash.logback.encoder.LogstashEncoder">
                    <includeMdcKeyName>traceId</includeMdcKeyName>
                    <includeMdcKeyName>spanId</includeMdcKeyName>
                </encoder>
            </appender>

            // 使用MDC添加上下文信息
            import org.slf4j.MDC;

            @Service
            public class OrderService {

                public Order createOrder(Order order) {
                    MDC.put("orderId", order.getId().toString());
                    MDC.put("userId", order.getUserId().toString());

                    try {
                        LOG.info("Processing order");
                        return orderRepository.save(order);
                    } finally {
                        MDC.clear();
                    }
                }
            }
            ---

02.指标监控
    a.Micrometer集成
        a.功能说明
            使用Micrometer收集应用指标。
        b.配置示例
            ---
            // build.gradle
            dependencies {
                implementation("io.micronaut.micrometer:micronaut-micrometer-core")
                implementation("io.micronaut.micrometer:micronaut-micrometer-registry-prometheus")
            }

            // application.yml
            micronaut:
              metrics:
                enabled: true
                export:
                  prometheus:
                    enabled: true
                    step: PT1M
                    descriptions: true

            endpoints:
              prometheus:
                sensitive: false

            // 访问指标端点
            // http://localhost:8080/prometheus

            // 自定义指标
            import io.micrometer.core.instrument.MeterRegistry;
            import io.micrometer.core.instrument.Counter;
            import io.micrometer.core.instrument.Timer;

            @Service
            public class OrderService {

                private final Counter orderCounter;
                private final Timer orderTimer;

                public OrderService(MeterRegistry registry) {
                    this.orderCounter = registry.counter("orders.created");
                    this.orderTimer = registry.timer("orders.processing.time");
                }

                public Order createOrder(Order order) {
                    return orderTimer.record(() -> {
                        Order created = orderRepository.save(order);
                        orderCounter.increment();
                        return created;
                    });
                }
            }
            ---
    b.健康检查
        a.功能说明
            实现健康检查端点,监控服务状态。
        b.代码示例
            ---
            // application.yml
            endpoints:
              health:
                enabled: true
                sensitive: false
                details-visible: ANONYMOUS

            // 自定义健康检查
            import io.micronaut.management.health.indicator.HealthIndicator;
            import io.micronaut.management.health.indicator.HealthResult;
            import org.reactivestreams.Publisher;
            import reactor.core.publisher.Mono;

            @Singleton
            public class CustomHealthIndicator implements HealthIndicator {

                @Inject
                private OrderService orderService;

                @Override
                public Publisher<HealthResult> getResult() {
                    return Mono.fromCallable(() -> {
                        try {
                            // 检查服务是否正常
                            long count = orderService.count();

                            return HealthResult.builder("order-service")
                                .status(HealthStatus.UP)
                                .details(Map.of("totalOrders", count))
                                .build();
                        } catch (Exception e) {
                            return HealthResult.builder("order-service")
                                .status(HealthStatus.DOWN)
                                .exception(e)
                                .build();
                        }
                    });
                }
            }

            // 访问健康检查
            // http://localhost:8080/health
            ---

03.APM集成
    a.Prometheus监控
        a.功能说明
            集成Prometheus进行指标采集和监控。
        b.配置示例
            ---
            // prometheus.yml
            global:
              scrape_interval: 15s

            scrape_configs:
              - job_name: 'micronaut-app'
                static_configs:
                  - targets: ['localhost:8080']
                metrics_path: '/prometheus'

            # 启动Prometheus
            docker run -d \
              -p 9090:9090 \
              -v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml \
              prom/prometheus

            # 访问Prometheus UI
            # http://localhost:9090
            ---
    b.Grafana可视化
        a.功能说明
            使用Grafana创建监控仪表板。
        b.配置示例
            ---
            # 启动Grafana
            docker run -d \
              -p 3000:3000 \
              grafana/grafana

            # 配置数据源
            # 1. 访问 http://localhost:3000
            # 2. 添加Prometheus数据源
            # 3. URL: http://prometheus:9090

            # 导入Micronaut仪表板
            # Dashboard ID: 11955

            # 常用查询
            # - JVM内存使用: jvm_memory_used_bytes
            # - HTTP请求数: http_server_requests_total
            # - 响应时间: http_server_requests_seconds
            # - 数据库连接: hikaricp_connections_active
            ---

04.日志聚合
    a.ELK Stack
        a.功能说明
            使用Elasticsearch、Logstash、Kibana进行日志聚合和分析。
        b.配置示例
            ---
            // logback.xml - Logstash输出
            <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
                <destination>logstash:5000</destination>
                <encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
            </appender>

            // docker-compose.yml
            version: '3'
            services:
              elasticsearch:
                image: elasticsearch:8.5.0
                ports:
                  - "9200:9200"
                environment:
                  - discovery.type=single-node

              logstash:
                image: logstash:8.5.0
                ports:
                  - "5000:5000"
                volumes:
                  - ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf

              kibana:
                image: kibana:8.5.0
                ports:
                  - "5601:5601"
                depends_on:
                  - elasticsearch

            // logstash.conf
            input {
              tcp {
                port => 5000
                codec => json
              }
            }

            output {
              elasticsearch {
                hosts => ["elasticsearch:9200"]
                index => "micronaut-logs-%{+YYYY.MM.dd}"
              }
            }
            ---
    b.日志查询
        a.功能说明
            在Kibana中查询和分析日志。
        b.查询示例
            ---
            # Kibana查询语法
            # 查询错误日志
            level: ERROR

            # 查询特定服务
            logger_name: "com.example.OrderService"

            # 查询特定时间范围
            @timestamp: [2024-01-01 TO 2024-01-31]

            # 组合查询
            level: ERROR AND logger_name: "com.example.*"

            # 聚合查询
            # 按日志级别统计
            # 按服务统计错误数
            ---

05.告警配置
    a.Prometheus告警
        a.功能说明
            配置Prometheus告警规则。
        b.配置示例
            ---
            // alert.rules.yml
            groups:
              - name: micronaut_alerts
                interval: 30s
                rules:
                  - alert: HighErrorRate
                    expr: rate(http_server_requests_total{status=~"5.."}[5m]) > 0.05
                    for: 5m
                    labels:
                      severity: critical
                    annotations:
                      summary: "High error rate detected"
                      description: "Error rate is {{ $value }} requests/sec"

                  - alert: HighMemoryUsage
                    expr: jvm_memory_used_bytes / jvm_memory_max_bytes > 0.9
                    for: 5m
                    labels:
                      severity: warning
                    annotations:
                      summary: "High memory usage"
                      description: "Memory usage is {{ $value | humanizePercentage }}"

                  - alert: ServiceDown
                    expr: up == 0
                    for: 1m
                    labels:
                      severity: critical
                    annotations:
                      summary: "Service is down"
            ---
    b.Alertmanager配置
        a.功能说明
            配置告警通知渠道。
        b.配置示例
            ---
            // alertmanager.yml
            global:
              resolve_timeout: 5m

            route:
              group_by: ['alertname']
              group_wait: 10s
              group_interval: 10s
              repeat_interval: 1h
              receiver: 'email'

            receivers:
              - name: 'email'
                email_configs:
                  - to: '[email protected]'
                    from: '[email protected]'
                    smarthost: 'smtp.example.com:587'
                    auth_username: 'alertmanager'
                    auth_password: 'password'

              - name: 'slack'
                slack_configs:
                  - api_url: 'https://hooks.slack.com/services/xxx'
                    channel: '#alerts'
            ---

7.6 容器化部署

01.Docker镜像构建
    a.Dockerfile编写
        a.功能说明
            编写Dockerfile构建应用镜像。
        b.配置示例
            ---
            # 多阶段构建Dockerfile
            FROM gradle:8.5-jdk17 AS builder

            WORKDIR /app
            COPY . .

            RUN gradle clean build --no-daemon

            FROM eclipse-temurin:17-jre-alpine

            WORKDIR /app

            COPY --from=builder /app/build/libs/app.jar app.jar

            EXPOSE 8080

            ENTRYPOINT ["java", "-jar", "app.jar"]

            # 构建镜像
            docker build -t micronaut-app:1.0.0 .

            # 运行容器
            docker run -d \
              -p 8080:8080 \
              --name micronaut-app \
              micronaut-app:1.0.0
            ---
    b.镜像优化
        a.功能说明
            优化Docker镜像大小和构建速度。
        b.配置示例
            ---
            # 使用.dockerignore
            .git
            .gradle
            build
            *.md
            .idea

            # 分层构建
            FROM gradle:8.5-jdk17 AS builder
            WORKDIR /app

            # 先复制依赖文件
            COPY build.gradle settings.gradle ./
            COPY gradle ./gradle
            RUN gradle dependencies --no-daemon

            # 再复制源代码
            COPY src ./src
            RUN gradle build --no-daemon

            # 使用Alpine基础镜像
            FROM eclipse-temurin:17-jre-alpine

            # 添加非root用户
            RUN addgroup -S micronaut && adduser -S micronaut -G micronaut

            WORKDIR /app
            COPY --from=builder /app/build/libs/app.jar app.jar

            RUN chown -R micronaut:micronaut /app
            USER micronaut

            EXPOSE 8080

            ENTRYPOINT ["java", \
              "-XX:+UseContainerSupport", \
              "-XX:MaxRAMPercentage=75.0", \
              "-jar", "app.jar"]
            ---

02.Docker Compose
    a.多服务编排
        a.功能说明
            使用Docker Compose编排多个服务。
        b.配置示例
            ---
            # docker-compose.yml
            version: '3.8'

            services:
              order-service:
                build: ./order-service
                ports:
                  - "8080:8080"
                environment:
                  - MICRONAUT_ENVIRONMENTS=prod
                  - DB_HOST=mysql
                  - REDIS_HOST=redis
                depends_on:
                  - mysql
                  - redis
                networks:
                  - app-network

              inventory-service:
                build: ./inventory-service
                ports:
                  - "8081:8080"
                environment:
                  - MICRONAUT_ENVIRONMENTS=prod
                  - DB_HOST=mysql
                depends_on:
                  - mysql
                networks:
                  - app-network

              mysql:
                image: mysql:8.0
                environment:
                  - MYSQL_ROOT_PASSWORD=secret
                  - MYSQL_DATABASE=orders
                volumes:
                  - mysql-data:/var/lib/mysql
                networks:
                  - app-network

              redis:
                image: redis:7-alpine
                networks:
                  - app-network

            volumes:
              mysql-data:

            networks:
              app-network:
                driver: bridge

            # 启动所有服务
            docker-compose up -d

            # 查看日志
            docker-compose logs -f order-service

            # 停止服务
            docker-compose down
            ---
    b.健康检查
        a.功能说明
            配置容器健康检查。
        b.配置示例
            ---
            # docker-compose.yml
            services:
              order-service:
                build: ./order-service
                healthcheck:
                  test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
                  interval: 30s
                  timeout: 10s
                  retries: 3
                  start_period: 40s

            # Dockerfile
            FROM eclipse-temurin:17-jre-alpine

            # 安装curl用于健康检查
            RUN apk add --no-cache curl

            WORKDIR /app
            COPY app.jar app.jar

            HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
              CMD curl -f http://localhost:8080/health || exit 1

            ENTRYPOINT ["java", "-jar", "app.jar"]
            ---

03.Kubernetes部署
    a.Deployment配置
        a.功能说明
            创建Kubernetes Deployment部署应用。
        b.配置示例
            ---
            # deployment.yaml
            apiVersion: apps/v1
            kind: Deployment
            metadata:
              name: order-service
              labels:
                app: order-service
            spec:
              replicas: 3
              selector:
                matchLabels:
                  app: order-service
              template:
                metadata:
                  labels:
                    app: order-service
                spec:
                  containers:
                  - name: order-service
                    image: micronaut-app:1.0.0
                    ports:
                    - containerPort: 8080
                    env:
                    - name: MICRONAUT_ENVIRONMENTS
                      value: "prod"
                    - name: DB_HOST
                      value: "mysql-service"
                    resources:
                      requests:
                        memory: "512Mi"
                        cpu: "500m"
                      limits:
                        memory: "1Gi"
                        cpu: "1000m"
                    livenessProbe:
                      httpGet:
                        path: /health
                        port: 8080
                      initialDelaySeconds: 30
                      periodSeconds: 10
                    readinessProbe:
                      httpGet:
                        path: /health
                        port: 8080
                      initialDelaySeconds: 20
                      periodSeconds: 5

            # 部署应用
            kubectl apply -f deployment.yaml

            # 查看部署状态
            kubectl get deployments
            kubectl get pods

            # 查看日志
            kubectl logs -f deployment/order-service
            ---
    b.Service配置
        a.功能说明
            创建Kubernetes Service暴露应用。
        b.配置示例
            ---
            # service.yaml
            apiVersion: v1
            kind: Service
            metadata:
              name: order-service
            spec:
              type: LoadBalancer
              selector:
                app: order-service
              ports:
              - protocol: TCP
                port: 80
                targetPort: 8080

            # 部署Service
            kubectl apply -f service.yaml

            # 查看Service
            kubectl get services

            # 获取外部IP
            kubectl get service order-service
            ---
    c.ConfigMap和Secret
        a.功能说明
            使用ConfigMap和Secret管理配置和敏感信息。
        b.配置示例
            ---
            # configmap.yaml
            apiVersion: v1
            kind: ConfigMap
            metadata:
              name: order-config
            data:
              application.yml: |
                micronaut:
                  application:
                    name: order-service
                  server:
                    port: 8080

            # secret.yaml
            apiVersion: v1
            kind: Secret
            metadata:
              name: order-secret
            type: Opaque
            data:
              db-password: c2VjcmV0  # base64编码

            # 在Deployment中使用
            spec:
              containers:
              - name: order-service
                env:
                - name: DB_PASSWORD
                  valueFrom:
                    secretKeyRef:
                      name: order-secret
                      key: db-password
                volumeMounts:
                - name: config
                  mountPath: /app/config
              volumes:
              - name: config
                configMap:
                  name: order-config

            # 创建ConfigMap和Secret
            kubectl apply -f configmap.yaml
            kubectl apply -f secret.yaml
            ---

04.Helm部署
    a.Chart创建
        a.功能说明
            使用Helm简化Kubernetes应用部署。
        b.配置示例
            ---
            # 创建Helm Chart
            helm create micronaut-app

            # Chart.yaml
            apiVersion: v2
            name: micronaut-app
            version: 1.0.0
            appVersion: "1.0.0"

            # values.yaml
            replicaCount: 3

            image:
              repository: micronaut-app
              tag: "1.0.0"
              pullPolicy: IfNotPresent

            service:
              type: LoadBalancer
              port: 80
              targetPort: 8080

            resources:
              requests:
                memory: "512Mi"
                cpu: "500m"
              limits:
                memory: "1Gi"
                cpu: "1000m"

            env:
              - name: MICRONAUT_ENVIRONMENTS
                value: "prod"

            # 安装Chart
            helm install order-service ./micronaut-app

            # 升级
            helm upgrade order-service ./micronaut-app

            # 回滚
            helm rollback order-service 1

            # 卸载
            helm uninstall order-service
            ---
    b.多环境配置
        a.功能说明
            为不同环境配置不同的values文件。
        b.配置示例
            ---
            # values-dev.yaml
            replicaCount: 1
            image:
              tag: "dev"
            env:
              - name: MICRONAUT_ENVIRONMENTS
                value: "dev"

            # values-prod.yaml
            replicaCount: 5
            image:
              tag: "1.0.0"
            env:
              - name: MICRONAUT_ENVIRONMENTS
                value: "prod"
            resources:
              requests:
                memory: "1Gi"
                cpu: "1000m"

            # 部署到不同环境
            helm install order-service-dev ./micronaut-app -f values-dev.yaml
            helm install order-service-prod ./micronaut-app -f values-prod.yaml
            ---

05.CI/CD集成
    a.GitHub Actions
        a.功能说明
            使用GitHub Actions自动化构建和部署。
        b.配置示例
            ---
            # .github/workflows/deploy.yml
            name: Build and Deploy

            on:
              push:
                branches: [ main ]

            jobs:
              build:
                runs-on: ubuntu-latest

                steps:
                  - uses: actions/checkout@v3

                  - name: Set up JDK 17
                    uses: actions/setup-java@v3
                    with:
                      java-version: '17'
                      distribution: 'temurin'

                  - name: Build with Gradle
                    run: ./gradlew build

                  - name: Build Docker image
                    run: docker build -t micronaut-app:${{ github.sha }} .

                  - name: Push to Registry
                    run: |
                      echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
                      docker tag micronaut-app:${{ github.sha }} myregistry/micronaut-app:${{ github.sha }}
                      docker push myregistry/micronaut-app:${{ github.sha }}

                  - name: Deploy to Kubernetes
                    uses: azure/k8s-deploy@v4
                    with:
                      manifests: |
                        k8s/deployment.yaml
                        k8s/service.yaml
                      images: |
                        myregistry/micronaut-app:${{ github.sha }}
            ---
    b.GitLab CI
        a.功能说明
            使用GitLab CI/CD进行自动化部署。
        b.配置示例
            ---
            # .gitlab-ci.yml
            stages:
              - build
              - test
              - deploy

            variables:
              DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

            build:
              stage: build
              image: gradle:8.5-jdk17
              script:
                - gradle clean build
              artifacts:
                paths:
                  - build/libs/*.jar

            docker:
              stage: build
              image: docker:latest
              services:
                - docker:dind
              script:
                - docker build -t $DOCKER_IMAGE .
                - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
                - docker push $DOCKER_IMAGE

            deploy:
              stage: deploy
              image: bitnami/kubectl:latest
              script:
                - kubectl set image deployment/order-service order-service=$DOCKER_IMAGE
                - kubectl rollout status deployment/order-service
              only:
                - main
            ---

7.7 常见问题排查

01.启动问题
    a.端口占用
        a.问题描述
            应用启动失败,提示端口已被占用。
        b.解决方案
            ---
            # 查看端口占用
            # Linux/macOS
            lsof -i :8080
            netstat -an | grep 8080

            # Windows
            netstat -ano | findstr :8080

            # 终止占用进程
            kill -9 <PID>

            # 或修改应用端口
            // application.yml
            micronaut:
              server:
                port: 8081

            # 或使用随机端口
            micronaut:
              server:
                port: -1
            ---
    b.依赖冲突
        a.问题描述
            应用启动时出现ClassNotFoundException或NoSuchMethodError。
        b.解决方案
            ---
            # 查看依赖树
            ./gradlew dependencies

            # 排除冲突依赖
            // build.gradle
            dependencies {
                implementation("io.micronaut:micronaut-runtime") {
                    exclude group: 'org.slf4j', module: 'slf4j-api'
                }
            }

            # 强制使用特定版本
            configurations.all {
                resolutionStrategy {
                    force 'org.slf4j:slf4j-api:2.0.0'
                }
            }

            # 清理缓存重新构建
            ./gradlew clean build --refresh-dependencies
            ---
    c.Bean注入失败
        a.问题描述
            启动时提示No bean of type found。
        b.解决方案
            ---
            # 检查Bean定义
            @Singleton  // 确保有注解
            public class OrderService {
                // ...
            }

            # 检查包扫描路径
            @Application
            @ComponentScan("com.example")  // 指定扫描路径
            public class Application {
                // ...
            }

            # 检查依赖注入
            @Controller("/orders")
            public class OrderController {

                @Inject  // 使用@Inject注解
                private OrderService orderService;

                // 或使用构造器注入(推荐)
                public OrderController(OrderService orderService) {
                    this.orderService = orderService;
                }
            }

            # 查看Bean定义
            ./gradlew run --debug
            ---

02.数据库问题
    a.连接失败
        a.问题描述
            应用无法连接到数据库。
        b.解决方案
            ---
            # 检查数据库配置
            // application.yml
            datasources:
              default:
                url: jdbc:mysql://localhost:3306/db?serverTimezone=UTC
                username: root
                password: secret
                driverClassName: com.mysql.cj.jdbc.Driver

            # 测试数据库连接
            mysql -h localhost -u root -p

            # 检查防火墙
            telnet localhost 3306

            # 检查数据库驱动
            // build.gradle
            dependencies {
                runtimeOnly("mysql:mysql-connector-java:8.0.33")
            }

            # 启用SQL日志
            // application.yml
            jpa:
              default:
                properties:
                  hibernate:
                    show_sql: true
                    format_sql: true

            logger:
              levels:
                org.hibernate.SQL: DEBUG
                org.hibernate.type.descriptor.sql.BasicBinder: TRACE
            ---
    b.事务问题
        a.问题描述
            数据未正确提交或回滚。
        b.解决方案
            ---
            # 确保使用@Transactional注解
            @Service
            public class OrderService {

                @Transactional
                public Order createOrder(Order order) {
                    return orderRepository.save(order);
                }

                @Transactional(readOnly = true)
                public Order findById(Long id) {
                    return orderRepository.findById(id).orElseThrow();
                }
            }

            # 检查事务传播
            @Transactional(propagation = Propagation.REQUIRES_NEW)
            public void independentOperation() {
                // 独立事务
            }

            # 异常回滚配置
            @Transactional(rollbackFor = Exception.class)
            public void riskyOperation() throws Exception {
                // 所有��常都回滚
            }

            # 手动事务管理
            @Inject
            private TransactionOperations<Connection> transactionManager;

            public void manualTransaction() {
                transactionManager.executeWrite(status -> {
                    // 事务操作
                    return null;
                });
            }
            ---

03.性能问题
    a.响应慢
        a.问题描述
            API响应时间过长。
        b.解决方案
            ---
            # 启用请求日志
            // application.yml
            logger:
              levels:
                io.micronaut.http.server: DEBUG

            # 添加性能监控
            import io.micrometer.core.instrument.Timer;

            @Controller("/orders")
            public class OrderController {

                @Inject
                private MeterRegistry registry;

                @Get("/{id}")
                public Order getOrder(Long id) {
                    Timer.Sample sample = Timer.start(registry);

                    try {
                        return orderService.findById(id);
                    } finally {
                        sample.stop(registry.timer("order.get.time"));
                    }
                }
            }

            # 检查数据库查询
            // 启用慢查询日志
            jpa:
              default:
                properties:
                  hibernate:
                    generate_statistics: true

            # 添加数据库索引
            @Entity
            @Table(indexes = {
                @Index(name = "idx_user_id", columnList = "user_id"),
                @Index(name = "idx_status", columnList = "status")
            })
            public class Order {
                // ...
            }

            # 使用缓存
            @Cacheable("orders")
            public Order findById(Long id) {
                return orderRepository.findById(id).orElseThrow();
            }
            ---
    b.内存泄漏
        a.问题描述
            应用内存持续增长,最终OOM。
        b.解决方案
            ---
            # 生成堆转储
            jmap -dump:live,format=b,file=heap.bin <pid>

            # 分析堆转储
            # 使用Eclipse MAT或VisualVM

            # 启用GC日志
            java -Xlog:gc*:file=gc.log:time,uptime,level,tags \
                 -jar app.jar

            # 检查资源泄漏
            @Service
            public class FileService {

                public void processFile(String path) {
                    // 使用try-with-resources
                    try (InputStream is = new FileInputStream(path)) {
                        // 处理文件
                    } catch (IOException e) {
                        LOG.error("Failed to process file", e);
                    }
                }
            }

            # 检查线程池
            @Inject
            @Named("io")
            private ExecutorService executor;

            @PreDestroy
            public void cleanup() {
                executor.shutdown();
            }
            ---

04.网络问题
    a.服务调用失败
        a.问题描述
            微服务间调用失败或超时。
        b.解决方案
            ---
            # 检查服务发现
            @Client("inventory-service")
            public interface InventoryClient {
                @Get("/inventory/{id}")
                Inventory getInventory(Long id);
            }

            # 配置超时
            // application.yml
            micronaut:
              http:
                client:
                  read-timeout: 30s
                  connect-timeout: 10s

            # 添加重试
            // build.gradle
            dependencies {
                implementation("io.micronaut.retry:micronaut-retry")
            }

            @Retryable(attempts = "3", delay = "1s")
            public Inventory getInventory(Long id) {
                return inventoryClient.getInventory(id);
            }

            # 添加熔断器
            @CircuitBreaker(name = "inventory-service")
            public Inventory getInventory(Long id) {
                return inventoryClient.getInventory(id);
            }

            # 检查网络连通性
            curl http://inventory-service:8080/health
            ping inventory-service
            ---
    b.负载均衡问题
        a.问题描述
            请求未均匀分配到服务实例。
        b.解决方案
            ---
            # 检查服务注册
            curl http://consul:8500/v1/catalog/service/order-service

            # 配置负载均衡策略
            // application.yml
            micronaut:
              http:
                client:
                  load-balancer:
                    strategy: round-robin  # 或 random

            # 健康检查配置
            consul:
              client:
                registration:
                  check:
                    enabled: true
                    interval: 10s
                    http: true
                    path: /health

            # 查看负载均衡日志
            logger:
              levels:
                io.micronaut.http.client.loadbalance: DEBUG
            ---

05.配置问题
    a.配置不生效
        a.问题描述
            修改配置后应用行为未改变。
        b.解决方案
            ---
            # 检查配置文件位置
            src/main/resources/application.yml
            src/main/resources/application-{env}.yml

            # 检查环境变量
            export MICRONAUT_ENVIRONMENTS=prod
            java -jar app.jar

            # 或使用系统属性
            java -Dmicronaut.environments=prod -jar app.jar

            # 查看生效的配置
            @Inject
            private Environment environment;

            public void printConfig() {
                environment.getPropertySources().forEach(source -> {
                    LOG.info("Config source: {}", source.getName());
                });
            }

            # 配置优先级
            # 1. 命令行参数
            # 2. 系统属性
            # 3. 环境变量
            # 4. 配置中心
            # 5. application.yml
            ---
    b.配置验证失败
        a.问题描述
            启动时提示配置验证错误。
        b.解决方案
            ---
            # 检查配置类
            @ConfigurationProperties("app")
            public class AppConfig {

                @NotBlank
                private String name;

                @Min(1)
                private int maxConnections;

                // Getters and Setters
            }

            # 提供正确的配置
            // application.yml
            app:
              name: "order-service"
              max-connections: 10

            # 禁用验证(不推荐)
            @ConfigurationProperties(value = "app", validate = false)
            public class AppConfig {
                // ...
            }
            ---

06.日志问题
    a.日志未输出
        a.问题描述
            应用日志未正常输出。
        b.解决方案
            ---
            # 检查logback配置
            // src/main/resources/logback.xml
            <configuration>
                <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
                    <encoder>
                        <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
                    </encoder>
                </appender>

                <root level="INFO">
                    <appender-ref ref="STDOUT"/>
                </root>
            </configuration>

            # 检查日志级别
            // application.yml
            logger:
              levels:
                com.example: DEBUG
                io.micronaut: INFO

            # 使用正确的Logger
            import org.slf4j.Logger;
            import org.slf4j.LoggerFactory;

            private static final Logger LOG = LoggerFactory.getLogger(OrderService.class);

            # 检查依赖
            // build.gradle
            dependencies {
                runtimeOnly("ch.qos.logback:logback-classic")
            }
            ---
    b.日志文件过大
        a.问题描述
            日志文件占用大量磁盘空间。
        b.解决方案
            ---
            # 配置日志滚动
            <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
                <file>logs/application.log</file>
                <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
                    <fileNamePattern>logs/application-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
                    <maxFileSize>100MB</maxFileSize>
                    <maxHistory>30</maxHistory>
                    <totalSizeCap>10GB</totalSizeCap>
                </rollingPolicy>
                <encoder>
                    <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
                </encoder>
            </appender>

            # 调整日志级别
            logger:
              levels:
                root: WARN
                com.example: INFO

            # 使用异步日志
            <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
                <appender-ref ref="FILE"/>
                <queueSize>512</queueSize>
            </appender>
            ---