2.1 CDI(Contexts and Dependency Injection)基础

2.1.1 CDI 概述

CDI 是 Jakarta EE 的核心规范之一,Quarkus 使用 ArC(一个轻量级的 CDI 实现)来提供依赖注入功能。CDI 提供了类型安全的依赖注入、拦截器、装饰器和事件机制。

graph TB
    A[CDI 容器] --> B[Bean 管理]
    A --> C[依赖注入]
    A --> D[生命周期管理]
    A --> E[事件系统]
    A --> F[拦截器]
    
    B --> B1[Bean 发现]
    B --> B2[Bean 创建]
    B --> B3[Bean 销毁]
    
    C --> C1[构造器注入]
    C --> C2[字段注入]
    C --> C3[方法注入]
    
    D --> D1[@ApplicationScoped]
    D --> D2[@RequestScoped]
    D --> D3[@Singleton]
    
    E --> E1[事件发布]
    E --> E2[事件监听]
    
    F --> F1[方法拦截]
    F --> F2[AOP 支持]

2.1.2 Bean 的定义和发现

基本 Bean 定义

package com.example.service;

import jakarta.enterprise.context.ApplicationScoped;

// 应用作用域的 Bean
@ApplicationScoped
public class GreetingService {
    
    public String greet(String name) {
        return "Hello, " + name + "!";
    }
    
    public String greetWithTime(String name) {
        return String.format("Hello, %s! Current time: %s", 
                           name, java.time.LocalTime.now());
    }
}

Bean 发现规则

// 1. 使用 CDI 注解的类自动成为 Bean
@ApplicationScoped
public class UserService {
    // 自动发现
}

// 2. 使用 @Produces 方法创建 Bean
@ApplicationScoped
public class ConfigurationProducer {
    
    @Produces
    @ApplicationScoped
    public DatabaseConfig createDatabaseConfig() {
        return new DatabaseConfig("localhost", 5432, "mydb");
    }
}

// 3. 接口实现自动成为 Bean
public interface NotificationService {
    void sendNotification(String message);
}

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

2.2 依赖注入模式

2.2.1 构造器注入(推荐)

package com.example.resource;

import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import com.example.service.GreetingService;
import com.example.service.UserService;

@Path("/api/greetings")
public class GreetingResource {
    
    private final GreetingService greetingService;
    private final UserService userService;
    
    // 构造器注入 - 推荐方式
    public GreetingResource(GreetingService greetingService, 
                           UserService userService) {
        this.greetingService = greetingService;
        this.userService = userService;
    }
    
    @GET
    @Path("/hello/{name}")
    @Produces(MediaType.TEXT_PLAIN)
    public String hello(@PathParam("name") String name) {
        return greetingService.greet(name);
    }
    
    @GET
    @Path("/time/{name}")
    @Produces(MediaType.TEXT_PLAIN)
    public String helloWithTime(@PathParam("name") String name) {
        return greetingService.greetWithTime(name);
    }
}

2.2.2 字段注入

@Path("/api/users")
public class UserResource {
    
    // 字段注入
    @Inject
    UserService userService;
    
    @Inject
    NotificationService notificationService;
    
    @GET
    @Path("/{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public User getUser(@PathParam("id") Long id) {
        return userService.findById(id);
    }
    
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public User createUser(User user) {
        User savedUser = userService.save(user);
        notificationService.sendNotification("User created: " + user.getName());
        return savedUser;
    }
}

2.2.3 方法注入

@ApplicationScoped
public class OrderService {
    
    private PaymentService paymentService;
    private InventoryService inventoryService;
    
    // 方法注入
    @Inject
    public void setServices(PaymentService paymentService, 
                           InventoryService inventoryService) {
        this.paymentService = paymentService;
        this.inventoryService = inventoryService;
    }
    
    public Order processOrder(Order order) {
        // 检查库存
        if (!inventoryService.checkAvailability(order.getItems())) {
            throw new IllegalStateException("Insufficient inventory");
        }
        
        // 处理支付
        Payment payment = paymentService.processPayment(order.getTotal());
        order.setPayment(payment);
        
        return order;
    }
}

2.3 Bean 作用域

2.3.1 应用作用域(@ApplicationScoped)

// 应用启动时创建,应用关闭时销毁
// 整个应用共享一个实例
@ApplicationScoped
public class CacheService {
    
    private final Map<String, Object> cache = new ConcurrentHashMap<>();
    
    public void put(String key, Object value) {
        cache.put(key, value);
    }
    
    public <T> T get(String key, Class<T> type) {
        return type.cast(cache.get(key));
    }
    
    public void clear() {
        cache.clear();
    }
    
    // 生命周期回调
    @PostConstruct
    void init() {
        System.out.println("CacheService initialized");
    }
    
    @PreDestroy
    void cleanup() {
        System.out.println("CacheService destroyed");
        cache.clear();
    }
}

2.3.2 请求作用域(@RequestScoped)

// 每个 HTTP 请求创建一个新实例
@RequestScoped
public class RequestContext {
    
    private String requestId;
    private LocalDateTime startTime;
    private Map<String, Object> attributes = new HashMap<>();
    
    @PostConstruct
    void init() {
        this.requestId = UUID.randomUUID().toString();
        this.startTime = LocalDateTime.now();
        System.out.println("Request context created: " + requestId);
    }
    
    @PreDestroy
    void cleanup() {
        Duration duration = Duration.between(startTime, LocalDateTime.now());
        System.out.println("Request " + requestId + " completed in " + 
                          duration.toMillis() + "ms");
    }
    
    // Getter 和 Setter 方法
    public String getRequestId() { return requestId; }
    public LocalDateTime getStartTime() { return startTime; }
    public Map<String, Object> getAttributes() { return attributes; }
}

2.3.3 单例作用域(@Singleton)

// 应用启动时立即创建,线程安全
@Singleton
public class MetricsCollector {
    
    private final AtomicLong requestCount = new AtomicLong(0);
    private final AtomicLong errorCount = new AtomicLong(0);
    private final Map<String, AtomicLong> endpointCounts = new ConcurrentHashMap<>();
    
    public void incrementRequestCount() {
        requestCount.incrementAndGet();
    }
    
    public void incrementErrorCount() {
        errorCount.incrementAndGet();
    }
    
    public void incrementEndpointCount(String endpoint) {
        endpointCounts.computeIfAbsent(endpoint, k -> new AtomicLong(0))
                     .incrementAndGet();
    }
    
    public MetricsSnapshot getSnapshot() {
        return new MetricsSnapshot(
            requestCount.get(),
            errorCount.get(),
            new HashMap<>(endpointCounts.entrySet().stream()
                .collect(Collectors.toMap(
                    Map.Entry::getKey,
                    entry -> entry.getValue().get()
                )))
        );
    }
    
    public static class MetricsSnapshot {
        public final long requestCount;
        public final long errorCount;
        public final Map<String, Long> endpointCounts;
        
        public MetricsSnapshot(long requestCount, long errorCount, 
                              Map<String, Long> endpointCounts) {
            this.requestCount = requestCount;
            this.errorCount = errorCount;
            this.endpointCounts = endpointCounts;
        }
    }
}

2.4 限定符(Qualifiers)

2.4.1 自定义限定符

// 定义限定符注解
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
public @interface Email {
}

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
public @interface SMS {
}

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
public @interface Push {
}

2.4.2 使用限定符

// 不同的通知服务实现
@Email
@ApplicationScoped
public class EmailNotificationService implements NotificationService {
    @Override
    public void sendNotification(String message) {
        System.out.println("📧 Email: " + message);
    }
}

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

@Push
@ApplicationScoped
public class PushNotificationService implements NotificationService {
    @Override
    public void sendNotification(String message) {
        System.out.println("🔔 Push: " + message);
    }
}

// 使用特定的实现
@ApplicationScoped
public class NotificationManager {
    
    private final NotificationService emailService;
    private final NotificationService smsService;
    private final NotificationService pushService;
    
    public NotificationManager(@Email NotificationService emailService,
                              @SMS NotificationService smsService,
                              @Push NotificationService pushService) {
        this.emailService = emailService;
        this.smsService = smsService;
        this.pushService = pushService;
    }
    
    public void sendAllNotifications(String message) {
        emailService.sendNotification(message);
        smsService.sendNotification(message);
        pushService.sendNotification(message);
    }
    
    public void sendEmailNotification(String message) {
        emailService.sendNotification(message);
    }
}

2.4.3 参数化限定符

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
public @interface Database {
    DatabaseType value();
    
    enum DatabaseType {
        MYSQL, POSTGRESQL, MONGODB
    }
}

// 不同数据库的实现
@Database(Database.DatabaseType.MYSQL)
@ApplicationScoped
public class MySQLUserRepository implements UserRepository {
    @Override
    public User findById(Long id) {
        // MySQL 实现
        return new User(id, "MySQL User");
    }
}

@Database(Database.DatabaseType.POSTGRESQL)
@ApplicationScoped
public class PostgreSQLUserRepository implements UserRepository {
    @Override
    public User findById(Long id) {
        // PostgreSQL 实现
        return new User(id, "PostgreSQL User");
    }
}

// 使用参数化限定符
@ApplicationScoped
public class UserService {
    
    private final UserRepository primaryRepository;
    private final UserRepository secondaryRepository;
    
    public UserService(@Database(Database.DatabaseType.POSTGRESQL) UserRepository primaryRepository,
                      @Database(Database.DatabaseType.MYSQL) UserRepository secondaryRepository) {
        this.primaryRepository = primaryRepository;
        this.secondaryRepository = secondaryRepository;
    }
    
    public User findById(Long id) {
        try {
            return primaryRepository.findById(id);
        } catch (Exception e) {
            // 降级到备用数据库
            return secondaryRepository.findById(id);
        }
    }
}

2.5 配置管理

2.5.1 配置文件层次结构

graph TB
    A[配置源优先级] --> B[系统属性]
    A --> C[环境变量]
    A --> D[.env 文件]
    A --> E[application.properties]
    A --> F[application.yaml]
    A --> G[配置文件 Profile]
    
    G --> G1[application-dev.properties]
    G --> G2[application-prod.properties]
    G --> G3[application-test.properties]
    
    B --> H[最高优先级]
    C --> I[高优先级]
    D --> J[中等优先级]
    E --> K[低优先级]
    F --> L[最低优先级]

2.5.2 基本配置属性

# application.properties

# 应用基本信息
app.name=Quarkus Demo
app.version=1.0.0
app.description=A sample Quarkus application

# 服务器配置
quarkus.http.port=8080
quarkus.http.host=0.0.0.0
quarkus.http.cors=true

# 数据库配置
quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=admin
quarkus.datasource.password=secret
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/mydb
quarkus.datasource.jdbc.max-size=20
quarkus.datasource.jdbc.min-size=5

# JPA/Hibernate 配置
quarkus.hibernate-orm.database.generation=drop-and-create
quarkus.hibernate-orm.log.sql=true
quarkus.hibernate-orm.sql-load-script=import.sql

# 日志配置
quarkus.log.level=INFO
quarkus.log.category."com.example".level=DEBUG
quarkus.log.console.format=%d{HH:mm:ss} %-5p [%c{2.}] (%t) %s%e%n

# 自定义业务配置
business.email.smtp.host=smtp.gmail.com
business.email.smtp.port=587
business.email.from=noreply@example.com

business.cache.ttl=3600
business.cache.max-size=1000

business.notification.enabled=true
business.notification.batch-size=100

2.5.3 配置属性注入

单个属性注入

@ApplicationScoped
public class EmailService {
    
    @ConfigProperty(name = "business.email.smtp.host")
    String smtpHost;
    
    @ConfigProperty(name = "business.email.smtp.port")
    int smtpPort;
    
    @ConfigProperty(name = "business.email.from")
    String fromAddress;
    
    // 带默认值的配置
    @ConfigProperty(name = "business.email.timeout", defaultValue = "30")
    int timeout;
    
    // Optional 配置
    @ConfigProperty(name = "business.email.debug")
    Optional<Boolean> debugEnabled;
    
    public void sendEmail(String to, String subject, String body) {
        System.out.printf("Sending email via %s:%d from %s to %s%n", 
                         smtpHost, smtpPort, fromAddress, to);
        System.out.printf("Subject: %s%n", subject);
        System.out.printf("Body: %s%n", body);
        
        if (debugEnabled.orElse(false)) {
            System.out.println("Debug mode enabled");
        }
    }
}

配置对象映射

// 配置映射接口
@ConfigMapping(prefix = "business.cache")
public interface CacheConfig {
    
    @WithDefault("3600")
    int ttl();
    
    @WithDefault("1000")
    int maxSize();
    
    @WithDefault("true")
    boolean enabled();
    
    Optional<String> provider();
    
    // 嵌套配置
    RedisConfig redis();
    
    interface RedisConfig {
        String host();
        
        @WithDefault("6379")
        int port();
        
        Optional<String> password();
        
        @WithDefault("0")
        int database();
    }
}

// 使用配置对象
@ApplicationScoped
public class CacheService {
    
    private final CacheConfig config;
    private final Map<String, CacheEntry> cache = new ConcurrentHashMap<>();
    
    public CacheService(CacheConfig config) {
        this.config = config;
    }
    
    @PostConstruct
    void init() {
        System.out.println("Cache initialized with TTL: " + config.ttl() + 
                          ", Max Size: " + config.maxSize());
        
        if (config.redis().host() != null) {
            System.out.println("Redis configured at: " + 
                              config.redis().host() + ":" + config.redis().port());
        }
    }
    
    public void put(String key, Object value) {
        if (!config.enabled()) {
            return;
        }
        
        if (cache.size() >= config.maxSize()) {
            // 简单的 LRU 清理
            cache.entrySet().iterator().next();
            cache.remove(cache.keySet().iterator().next());
        }
        
        cache.put(key, new CacheEntry(value, System.currentTimeMillis()));
    }
    
    public <T> Optional<T> get(String key, Class<T> type) {
        if (!config.enabled()) {
            return Optional.empty();
        }
        
        CacheEntry entry = cache.get(key);
        if (entry == null) {
            return Optional.empty();
        }
        
        // 检查 TTL
        if (System.currentTimeMillis() - entry.timestamp > config.ttl() * 1000L) {
            cache.remove(key);
            return Optional.empty();
        }
        
        return Optional.of(type.cast(entry.value));
    }
    
    private static class CacheEntry {
        final Object value;
        final long timestamp;
        
        CacheEntry(Object value, long timestamp) {
            this.value = value;
            this.timestamp = timestamp;
        }
    }
}

2.5.4 环境特定配置

Profile 配置

# application.properties (默认配置)
app.environment=default
quarkus.log.level=INFO

# application-dev.properties (开发环境)
app.environment=development
quarkus.log.level=DEBUG
quarkus.hibernate-orm.database.generation=drop-and-create
quarkus.hibernate-orm.log.sql=true

# application-prod.properties (生产环境)
app.environment=production
quarkus.log.level=WARN
quarkus.hibernate-orm.database.generation=none
quarkus.hibernate-orm.log.sql=false
quarkus.datasource.jdbc.max-size=50

# application-test.properties (测试环境)
app.environment=test
quarkus.log.level=DEBUG
quarkus.datasource.db-kind=h2
quarkus.datasource.jdbc.url=jdbc:h2:mem:testdb
quarkus.hibernate-orm.database.generation=drop-and-create

环境变量配置

# 设置环境变量
export QUARKUS_PROFILE=prod
export QUARKUS_DATASOURCE_PASSWORD=prod_secret
export BUSINESS_EMAIL_SMTP_HOST=prod-smtp.example.com

# 或者在 .env 文件中
QUARKUS_PROFILE=dev
QUARKUS_DATASOURCE_PASSWORD=dev_secret
BUSINESS_EMAIL_SMTP_HOST=dev-smtp.example.com

2.5.5 动态配置和配置热更新

@ApplicationScoped
public class DynamicConfigService {
    
    @Inject
    @ConfigProperty(name = "business.feature.enabled")
    Instance<Boolean> featureEnabled;
    
    @Inject
    @ConfigProperty(name = "business.rate.limit")
    Instance<Integer> rateLimit;
    
    public boolean isFeatureEnabled() {
        return featureEnabled.get();
    }
    
    public int getRateLimit() {
        return rateLimit.get();
    }
    
    // 配置变更监听
    void onConfigChange(@Observes @ConfigProperty(name = "business.feature.enabled") 
                       ConfigPropertyChangeEvent event) {
        System.out.println("Feature enabled changed from " + 
                          event.getOldValue() + " to " + event.getNewValue());
    }
}

2.6 生产者方法(Producer Methods)

2.6.1 基本生产者方法

@ApplicationScoped
public class ConfigurationProducer {
    
    @Produces
    @ApplicationScoped
    public ObjectMapper createObjectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        mapper.registerModule(new JavaTimeModule());
        return mapper;
    }
    
    @Produces
    @ApplicationScoped
    public RestTemplate createRestTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
        return restTemplate;
    }
    
    @Produces
    @ApplicationScoped
    @Named("systemClock")
    public Clock createSystemClock() {
        return Clock.systemDefaultZone();
    }
    
    @Produces
    @ApplicationScoped
    @Named("utcClock")
    public Clock createUtcClock() {
        return Clock.systemUTC();
    }
}

2.6.2 条件化生产者

@ApplicationScoped
public class ConditionalProducer {
    
    @Produces
    @ApplicationScoped
    public DataSource createDataSource(CacheConfig config) {
        if (config.redis().host() != null) {
            return createRedisDataSource(config.redis());
        } else {
            return createInMemoryDataSource();
        }
    }
    
    private DataSource createRedisDataSource(CacheConfig.RedisConfig redis) {
        // 创建 Redis 数据源
        System.out.println("Creating Redis data source: " + 
                          redis.host() + ":" + redis.port());
        return new RedisDataSource(redis.host(), redis.port());
    }
    
    private DataSource createInMemoryDataSource() {
        // 创建内存数据源
        System.out.println("Creating in-memory data source");
        return new InMemoryDataSource();
    }
    
    // 模拟数据源接口和实现
    public interface DataSource {
        void connect();
        void disconnect();
    }
    
    public static class RedisDataSource implements DataSource {
        private final String host;
        private final int port;
        
        public RedisDataSource(String host, int port) {
            this.host = host;
            this.port = port;
        }
        
        @Override
        public void connect() {
            System.out.println("Connecting to Redis: " + host + ":" + port);
        }
        
        @Override
        public void disconnect() {
            System.out.println("Disconnecting from Redis");
        }
    }
    
    public static class InMemoryDataSource implements DataSource {
        @Override
        public void connect() {
            System.out.println("Connecting to in-memory data source");
        }
        
        @Override
        public void disconnect() {
            System.out.println("Disconnecting from in-memory data source");
        }
    }
}

2.7 事件系统

2.7.1 事件定义和发布

// 事件类
public class UserCreatedEvent {
    private final User user;
    private final LocalDateTime timestamp;
    
    public UserCreatedEvent(User user) {
        this.user = user;
        this.timestamp = LocalDateTime.now();
    }
    
    // Getters
    public User getUser() { return user; }
    public LocalDateTime getTimestamp() { return timestamp; }
}

public class OrderProcessedEvent {
    private final Order order;
    private final String status;
    private final LocalDateTime timestamp;
    
    public OrderProcessedEvent(Order order, String status) {
        this.order = order;
        this.status = status;
        this.timestamp = LocalDateTime.now();
    }
    
    // Getters
    public Order getOrder() { return order; }
    public String getStatus() { return status; }
    public LocalDateTime getTimestamp() { return timestamp; }
}

// 事件发布者
@ApplicationScoped
public class UserService {
    
    @Inject
    Event<UserCreatedEvent> userCreatedEvent;
    
    @Inject
    UserRepository userRepository;
    
    public User createUser(User user) {
        // 保存用户
        User savedUser = userRepository.save(user);
        
        // 发布事件
        userCreatedEvent.fire(new UserCreatedEvent(savedUser));
        
        return savedUser;
    }
}

2.7.2 事件监听

@ApplicationScoped
public class UserEventListener {
    
    @Inject
    @Email
    NotificationService emailService;
    
    @Inject
    AuditService auditService;
    
    // 同步事件监听
    void onUserCreated(@Observes UserCreatedEvent event) {
        System.out.println("User created: " + event.getUser().getName());
        
        // 发送欢迎邮件
        emailService.sendNotification(
            "Welcome " + event.getUser().getName() + "!");
        
        // 记录审计日志
        auditService.logUserCreation(event.getUser());
    }
    
    // 异步事件监听
    void onUserCreatedAsync(@ObservesAsync UserCreatedEvent event) {
        // 异步处理,不阻塞主流程
        try {
            Thread.sleep(1000); // 模拟耗时操作
            System.out.println("Async processing completed for user: " + 
                              event.getUser().getName());
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

@ApplicationScoped
public class OrderEventListener {
    
    @Inject
    InventoryService inventoryService;
    
    @Inject
    @SMS
    NotificationService smsService;
    
    void onOrderProcessed(@Observes OrderProcessedEvent event) {
        Order order = event.getOrder();
        String status = event.getStatus();
        
        System.out.println("Order " + order.getId() + " status: " + status);
        
        if ("COMPLETED".equals(status)) {
            // 更新库存
            inventoryService.updateInventory(order.getItems());
            
            // 发送短信通知
            smsService.sendNotification(
                "Your order " + order.getId() + " has been completed!");
        }
    }
}

2.7.3 条件化事件监听

@ApplicationScoped
public class ConditionalEventListener {
    
    // 只监听特定类型的用户创建事件
    void onVipUserCreated(@Observes UserCreatedEvent event) {
        if ("VIP".equals(event.getUser().getType())) {
            System.out.println("VIP user created: " + event.getUser().getName());
            // VIP 用户特殊处理
        }
    }
    
    // 使用限定符过滤事件
    void onHighValueOrder(@Observes @HighValue OrderProcessedEvent event) {
        System.out.println("High value order processed: " + event.getOrder().getId());
    }
}

// 事件限定符
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
public @interface HighValue {
}

// 发布带限定符的事件
@ApplicationScoped
public class OrderService {
    
    @Inject
    Event<OrderProcessedEvent> orderEvent;
    
    @Inject
    @HighValue
    Event<OrderProcessedEvent> highValueOrderEvent;
    
    public void processOrder(Order order) {
        // 处理订单逻辑
        
        if (order.getTotal().compareTo(BigDecimal.valueOf(1000)) > 0) {
            // 高价值订单
            highValueOrderEvent.fire(new OrderProcessedEvent(order, "COMPLETED"));
        } else {
            // 普通订单
            orderEvent.fire(new OrderProcessedEvent(order, "COMPLETED"));
        }
    }
}

2.8 实践练习

2.8.1 练习1:创建用户管理系统

创建一个完整的用户管理系统,包含以下组件:

// 用户实体
public class User {
    private Long id;
    private String name;
    private String email;
    private String type; // NORMAL, VIP
    private LocalDateTime createdAt;
    
    // 构造器、getter、setter
    public User() {}
    
    public User(Long id, String name, String email, String type) {
        this.id = id;
        this.name = name;
        this.email = email;
        this.type = type;
        this.createdAt = LocalDateTime.now();
    }
    
    // Getters and Setters
    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 getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    
    public String getType() { return type; }
    public void setType(String type) { this.type = type; }
    
    public LocalDateTime getCreatedAt() { return createdAt; }
    public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
}

// 用户仓库
public interface UserRepository {
    User save(User user);
    User findById(Long id);
    List<User> findAll();
    void deleteById(Long id);
}

@ApplicationScoped
public class InMemoryUserRepository implements UserRepository {
    
    private final Map<Long, User> users = new ConcurrentHashMap<>();
    private final AtomicLong idGenerator = new AtomicLong(1);
    
    @Override
    public User save(User user) {
        if (user.getId() == null) {
            user.setId(idGenerator.getAndIncrement());
        }
        users.put(user.getId(), user);
        return user;
    }
    
    @Override
    public User findById(Long id) {
        return users.get(id);
    }
    
    @Override
    public List<User> findAll() {
        return new ArrayList<>(users.values());
    }
    
    @Override
    public void deleteById(Long id) {
        users.remove(id);
    }
}

// 审计服务
@ApplicationScoped
public class AuditService {
    
    public void logUserCreation(User user) {
        System.out.println("AUDIT: User created - ID: " + user.getId() + 
                          ", Name: " + user.getName() + 
                          ", Time: " + LocalDateTime.now());
    }
    
    public void logUserDeletion(Long userId) {
        System.out.println("AUDIT: User deleted - ID: " + userId + 
                          ", Time: " + LocalDateTime.now());
    }
}

2.8.2 练习2:配置驱动的功能开关

// 功能开关配置
@ConfigMapping(prefix = "features")
public interface FeatureConfig {
    
    @WithDefault("true")
    boolean userRegistration();
    
    @WithDefault("false")
    boolean advancedSearch();
    
    @WithDefault("true")
    boolean emailNotifications();
    
    @WithDefault("false")
    boolean smsNotifications();
    
    RateLimitConfig rateLimit();
    
    interface RateLimitConfig {
        @WithDefault("100")
        int requestsPerMinute();
        
        @WithDefault("true")
        boolean enabled();
    }
}

// 功能开关服务
@ApplicationScoped
public class FeatureToggleService {
    
    private final FeatureConfig config;
    
    public FeatureToggleService(FeatureConfig config) {
        this.config = config;
    }
    
    public boolean isUserRegistrationEnabled() {
        return config.userRegistration();
    }
    
    public boolean isAdvancedSearchEnabled() {
        return config.advancedSearch();
    }
    
    public boolean isEmailNotificationsEnabled() {
        return config.emailNotifications();
    }
    
    public boolean isSmsNotificationsEnabled() {
        return config.smsNotifications();
    }
    
    public boolean isRateLimitEnabled() {
        return config.rateLimit().enabled();
    }
    
    public int getRateLimitRequestsPerMinute() {
        return config.rateLimit().requestsPerMinute();
    }
}

2.8.3 练习3:多环境配置管理

# application.properties
features.user-registration=true
features.advanced-search=false
features.email-notifications=true
features.sms-notifications=false
features.rate-limit.enabled=true
features.rate-limit.requests-per-minute=100

# application-dev.properties
features.advanced-search=true
features.sms-notifications=true
features.rate-limit.requests-per-minute=1000

# application-prod.properties
features.advanced-search=true
features.rate-limit.requests-per-minute=50

2.9 本章小结

2.9.1 核心概念回顾

  1. CDI 基础

    • Bean 的定义和发现
    • 依赖注入模式
    • Bean 作用域管理
    • 生命周期回调
  2. 限定符系统

    • 自定义限定符
    • 参数化限定符
    • 多实现选择
  3. 配置管理

    • 配置属性注入
    • 配置对象映射
    • 环境特定配置
    • 动态配置更新
  4. 生产者方法

    • Bean 创建定制
    • 条件化生产
    • 第三方库集成
  5. 事件系统

    • 事件发布和监听
    • 同步和异步处理
    • 条件化事件处理

2.9.2 技术要点

  • 类型安全: CDI 提供编译时类型检查
  • 松耦合: 通过接口和限定符实现组件解耦
  • 可测试性: 依赖注入便于单元测试
  • 配置外部化: 配置与代码分离
  • 事件驱动: 异步处理和系统解耦

2.9.3 最佳实践

  1. 依赖注入

    • 优先使用构造器注入
    • 避免循环依赖
    • 合理选择 Bean 作用域
  2. 配置管理

    • 使用配置映射接口
    • 提供合理的默认值
    • 支持多环境配置
  3. 事件系统

    • 保持事件的简单性
    • 合理使用异步处理
    • 避免事件链过长

2.9.4 下一章预告

下一章我们将学习 RESTful Web 服务开发,包括: - JAX-RS 基础和注解 - 请求和响应处理 - 内容协商和序列化 - 异常处理和验证 - OpenAPI 文档生成


恭喜! 🎉 您已经掌握了 Quarkus 的依赖注入和配置管理核心概念。继续下一章的学习,开始构建 RESTful Web 服务!