Administrator
发布于 2026-03-16 / 0 阅读
0
0

Java核心编程与设计模式实战指南

# Java核心编程与设计模式实战指南

> 🎯 从基础到进阶:网络编程 + Stream流 + AOP + 注解 + 设计模式  
> 涵盖:企业级实战场景、代码示例、最佳实践

---

## 📚 目录

1. [网络编程实战](#一网络编程实战)
2. [Stream流式编程](#二stream流式编程)
3. [AOP切面编程](#三aop切面编程)
4. [Spring Boot常用注解](#四spring-boot常用注解)
5. [自定义注解实战](#五自定义注解实战)
6. [设计模式在项目中的应用](#六设计模式在项目中的应用)
7. [其他重要知识点](#七其他重要知识点)

---

# 一、网络编程实战

## 1.1 BIO vs NIO vs AIO

| 模型 | 说明 | 适用场景 | 代表框架 |
|------|------|---------|---------|
| **BIO** | 同步阻塞,一个连接一个线程 | 连接数少 | 传统Socket |
| **NIO** | 同步非阻塞,多路复用 | 高并发、长连接 | Netty |
| **AIO** | 异步非阻塞 | Linux下性能不如NIO | - |

## 1.2 HTTP客户端实战

**场景:调用第三方API(支付、短信、物流)**

### 方式1:RestTemplate(Spring传统方式)

```java
@Configuration
public class RestTemplateConfig {
    
    @Bean
    public RestTemplate restTemplate() {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setConnectTimeout(5000);  // 连接超时5秒
        factory.setReadTimeout(10000);    // 读超时10秒
        
        RestTemplate restTemplate = new RestTemplate(factory);
        
        // 添加拦截器(统一处理)
        restTemplate.setInterceptors(Collections.singletonList(
            new ClientHttpRequestInterceptor() {
                @Override
                public ClientHttpResponse intercept(HttpRequest request, 
                                                   byte[] body, 
                                                   ClientHttpRequestExecution execution) throws IOException {
                    // 打印请求日志
                    log.info("Request: {} {}", request.getMethod(), request.getURI());
                    
                    // 统一添加Header
                    request.getHeaders().add("User-Agent", "MyApp/1.0");
                    
                    long start = System.currentTimeMillis();
                    ClientHttpResponse response = execution.execute(request, body);
                    long cost = System.currentTimeMillis() - start;
                    
                    log.info("Response: status={}, cost={}ms", response.getStatusCode(), cost);
                    return response;
                }
            }
        ));
        
        return restTemplate;
    }
}

/**
 * 调用第三方支付接口
 */
@Service
@Slf4j
public class PaymentHttpClient {
    
    @Autowired
    private RestTemplate restTemplate;
    
    /**
     * GET请求
     */
    public String queryOrder(String orderNo) {
        String url = "https://api.payment.com/order/{orderNo}";
        
        try {
            ResponseEntity<String> response = restTemplate.getForEntity(
                url, 
                String.class, 
                orderNo
            );
            
            if (response.getStatusCode() == HttpStatus.OK) {
                return response.getBody();
            }
            
            log.error("查询订单失败: status={}", response.getStatusCode());
            return null;
            
        } catch (RestClientException e) {
            log.error("调用支付接口异常", e);
            throw new BusinessException("查询订单失败");
        }
    }
    
    /**
     * POST请求(JSON)
     */
    public PaymentResponse createPayment(PaymentRequest request) {
        String url = "https://api.payment.com/pay";
        
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("Authorization", "Bearer " + getToken());
        
        HttpEntity<PaymentRequest> entity = new HttpEntity<>(request, headers);
        
        try {
            ResponseEntity<PaymentResponse> response = restTemplate.postForEntity(
                url, 
                entity, 
                PaymentResponse.class
            );
            
            return response.getBody();
            
        } catch (HttpClientErrorException e) {
            // 4xx错误
            log.error("客户端错误: status={}, body={}", 
                e.getStatusCode(), e.getResponseBodyAsString());
            throw new BusinessException("支付请求参数错误");
            
        } catch (HttpServerErrorException e) {
            // 5xx错误
            log.error("服务端错误: status={}", e.getStatusCode());
            throw new BusinessException("支付服务异常");
        }
    }
}
```

### 方式2:OkHttp(推荐)

```java
@Configuration
public class OkHttpConfig {
    
    @Bean
    public OkHttpClient okHttpClient() {
        return new OkHttpClient.Builder()
            .connectTimeout(5, TimeUnit.SECONDS)
            .readTimeout(10, TimeUnit.SECONDS)
            .writeTimeout(10, TimeUnit.SECONDS)
            // 连接池
            .connectionPool(new ConnectionPool(10, 5, TimeUnit.MINUTES))
            // 重试
            .retryOnConnectionFailure(true)
            // 拦截器
            .addInterceptor(new LoggingInterceptor())
            .build();
    }
}

/**
 * OkHttp调用示例
 */
@Service
@Slf4j
public class OkHttpService {
    
    @Autowired
    private OkHttpClient okHttpClient;
    
    @Autowired
    private ObjectMapper objectMapper;
    
    /**
     * GET请求
     */
    public String get(String url) throws IOException {
        Request request = new Request.Builder()
            .url(url)
            .get()
            .build();
        
        try (Response response = okHttpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("请求失败: " + response);
            }
            return response.body().string();
        }
    }
    
    /**
     * POST JSON
     */
    public <T> T postJson(String url, Object requestBody, Class<T> responseType) throws IOException {
        String json = objectMapper.writeValueAsString(requestBody);
        
        RequestBody body = RequestBody.create(
            json, 
            MediaType.get("application/json; charset=utf-8")
        );
        
        Request request = new Request.Builder()
            .url(url)
            .post(body)
            .build();
        
        try (Response response = okHttpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("请求失败: " + response);
            }
            
            String responseBody = response.body().string();
            return objectMapper.readValue(responseBody, responseType);
        }
    }
}
```

### 方式3:WebClient(Spring WebFlux,异步)

```java
@Configuration
public class WebClientConfig {
    
    @Bean
    public WebClient webClient() {
        return WebClient.builder()
            .baseUrl("https://api.payment.com")
            .defaultHeader("User-Agent", "MyApp/1.0")
            .filter(ExchangeFilterFunction.ofRequestProcessor(
                request -> {
                    log.info("Request: {} {}", request.method(), request.url());
                    return Mono.just(request);
                }
            ))
            .build();
    }
}

/**
 * WebClient异步调用
 */
@Service
public class WebClientService {
    
    @Autowired
    private WebClient webClient;
    
    /**
     * 异步GET
     */
    public Mono<String> getAsync(String uri) {
        return webClient.get()
            .uri(uri)
            .retrieve()
            .bodyToMono(String.class);
    }
    
    /**
     * 异步POST
     */
    public Mono<PaymentResponse> postAsync(PaymentRequest request) {
        return webClient.post()
            .uri("/pay")
            .contentType(MediaType.APPLICATION_JSON)
            .bodyValue(request)
            .retrieve()
            .bodyToMono(PaymentResponse.class);
    }
    
    /**
     * 批量并发请求
     */
    public Flux<Order> batchQuery(List<String> orderNos) {
        return Flux.fromIterable(orderNos)
            .flatMap(orderNo -> 
                webClient.get()
                    .uri("/order/{orderNo}", orderNo)
                    .retrieve()
                    .bodyToMono(Order.class)
            )
            .onErrorContinue((error, orderNo) -> {
                log.error("查询订单失败: orderNo={}", orderNo, error);
            });
    }
}
```

## 1.3 WebSocket实战

**场景:实时推送(订单状态、消息通知)**

```java
/**
 * WebSocket配置
 */
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    
    @Autowired
    private OrderWebSocketHandler orderHandler;
    
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(orderHandler, "/ws/order")
            .setAllowedOrigins("*");  // 生产环境要配置具体域名
    }
}

/**
 * WebSocket处理器
 */
@Component
@Slf4j
public class OrderWebSocketHandler extends TextWebSocketHandler {
    
    // 存储连接(用户ID -> WebSocket会话)
    private static final ConcurrentHashMap<Long, WebSocketSession> SESSIONS = new ConcurrentHashMap<>();
    
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        // 从URL获取用户ID
        Long userId = getUserId(session);
        SESSIONS.put(userId, session);
        log.info("WebSocket连接建立: userId={}", userId);
    }
    
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        log.info("收到消息: {}", message.getPayload());
        
        // 回复消息
        session.sendMessage(new TextMessage("收到: " + message.getPayload()));
    }
    
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        Long userId = getUserId(session);
        SESSIONS.remove(userId);
        log.info("WebSocket连接关闭: userId={}", userId);
    }
    
    /**
     * 推送订单状态给指定用户
     */
    public void pushOrderStatus(Long userId, OrderStatusDTO status) {
        WebSocketSession session = SESSIONS.get(userId);
        if (session != null && session.isOpen()) {
            try {
                String json = new ObjectMapper().writeValueAsString(status);
                session.sendMessage(new TextMessage(json));
            } catch (Exception e) {
                log.error("推送消息失败", e);
            }
        }
    }
    
    /**
     * 广播消息给所有在线用户
     */
    public void broadcast(String message) {
        SESSIONS.values().forEach(session -> {
            if (session.isOpen()) {
                try {
                    session.sendMessage(new TextMessage(message));
                } catch (Exception e) {
                    log.error("广播消息失败", e);
                }
            }
        });
    }
    
    private Long getUserId(WebSocketSession session) {
        // 从URL或Header中获取用户ID
        return 1L; // 示例
    }
}
```

---

# 二、Stream流式编程

## 2.1 基础操作

```java
@Service
public class StreamBasicService {
    
    /**
     * 场景1:过滤 + 映射 + 收集
     * 
     * 需求:查询所有已支付订单的订单号列表
     */
    public List<String> getOrderNos(List<Order> orders) {
        return orders.stream()
            .filter(order -> order.getStatus() == 1)  // 过滤已支付
            .map(Order::getOrderNo)                   // 提取订单号
            .collect(Collectors.toList());            // 收集为List
    }
    
    /**
     * 场景2:去重
     * 
     * 需求:获取所有订单中的唯一用户ID
     */
    public Set<Long> getUniqueUserIds(List<Order> orders) {
        return orders.stream()
            .map(Order::getUserId)
            .collect(Collectors.toSet());  // 自动去重
    }
    
    /**
     * 场景3:排序
     * 
     * 需求:按金额降序排列订单
     */
    public List<Order> sortByAmount(List<Order> orders) {
        return orders.stream()
            .sorted(Comparator.comparing(Order::getTotalAmount).reversed())
            .collect(Collectors.toList());
    }
    
    /**
     * 场景4:分页
     * 
     * 需求:获取前10条订单
     */
    public List<Order> getTop10(List<Order> orders) {
        return orders.stream()
            .limit(10)
            .collect(Collectors.toList());
    }
}
```

## 2.2 高级操作

```java
@Service
public class StreamAdvancedService {
    
    /**
     * 场景1:分组
     * 
     * 需求:按状态分组订单
     * 结果:Map<Integer, List<Order>>
     */
    public Map<Integer, List<Order>> groupByStatus(List<Order> orders) {
        return orders.stream()
            .collect(Collectors.groupingBy(Order::getStatus));
    }
    
    /**
     * 场景2:分组统计
     * 
     * 需求:统计每个用户的订单总金额
     * 结果:Map<Long, BigDecimal>
     */
    public Map<Long, BigDecimal> sumAmountByUser(List<Order> orders) {
        return orders.stream()
            .collect(Collectors.groupingBy(
                Order::getUserId,
                Collectors.reducing(
                    BigDecimal.ZERO,
                    Order::getTotalAmount,
                    BigDecimal::add
                )
            ));
    }
    
    /**
     * 场景3:分组计数
     * 
     * 需求:统计每个状态的订单数量
     * 结果:Map<Integer, Long>
     */
    public Map<Integer, Long> countByStatus(List<Order> orders) {
        return orders.stream()
            .collect(Collectors.groupingBy(
                Order::getStatus,
                Collectors.counting()
            ));
    }
    
    /**
     * 场景4:分区(二分类)
     * 
     * 需求:将订单分为大额订单和普通订单
     * 结果:Map<Boolean, List<Order>>
     */
    public Map<Boolean, List<Order>> partitionByAmount(List<Order> orders) {
        return orders.stream()
            .collect(Collectors.partitioningBy(
                order -> order.getTotalAmount().compareTo(new BigDecimal("1000")) > 0
            ));
    }
    
    /**
     * 场景5:拼接字符串
     * 
     * 需求:将所有订单号用逗号拼接
     * 结果:"O001,O002,O003"
     */
    public String joinOrderNos(List<Order> orders) {
        return orders.stream()
            .map(Order::getOrderNo)
            .collect(Collectors.joining(","));
    }
    
    /**
     * 场景6:flatMap(扁平化)
     * 
     * 需求:获取所有订单的所有商品ID
     */
    public List<Long> getAllProductIds(List<Order> orders) {
        return orders.stream()
            .flatMap(order -> order.getItems().stream())  // 扁平化
            .map(OrderItem::getProductId)
            .distinct()
            .collect(Collectors.toList());
    }
    
    /**
     * 场景7:多条件过滤
     * 
     * 需求:查询已支付且金额>1000的订单
     */
    public List<Order> complexFilter(List<Order> orders) {
        return orders.stream()
            .filter(order -> order.getStatus() == 1)
            .filter(order -> order.getTotalAmount().compareTo(new BigDecimal("1000")) > 0)
            .collect(Collectors.toList());
    }
    
    /**
     * 场景8:peek(调试)
     * 
     * 需求:在处理过程中打印日志
     */
    public List<String> processWithLog(List<Order> orders) {
        return orders.stream()
            .filter(order -> order.getStatus() == 1)
            .peek(order -> log.info("处理订单: {}", order.getOrderNo()))
            .map(Order::getOrderNo)
            .peek(orderNo -> log.info("订单号: {}", orderNo))
            .collect(Collectors.toList());
    }
}
```

## 2.3 实战案例:订单统计报表

```java
@Service
public class OrderStatisticsService {
    
    /**
     * 复杂统计报表
     * 
     * 需求:
     * 1. 按日期分组
     * 2. 统计每天的订单数、总金额、平均金额
     */
    public List<OrderStatisticsVO> dailyStatistics(List<Order> orders) {
        Map<LocalDate, List<Order>> dateMap = orders.stream()
            .collect(Collectors.groupingBy(
                order -> order.getCreateTime().toLocalDate()
            ));
        
        return dateMap.entrySet().stream()
            .map(entry -> {
                LocalDate date = entry.getKey();
                List<Order> dayOrders = entry.getValue();
                
                OrderStatisticsVO vo = new OrderStatisticsVO();
                vo.setDate(date);
                vo.setOrderCount(dayOrders.size());
                
                // 总金额
                BigDecimal totalAmount = dayOrders.stream()
                    .map(Order::getTotalAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                vo.setTotalAmount(totalAmount);
                
                // 平均金额
                BigDecimal avgAmount = totalAmount.divide(
                    new BigDecimal(dayOrders.size()),
                    2,
                    RoundingMode.HALF_UP
                );
                vo.setAvgAmount(avgAmount);
                
                return vo;
            })
            .sorted(Comparator.comparing(OrderStatisticsVO::getDate))
            .collect(Collectors.toList());
    }
    
    /**
     * 找出Top N用户
     */
    public List<UserOrderStatVO> topUsers(List<Order> orders, int topN) {
        return orders.stream()
            .collect(Collectors.groupingBy(
                Order::getUserId,
                Collectors.collectingAndThen(
                    Collectors.toList(),
                    orderList -> {
                        UserOrderStatVO vo = new UserOrderStatVO();
                        vo.setUserId(orderList.get(0).getUserId());
                        vo.setOrderCount(orderList.size());
                        vo.setTotalAmount(
                            orderList.stream()
                                .map(Order::getTotalAmount)
                                .reduce(BigDecimal.ZERO, BigDecimal::add)
                        );
                        return vo;
                    }
                )
            ))
            .values().stream()
            .sorted(Comparator.comparing(UserOrderStatVO::getTotalAmount).reversed())
            .limit(topN)
            .collect(Collectors.toList());
    }
}
```

---

# 三、AOP切面编程

## 3.1 AOP核心概念

```
切面(Aspect):横切关注点的模块化
连接点(JoinPoint):程序执行的某个点(方法调用)
切入点(Pointcut):匹配连接点的表达式
通知(Advice):切面在特定连接点执行的动作
  - Before:方法前
  - After:方法后
  - AfterReturning:方法返回后
  - AfterThrowing:方法抛异常后
  - Around:方法前后
```

## 3.2 切入点表达式

```java
// 1. 匹配指定包下所有类的所有方法
@Pointcut("execution(* cn.ufood.fny.mall.service.*.*(..))")

// 2. 匹配指定类的所有方法
@Pointcut("execution(* cn.ufood.fny.mall.service.OrderService.*(..))")

// 3. 匹配指定方法
@Pointcut("execution(* cn.ufood.fny.mall.service.OrderService.createOrder(..))")

// 4. 匹配带有指定注解的方法
@Pointcut("@annotation(cn.ufood.fny.mall.annotation.Log)")

// 5. 匹配指定包及子包
@Pointcut("execution(* cn.ufood.fny.mall.service..*.*(..))")

// 6. 组合表达式
@Pointcut("execution(* cn.ufood.fny.mall.service..*.*(..)) && @annotation(log)")
```

## 3.3 实战场景1:操作日志记录

```java
/**
 * 操作日志注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperationLog {
    
    /**
     * 操作模块
     */
    String module() default "";
    
    /**
     * 操作类型
     */
    OperationType type() default OperationType.OTHER;
    
    /**
     * 操作描述(支持SpEL表达式)
     */
    String description() default "";
}

/**
 * 操作日志切面
 */
@Aspect
@Component
@Slf4j
public class OperationLogAspect {
    
    @Autowired
    private OperationLogService operationLogService;
    
    @Pointcut("@annotation(cn.ufood.fny.mall.annotation.OperationLog)")
    public void logPointcut() {}
    
    @Around("logPointcut() && @annotation(operationLog)")
    public Object around(ProceedingJoinPoint joinPoint, OperationLog operationLog) throws Throwable {
        long startTime = System.currentTimeMillis();
        
        // 构建日志对象
        OperationLogEntity logEntity = new OperationLogEntity();
        logEntity.setModule(operationLog.module());
        logEntity.setType(operationLog.type());
        logEntity.setDescription(parseDescription(operationLog.description(), joinPoint));
        
        // 获取请求信息
        HttpServletRequest request = getRequest();
        if (request != null) {
            logEntity.setRequestUrl(request.getRequestURI());
            logEntity.setRequestMethod(request.getMethod());
            logEntity.setIp(getIpAddress(request));
        }
        
        // 获取方法信息
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        logEntity.setMethod(signature.getDeclaringTypeName() + "." + signature.getName());
        logEntity.setParams(JSON.toJSONString(joinPoint.getArgs()));
        
        // 获取用户信息
        Long userId = UserContext.getCurrentUserId();
        logEntity.setUserId(userId);
        
        Object result = null;
        try {
            // 执行方法
            result = joinPoint.proceed();
            
            logEntity.setStatus(1);  // 成功
            logEntity.setResult(JSON.toJSONString(result));
            
        } catch (Throwable e) {
            logEntity.setStatus(0);  // 失败
            logEntity.setErrorMsg(e.getMessage());
            throw e;
            
        } finally {
            long costTime = System.currentTimeMillis() - startTime;
            logEntity.setCostTime(costTime);
            logEntity.setCreateTime(new Date());
            
            // 异步保存日志
            operationLogService.saveAsync(logEntity);
        }
        
        return result;
    }
    
    /**
     * 解析描述(支持SpEL表达式)
     * 
     * 例如:@OperationLog(description = "创建订单,订单号:#{#orderNo}")
     */
    private String parseDescription(String description, ProceedingJoinPoint joinPoint) {
        if (!description.contains("#{")) {
            return description;
        }
        
        // 使用SpEL解析
        ExpressionParser parser = new SpelExpressionParser();
        EvaluationContext context = new StandardEvaluationContext();
        
        // 获取方法参数
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String[] paramNames = signature.getParameterNames();
        Object[] args = joinPoint.getArgs();
        
        for (int i = 0; i < paramNames.length; i++) {
            context.setVariable(paramNames[i], args[i]);
        }
        
        return parser.parseExpression(description, new TemplateParserContext()).getValue(context, String.class);
    }
}

// 使用示例
@Service
public class OrderService {
    
    @OperationLog(
        module = "订单管理",
        type = OperationType.INSERT,
        description = "创建订单,订单号:#{#order.orderNo}"
    )
    public void createOrder(Order order) {
        // 业务逻辑
    }
    
    @OperationLog(
        module = "订单管理",
        type = OperationType.UPDATE,
        description = "取消订单,订单号:#{#orderNo}"
    )
    public void cancelOrder(String orderNo) {
        // 业务逻辑
    }
}
```

## 3.4 实战场景2:防重复提交

```java
/**
 * 防重复提交注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PreventDuplicateSubmit {
    
    /**
     * 锁定时间(秒)
     */
    int lockTime() default 3;
    
    /**
     * 提示信息
     */
    String message() default "请勿重复提交";
}

/**
 * 防重复提交切面
 */
@Aspect
@Component
@Slf4j
public class PreventDuplicateSubmitAspect {
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    @Around("@annotation(preventDuplicateSubmit)")
    public Object around(ProceedingJoinPoint joinPoint, PreventDuplicateSubmit preventDuplicateSubmit) throws Throwable {
        // 生成唯一key:用户ID + 方法签名
        Long userId = UserContext.getCurrentUserId();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String methodName = signature.getDeclaringTypeName() + "." + signature.getName();
        
        String key = "duplicate:submit:" + userId + ":" + methodName;
        
        // 尝试获取锁
        Boolean success = redisTemplate.opsForValue().setIfAbsent(
            key, 
            "1", 
            preventDuplicateSubmit.lockTime(), 
            TimeUnit.SECONDS
        );
        
        if (Boolean.FALSE.equals(success)) {
            log.warn("重复提交: userId={}, method={}", userId, methodName);
            throw new BusinessException(preventDuplicateSubmit.message());
        }
        
        try {
            return joinPoint.proceed();
        } finally {
            // 方法执行完成,删除锁(可选)
            // redisTemplate.delete(key);
        }
    }
}

// 使用示例
@PostMapping("/order")
@PreventDuplicateSubmit(lockTime = 5, message = "订单提交中,请勿重复提交")
public Result createOrder(@RequestBody OrderCreateRequest request) {
    orderService.createOrder(request);
    return Result.success();
}
```

## 3.5 实战场景3:性能监控

```java
/**
 * 性能监控切面
 */
@Aspect
@Component
@Slf4j
public class PerformanceMonitorAspect {
    
    /**
     * 监控Service层所有方法
     */
    @Around("execution(* cn.ufood.fny.mall.service..*.*(..))")
    public Object monitor(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String methodName = signature.getDeclaringTypeName() + "." + signature.getName();
        
        long startTime = System.currentTimeMillis();
        Object result = null;
        
        try {
            result = joinPoint.proceed();
            return result;
            
        } finally {
            long costTime = System.currentTimeMillis() - startTime;
            
            // 超过1秒打印警告
            if (costTime > 1000) {
                log.warn("慢方法: method={}, costTime={}ms", methodName, costTime);
            } else {
                log.debug("方法耗时: method={}, costTime={}ms", methodName, costTime);
            }
            
            // 上报到监控系统(Prometheus、Skywalking等)
            reportMetrics(methodName, costTime);
        }
    }
}
```

---

# 四、Spring Boot常用注解

## 4.1 核心注解

```java
/**
 * 1. @SpringBootApplication
 * 
 * 组合注解,包含:
 * - @SpringBootConfiguration:表明这是一个配置类
 * - @EnableAutoConfiguration:启用自动配置
 * - @ComponentScan:组件扫描
 */
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

/**
 * 2. @Configuration + @Bean
 * 
 * 配置类,替代XML配置
 */
@Configuration
public class AppConfig {
    
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    
    @Bean
    @ConditionalOnMissingBean  // 只有不存在时才创建
    public RedisTemplate<String, Object> redisTemplate() {
        // ...
    }
}

/**
 * 3. @Component、@Service、@Repository、@Controller
 * 
 * 组件注解,交给Spring管理
 */
@Service  // 业务层
public class OrderService {}

@Repository  // 数据访问层
public class OrderMapper {}

@Controller  // 控制层
public class OrderController {}

@Component  // 通用组件
public class MessageSender {}

/**
 * 4. @Autowired、@Resource、@Inject
 * 
 * 依赖注入
 */
@Service
public class OrderService {
    
    // 推荐:构造器注入
    private final OrderMapper orderMapper;
    
    @Autowired
    public OrderService(OrderMapper orderMapper) {
        this.orderMapper = orderMapper;
    }
    
    // 或者:字段注入(简单但不推荐)
    @Autowired
    private UserService userService;
    
    // 或者:@Resource(按名称注入)
    @Resource(name = "orderMapper")
    private OrderMapper mapper;
}

/**
 * 5. @Value、@ConfigurationProperties
 * 
 * 读取配置
 */
@Component
public class AppProperties {
    
    // 单个属性
    @Value("${app.name}")
    private String appName;
    
    // 默认值
    @Value("${app.version:1.0}")
    private String appVersion;
    
    // SpEL表达式
    @Value("#{systemProperties['user.name']}")
    private String userName;
}

@Component
@ConfigurationProperties(prefix = "app")
@Data
public class AppConfig {
    private String name;
    private String version;
    private Map<String, String> properties;
}

/**
 * 6. @Conditional系列
 * 
 * 条件注解
 */
@Configuration
public class ConditionalConfig {
    
    @Bean
    @ConditionalOnProperty(name = "feature.enabled", havingValue = "true")
    public FeatureService featureService() {
        return new FeatureService();
    }
    
    @Bean
    @ConditionalOnClass(name = "com.mysql.cj.jdbc.Driver")
    public DataSource mysqlDataSource() {
        // ...
    }
    
    @Bean
    @ConditionalOnMissingBean
    public CacheManager cacheManager() {
        // ...
    }
}
```

## 4.2 Web注解

```java
@RestController  // @Controller + @ResponseBody
@RequestMapping("/api/order")
public class OrderController {
    
    /**
     * GET请求
     */
    @GetMapping("/{id}")
    public Result<Order> getOrder(@PathVariable Long id) {
        return Result.success(orderService.getById(id));
    }
    
    /**
     * POST请求
     */
    @PostMapping
    public Result createOrder(@RequestBody @Valid OrderCreateRequest request) {
        orderService.createOrder(request);
        return Result.success();
    }
    
    /**
     * PUT请求
     */
    @PutMapping("/{id}")
    public Result updateOrder(
        @PathVariable Long id,
        @RequestBody OrderUpdateRequest request
    ) {
        orderService.updateOrder(id, request);
        return Result.success();
    }
    
    /**
     * DELETE请求
     */
    @DeleteMapping("/{id}")
    public Result deleteOrder(@PathVariable Long id) {
        orderService.deleteOrder(id);
        return Result.success();
    }
    
    /**
     * 多个参数
     */
    @GetMapping("/list")
    public Result<Page<Order>> listOrders(
        @RequestParam(required = false) Integer status,
        @RequestParam(defaultValue = "1") Integer pageNum,
        @RequestParam(defaultValue = "10") Integer pageSize
    ) {
        Page<Order> page = orderService.listOrders(status, pageNum, pageSize);
        return Result.success(page);
    }
    
    /**
     * 获取Header
     */
    @GetMapping("/info")
    public Result getInfo(@RequestHeader("User-Agent") String userAgent) {
        return Result.success(userAgent);
    }
}
```

## 4.3 数据校验注解

```java
@Data
public class OrderCreateRequest {
    
    @NotNull(message = "用户ID不能为空")
    private Long userId;
    
    @NotBlank(message = "收货地址不能为空")
    @Length(max = 200, message = "地址长度不能超过200")
    private String address;
    
    @NotBlank(message = "手机号不能为空")
    @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
    private String phone;
    
    @NotEmpty(message = "商品列表不能为空")
    @Size(min = 1, max = 20, message = "商品数量必须在1-20之间")
    private List<OrderItemRequest> items;
    
    @DecimalMin(value = "0.01", message = "金额必须大于0")
    @DecimalMax(value = "999999.99", message = "金额不能超过999999.99")
    private BigDecimal totalAmount;
    
    @Email(message = "邮箱格式不正确")
    private String email;
    
    @Past(message = "日期必须是过去的时间")
    private Date birthday;
}

// 使用
@PostMapping
public Result createOrder(@RequestBody @Valid OrderCreateRequest request) {
    // 如果校验失败,会自动抛出MethodArgumentNotValidException
    orderService.createOrder(request);
    return Result.success();
}
```

---

# 五、自定义注解实战

## 5.1 实战场景1:接口限流

```java
/**
 * 限流注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RateLimit {
    
    /**
     * 限流key(支持SpEL)
     */
    String key() default "";
    
    /**
     * 时间窗口(秒)
     */
    int time() default 60;
    
    /**
     * 最大请求数
     */
    int count() default 100;
    
    /**
     * 限流类型
     */
    LimitType limitType() default LimitType.DEFAULT;
}

public enum LimitType {
    DEFAULT,  // 默认策略(全局)
    IP,       // 按IP限流
    USER      // 按用户限流
}

/**
 * 限流切面
 */
@Aspect
@Component
@Slf4j
public class RateLimitAspect {
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    @Around("@annotation(rateLimit)")
    public Object around(ProceedingJoinPoint joinPoint, RateLimit rateLimit) throws Throwable {
        String key = generateKey(joinPoint, rateLimit);
        
        // Lua脚本实现限流(原子性)
        String luaScript = 
            "local key = KEYS[1] " +
            "local count = tonumber(ARGV[1]) " +
            "local time = tonumber(ARGV[2]) " +
            "local current = redis.call('get', key) " +
            "if current and tonumber(current) >= count then " +
            "    return 0 " +
            "end " +
            "current = redis.call('incr', key) " +
            "if tonumber(current) == 1 then " +
            "    redis.call('expire', key, time) " +
            "end " +
            "return 1";
        
        RedisScript<Long> script = RedisScript.of(luaScript, Long.class);
        Long result = redisTemplate.execute(
            script,
            Collections.singletonList(key),
            String.valueOf(rateLimit.count()),
            String.valueOf(rateLimit.time())
        );
        
        if (result == 0) {
            log.warn("触发限流: key={}", key);
            throw new BusinessException("访问过于频繁,请稍后再试");
        }
        
        return joinPoint.proceed();
    }
    
    private String generateKey(ProceedingJoinPoint joinPoint, RateLimit rateLimit) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String methodName = signature.getDeclaringTypeName() + "." + signature.getName();
        
        StringBuilder keyBuilder = new StringBuilder("rate_limit:");
        
        switch (rateLimit.limitType()) {
            case IP:
                String ip = getIpAddress();
                keyBuilder.append("ip:").append(ip).append(":");
                break;
            case USER:
                Long userId = UserContext.getCurrentUserId();
                keyBuilder.append("user:").append(userId).append(":");
                break;
            default:
                break;
        }
        
        keyBuilder.append(methodName);
        
        if (StrUtil.isNotBlank(rateLimit.key())) {
            keyBuilder.append(":").append(rateLimit.key());
        }
        
        return keyBuilder.toString();
    }
}

// 使用示例
@RestController
public class OrderController {
    
    // 全局限流:每分钟最多100次
    @RateLimit(time = 60, count = 100)
    @GetMapping("/list")
    public Result list() {
        return Result.success();
    }
    
    // 按IP限流:每10秒最多5次
    @RateLimit(time = 10, count = 5, limitType = LimitType.IP)
    @PostMapping("/submit")
    public Result submit() {
        return Result.success();
    }
    
    // 按用户限流:每天最多创建10个订单
    @RateLimit(time = 86400, count = 10, limitType = LimitType.USER)
    @PostMapping("/order")
    public Result createOrder() {
        return Result.success();
    }
}
```

## 5.2 实战场景2:数据权限控制

```java
/**
 * 数据权限注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataPermission {
    
    /**
     * 权限类型
     */
    PermissionType type() default PermissionType.SELF;
    
    /**
     * 部门字段名
     */
    String deptColumn() default "dept_id";
    
    /**
     * 用户字段名
     */
    String userColumn() default "user_id";
}

public enum PermissionType {
    ALL,       // 查看所有
    DEPT,      // 查看本部门
    DEPT_SUB,  // 查看本部门及子部门
    SELF       // 只看自己
}

/**
 * 数据权限切面(通过修改SQL实现)
 */
@Aspect
@Component
public class DataPermissionAspect {
    
    @Around("@annotation(dataPermission)")
    public Object around(ProceedingJoinPoint joinPoint, DataPermission dataPermission) throws Throwable {
        // 获取当前用户信息
        SysUser currentUser = UserContext.getCurrentUser();
        
        // 管理员不限制
        if (currentUser.isAdmin()) {
            return joinPoint.proceed();
        }
        
        // 设置数据权限上下文
        DataPermissionContext context = new DataPermissionContext();
        context.setType(dataPermission.type());
        context.setUserId(currentUser.getId());
        context.setDeptId(currentUser.getDeptId());
        context.setDeptColumn(dataPermission.deptColumn());
        context.setUserColumn(dataPermission.userColumn());
        
        DataPermissionHolder.set(context);
        
        try {
            return joinPoint.proceed();
        } finally {
            DataPermissionHolder.clear();
        }
    }
}

/**
 * MyBatis拦截器(拦截SQL并添加条件)
 */
@Intercepts({
    @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class DataPermissionInterceptor implements Interceptor {
    
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        BoundSql boundSql = statementHandler.getBoundSql();
        String sql = boundSql.getSql();
        
        // 获取数据权限上下文
        DataPermissionContext context = DataPermissionHolder.get();
        if (context == null) {
            return invocation.proceed();
        }
        
        // 修改SQL
        String newSql = appendDataPermissionSql(sql, context);
        
        // 通过反射设置新SQL
        Field field = boundSql.getClass().getDeclaredField("sql");
        field.setAccessible(true);
        field.set(boundSql, newSql);
        
        return invocation.proceed();
    }
    
    private String appendDataPermissionSql(String sql, DataPermissionContext context) {
        StringBuilder condition = new StringBuilder(" AND (");
        
        switch (context.getType()) {
            case SELF:
                condition.append(context.getUserColumn())
                    .append(" = ")
                    .append(context.getUserId());
                break;
            case DEPT:
                condition.append(context.getDeptColumn())
                    .append(" = ")
                    .append(context.getDeptId());
                break;
            case DEPT_SUB:
                // 查询部门及子部门ID
                List<Long> deptIds = getDeptAndSubIds(context.getDeptId());
                condition.append(context.getDeptColumn())
                    .append(" IN (")
                    .append(StringUtils.join(deptIds, ","))
                    .append(")");
                break;
        }
        
        condition.append(")");
        
        // 在WHERE后面添加条件
        return sql.replaceFirst("(?i)WHERE", "WHERE" + condition.toString());
    }
}

// 使用示例
@Service
public class OrderService {
    
    // 只能查看自己的订单
    @DataPermission(type = PermissionType.SELF, userColumn = "user_id")
    public List<Order> getMyOrders() {
        return orderMapper.selectList(null);
        // 自动添加条件:WHERE user_id = 当前用户ID
    }
    
    // 部门经理可以查看本部门所有订单
    @DataPermission(type = PermissionType.DEPT, deptColumn = "dept_id")
    public List<Order> getDeptOrders() {
        return orderMapper.selectList(null);
        // 自动添加条件:WHERE dept_id = 当前部门ID
    }
}
```

---

# 六、设计模式在项目中的应用

## 6.1 策略模式(支付方式)

**场景:支持多种支付方式(微信、支付宝、银行卡)**

```java
/**
 * 支付策略接口
 */
public interface PayStrategy {
    
    /**
     * 支付方式类型
     */
    String getType();
    
    /**
     * 创建支付订单
     */
    PayResult pay(PayRequest request);
    
    /**
     * 查询支付结果
     */
    PayResult query(String orderNo);
}

/**
 * 微信支付策略
 */
@Service
public class WxPayStrategy implements PayStrategy {
    
    @Override
    public String getType() {
        return "WECHAT";
    }
    
    @Override
    public PayResult pay(PayRequest request) {
        // 调用微信支付API
        return new PayResult();
    }
    
    @Override
    public PayResult query(String orderNo) {
        // 查询微信支付结果
        return new PayResult();
    }
}

/**
 * 支付宝支付策略
 */
@Service
public class AliPayStrategy implements PayStrategy {
    
    @Override
    public String getType() {
        return "ALIPAY";
    }
    
    @Override
    public PayResult pay(PayRequest request) {
        // 调用支付宝API
        return new PayResult();
    }
    
    @Override
    public PayResult query(String orderNo) {
        // 查询支付宝支付结果
        return new PayResult();
    }
}

/**
 * 策略工厂
 */
@Component
public class PayStrategyFactory {
    
    private final Map<String, PayStrategy> strategyMap;
    
    @Autowired
    public PayStrategyFactory(List<PayStrategy> strategies) {
        // Spring自动注入所有PayStrategy实现类
        this.strategyMap = strategies.stream()
            .collect(Collectors.toMap(
                PayStrategy::getType,
                strategy -> strategy
            ));
    }
    
    public PayStrategy getStrategy(String type) {
        PayStrategy strategy = strategyMap.get(type);
        if (strategy == null) {
            throw new BusinessException("不支持的支付方式: " + type);
        }
        return strategy;
    }
}

/**
 * 支付服务(使用策略)
 */
@Service
public class PaymentService {
    
    @Autowired
    private PayStrategyFactory payStrategyFactory;
    
    public PayResult pay(PayRequest request) {
        // 根据支付方式获取对应策略
        PayStrategy strategy = payStrategyFactory.getStrategy(request.getPayType());
        
        // 执行支付
        return strategy.pay(request);
    }
}
```

## 6.2 模板方法模式(订单流程)

**场景:不同类型订单创建流程类似,但部分步骤不同**

```java
/**
 * 订单创建模板
 */
@Slf4j
public abstract class AbstractOrderCreateTemplate {
    
    /**
     * 创建订单(模板方法)
     */
    public final OrderResult createOrder(OrderRequest request) {
        // 1. 参数校验
        validateParams(request);
        
        // 2. 检查库存
        checkStock(request);
        
        // 3. 计算价格(不同订单类型计算方式不同)
        BigDecimal totalAmount = calculatePrice(request);
        
        // 4. 创建订单
        Order order = buildOrder(request, totalAmount);
        orderMapper.insert(order);
        
        // 5. 扣减库存
        deductStock(request);
        
        // 6. 业务特殊处理(钩子方法,子类可选实现)
        afterOrderCreated(order);
        
        // 7. 发送MQ
        sendOrderMessage(order);
        
        log.info("订单创建成功: orderNo={}", order.getOrderNo());
        return OrderResult.success(order);
    }
    
    /**
     * 参数校验(通用)
     */
    private void validateParams(OrderRequest request) {
        if (request.getUserId() == null) {
            throw new BusinessException("用户ID不能为空");
        }
        if (CollectionUtils.isEmpty(request.getItems())) {
            throw new BusinessException("商品列表不能为空");
        }
    }
    
    /**
     * 检查库存(通用)
     */
    private void checkStock(OrderRequest request) {
        for (OrderItemRequest item : request.getItems()) {
            Integer stock = stockService.getStock(item.getProductId());
            if (stock < item.getQuantity()) {
                throw new BusinessException("商品库存不足");
            }
        }
    }
    
    /**
     * 计算价格(抽象方法,子类必须实现)
     */
    protected abstract BigDecimal calculatePrice(OrderRequest request);
    
    /**
     * 扣减库存(通用)
     */
    private void deductStock(OrderRequest request) {
        for (OrderItemRequest item : request.getItems()) {
            stockService.deduct(item.getProductId(), item.getQuantity());
        }
    }
    
    /**
     * 订单创建后处理(钩子方法,子类可选实现)
     */
    protected void afterOrderCreated(Order order) {
        // 默认空实现
    }
    
    /**
     * 发送MQ(通用)
     */
    private void sendOrderMessage(Order order) {
        mqProducer.send("order-created", order);
    }
    
    private Order buildOrder(OrderRequest request, BigDecimal totalAmount) {
        Order order = new Order();
        order.setOrderNo(generateOrderNo());
        order.setUserId(request.getUserId());
        order.setTotalAmount(totalAmount);
        order.setStatus(0);
        order.setCreateTime(new Date());
        return order;
    }
}

/**
 * 普通订单(原价)
 */
@Service("normalOrderCreate")
public class NormalOrderCreateTemplate extends AbstractOrderCreateTemplate {
    
    @Override
    protected BigDecimal calculatePrice(OrderRequest request) {
        return request.getItems().stream()
            .map(item -> {
                Product product = productService.getById(item.getProductId());
                return product.getPrice().multiply(new BigDecimal(item.getQuantity()));
            })
            .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
}

/**
 * 秒杀订单(秒杀价)
 */
@Service("seckillOrderCreate")
public class SeckillOrderCreateTemplate extends AbstractOrderCreateTemplate {
    
    @Override
    protected BigDecimal calculatePrice(OrderRequest request) {
        // 使用秒杀价
        return request.getItems().stream()
            .map(item -> {
                SeckillProduct seckill = seckillService.getById(item.getProductId());
                return seckill.getSeckillPrice().multiply(new BigDecimal(item.getQuantity()));
            })
            .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
    
    @Override
    protected void afterOrderCreated(Order order) {
        // 秒杀订单需要记录秒杀信息
        SeckillRecord record = new SeckillRecord();
        record.setOrderId(order.getId());
        record.setUserId(order.getUserId());
        record.setCreateTime(new Date());
        seckillRecordMapper.insert(record);
    }
}

/**
 * 拼团订单
 */
@Service("groupOrderCreate")
public class GroupOrderCreateTemplate extends AbstractOrderCreateTemplate {
    
    @Override
    protected BigDecimal calculatePrice(OrderRequest request) {
        // 使用拼团价
        return request.getItems().stream()
            .map(item -> {
                GroupProduct group = groupService.getById(item.getProductId());
                return group.getGroupPrice().multiply(new BigDecimal(item.getQuantity()));
            })
            .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
    
    @Override
    protected void afterOrderCreated(Order order) {
        // 拼团订单需要加入拼团
        groupService.joinGroup(order.getUserId(), order.getId());
    }
}

/**
 * 订单服务(使用模板)
 */
@Service
public class OrderService {
    
    @Autowired
    private ApplicationContext applicationContext;
    
    public OrderResult createOrder(OrderRequest request) {
        // 根据订单类型获取对应模板
        String beanName = request.getOrderType() + "OrderCreate";
        AbstractOrderCreateTemplate template = applicationContext.getBean(beanName, AbstractOrderCreateTemplate.class);
        
        return template.createOrder(request);
    }
}
```

## 6.3 责任链模式(订单校验)

**场景:订单创建前需要多个校验步骤**

```java
/**
 * 校验处理器接口
 */
public interface OrderValidateHandler {
    
    /**
     * 处理校验
     */
    void handle(OrderRequest request);
    
    /**
     * 设置下一个处理器
     */
    void setNext(OrderValidateHandler next);
}

/**
 * 抽象处理器
 */
public abstract class AbstractOrderValidateHandler implements OrderValidateHandler {
    
    protected OrderValidateHandler next;
    
    @Override
    public void setNext(OrderValidateHandler next) {
        this.next = next;
    }
    
    @Override
    public void handle(OrderRequest request) {
        // 当前处理器处理
        doHandle(request);
        
        // 传递给下一个处理器
        if (next != null) {
            next.handle(request);
        }
    }
    
    /**
     * 具体处理逻辑(子类实现)
     */
    protected abstract void doHandle(OrderRequest request);
}

/**
 * 1. 用户状态校验
 */
@Component
@Order(1)
public class UserStatusValidateHandler extends AbstractOrderValidateHandler {
    
    @Autowired
    private UserService userService;
    
    @Override
    protected void doHandle(OrderRequest request) {
        SysUser user = userService.getById(request.getUserId());
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        if (user.getStatus() != 1) {
            throw new BusinessException("用户状态异常");
        }
    }
}

/**
 * 2. 商品状态校验
 */
@Component
@Order(2)
public class ProductStatusValidateHandler extends AbstractOrderValidateHandler {
    
    @Autowired
    private ProductService productService;
    
    @Override
    protected void doHandle(OrderRequest request) {
        for (OrderItemRequest item : request.getItems()) {
            Product product = productService.getById(item.getProductId());
            if (product == null) {
                throw new BusinessException("商品不存在");
            }
            if (product.getStatus() != 1) {
                throw new BusinessException("商品已下架");
            }
        }
    }
}

/**
 * 3. 库存校验
 */
@Component
@Order(3)
public class StockValidateHandler extends AbstractOrderValidateHandler {
    
    @Autowired
    private StockService stockService;
    
    @Override
    protected void doHandle(OrderRequest request) {
        for (OrderItemRequest item : request.getItems()) {
            Integer stock = stockService.getStock(item.getProductId());
            if (stock < item.getQuantity()) {
                throw new BusinessException("商品库存不足");
            }
        }
    }
}

/**
 * 4. 限购校验
 */
@Component
@Order(4)
public class LimitBuyValidateHandler extends AbstractOrderValidateHandler {
    
    @Autowired
    private OrderMapper orderMapper;
    
    @Override
    protected void doHandle(OrderRequest request) {
        // 查询用户今日购买次数
        int count = orderMapper.selectCount(
            Wrappers.<Order>lambdaQuery()
                .eq(Order::getUserId, request.getUserId())
                .ge(Order::getCreateTime, DateUtil.beginOfDay(new Date()))
        );
        
        if (count >= 5) {
            throw new BusinessException("今日购买次数已达上限");
        }
    }
}

/**
 * 责任链工厂
 */
@Component
public class OrderValidateChainFactory {
    
    private final OrderValidateHandler chain;
    
    @Autowired
    public OrderValidateChainFactory(List<AbstractOrderValidateHandler> handlers) {
        // 按@Order排序
        handlers.sort(Comparator.comparingInt(h -> 
            h.getClass().getAnnotation(Order.class).value()
        ));
        
        // 构建责任链
        for (int i = 0; i < handlers.size() - 1; i++) {
            handlers.get(i).setNext(handlers.get(i + 1));
        }
        
        this.chain = handlers.get(0);
    }
    
    public OrderValidateHandler getChain() {
        return chain;
    }
}

/**
 * 订单服务(使用责任链)
 */
@Service
public class OrderService {
    
    @Autowired
    private OrderValidateChainFactory chainFactory;
    
    public void createOrder(OrderRequest request) {
        // 执行责任链校验
        chainFactory.getChain().handle(request);
        
        // 校验通过,创建订单
        // ...
    }
}
```

## 6.4 观察者模式(订单事件)

**场景:订单创建后,需要通知多个模块(库存、积分、优惠券等)**

```java
/**
 * 订单事件
 */
@Data
public class OrderCreatedEvent {
    private Long orderId;
    private Long userId;
    private BigDecimal amount;
    private Date createTime;
}

/**
 * 发布事件
 */
@Service
public class OrderService {
    
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    
    public void createOrder(OrderRequest request) {
        // 创建订单
        Order order = new Order();
        order.setOrderNo(generateOrderNo());
        order.setUserId(request.getUserId());
        order.setTotalAmount(request.getTotalAmount());
        orderMapper.insert(order);
        
        // 发布订单创建事件
        OrderCreatedEvent event = new OrderCreatedEvent();
        event.setOrderId(order.getId());
        event.setUserId(order.getUserId());
        event.setAmount(order.getTotalAmount());
        event.setCreateTime(order.getCreateTime());
        
        eventPublisher.publishEvent(event);
    }
}

/**
 * 监听器1:扣减库存
 */
@Component
@Slf4j
public class StockEventListener {
    
    @Autowired
    private StockService stockService;
    
    @EventListener
    @Async  // 异步处理
    public void onOrderCreated(OrderCreatedEvent event) {
        log.info("监听到订单创建事件,开始扣减库存: orderId={}", event.getOrderId());
        stockService.deductByOrderId(event.getOrderId());
    }
}

/**
 * 监听器2:增加积分
 */
@Component
@Slf4j
public class PointsEventListener {
    
    @Autowired
    private PointsService pointsService;
    
    @EventListener
    @Async
    public void onOrderCreated(OrderCreatedEvent event) {
        log.info("监听到订单创建事件,开始增加积分: userId={}", event.getUserId());
        // 消费100元增加1积分
        int points = event.getAmount().divide(new BigDecimal("100"), 0, RoundingMode.DOWN).intValue();
        pointsService.add(event.getUserId(), points, "订单消费赠送");
    }
}

/**
 * 监听器3:发送通知
 */
@Component
@Slf4j
public class NotificationEventListener {
    
    @Autowired
    private NotificationService notificationService;
    
    @EventListener
    @Async
    public void onOrderCreated(OrderCreatedEvent event) {
        log.info("监听到订单创建事件,开始发送通知: userId={}", event.getUserId());
        notificationService.sendOrderNotification(event.getUserId(), event.getOrderId());
    }
}
```

## 6.5 工厂模式(导出服务)

**场景:支持多种格式导出(Excel、PDF、CSV)**

```java
/**
 * 导出服务接口
 */
public interface ExportService {
    
    /**
     * 导出类型
     */
    String getType();
    
    /**
     * 导出数据
     */
    byte[] export(List<?> data);
}

/**
 * Excel导出
 */
@Service
public class ExcelExportService implements ExportService {
    
    @Override
    public String getType() {
        return "EXCEL";
    }
    
    @Override
    public byte[] export(List<?> data) {
        // 使用EasyExcel导出
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        EasyExcel.write(out).sheet("数据").doWrite(data);
        return out.toByteArray();
    }
}

/**
 * PDF导出
 */
@Service
public class PdfExportService implements ExportService {
    
    @Override
    public String getType() {
        return "PDF";
    }
    
    @Override
    public byte[] export(List<?> data) {
        // 使用iText导出PDF
        // ...
        return new byte[0];
    }
}

/**
 * 导出工厂
 */
@Component
public class ExportServiceFactory {
    
    private final Map<String, ExportService> serviceMap;
    
    @Autowired
    public ExportServiceFactory(List<ExportService> services) {
        this.serviceMap = services.stream()
            .collect(Collectors.toMap(
                ExportService::getType,
                service -> service
            ));
    }
    
    public ExportService getService(String type) {
        ExportService service = serviceMap.get(type);
        if (service == null) {
            throw new BusinessException("不支持的导出类型: " + type);
        }
        return service;
    }
}

/**
 * 使用
 */
@RestController
public class ExportController {
    
    @Autowired
    private ExportServiceFactory exportFactory;
    
    @GetMapping("/export")
    public void export(@RequestParam String type, HttpServletResponse response) throws IOException {
        // 查询数据
        List<Order> orders = orderService.list();
        
        // 获取导出服务
        ExportService exportService = exportFactory.getService(type);
        
        // 导出
        byte[] data = exportService.export(orders);
        
        // 返回文件
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment; filename=orders." + type.toLowerCase());
        response.getOutputStream().write(data);
    }
}
```

---

# 七、其他重要知识点

## 7.1 异步编程(CompletableFuture)

```java
@Service
@Slf4j
public class AsyncService {
    
    @Autowired
    private OrderService orderService;
    
    @Autowired
    private ProductService productService;
    
    @Autowired
    private UserService userService;
    
    /**
     * 场景:订单详情页需要查询多个接口
     * 
     * 串行:500ms + 300ms + 200ms = 1000ms
     * 并行:max(500ms, 300ms, 200ms) = 500ms
     */
    public OrderDetailVO getOrderDetail(Long orderId) {
        CompletableFuture<Order> orderFuture = CompletableFuture.supplyAsync(() -> {
            // 查询订单(500ms)
            return orderService.getById(orderId);
        });
        
        CompletableFuture<Product> productFuture = CompletableFuture.supplyAsync(() -> {
            // 查询商品(300ms)
            return productService.getById(1L);
        });
        
        CompletableFuture<User> userFuture = CompletableFuture.supplyAsync(() -> {
            // 查询用户(200ms)
            return userService.getById(1L);
        });
        
        // 等待所有任务完成
        CompletableFuture.allOf(orderFuture, productFuture, userFuture).join();
        
        // 组装结果
        OrderDetailVO vo = new OrderDetailVO();
        vo.setOrder(orderFuture.join());
        vo.setProduct(productFuture.join());
        vo.setUser(userFuture.join());
        
        return vo;
    }
    
    /**
     * 场景:级联查询
     * 
     * 先查订单 → 再查订单明细 → 再查商品详情
     */
    public OrderDetailVO getOrderDetailCascade(Long orderId) {
        return CompletableFuture.supplyAsync(() -> {
            // 1. 查订单
            return orderService.getById(orderId);
        })
        .thenApply(order -> {
            // 2. 查订单明细
            List<OrderItem> items = orderItemService.listByOrderId(order.getId());
            return Pair.of(order, items);
        })
        .thenApply(pair -> {
            // 3. 查商品详情
            List<Long> productIds = pair.getRight().stream()
                .map(OrderItem::getProductId)
                .collect(Collectors.toList());
            List<Product> products = productService.listByIds(productIds);
            
            // 组装结果
            OrderDetailVO vo = new OrderDetailVO();
            vo.setOrder(pair.getLeft());
            vo.setItems(pair.getRight());
            vo.setProducts(products);
            return vo;
        })
        .exceptionally(ex -> {
            log.error("查询订单详情失败", ex);
            return null;
        })
        .join();
    }
}
```

## 7.2 线程池配置

```java
@Configuration
@EnableAsync
public class ThreadPoolConfig {
    
    /**
     * 核心线程池
     */
    @Bean("taskExecutor")
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        
        // 核心线程数(CPU密集型:CPU核数,IO密集型:CPU核数*2)
        executor.setCorePoolSize(8);
        
        // 最大线程数
        executor.setMaxPoolSize(16);
        
        // 队列容量
        executor.setQueueCapacity(100);
        
        // 线程空闲时间(秒)
        executor.setKeepAliveSeconds(60);
        
        // 线程名前缀
        executor.setThreadNamePrefix("task-");
        
        // 拒绝策略(队列满时)
        // CallerRunsPolicy:调用者线程执行
        // AbortPolicy:抛异常(默认)
        // DiscardPolicy:丢弃
        // DiscardOldestPolicy:丢弃最旧的任务
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        
        // 等待任务完成后关闭
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setAwaitTerminationSeconds(60);
        
        executor.initialize();
        return executor;
    }
    
    /**
     * 异步方法异常处理
     */
    @Bean
    public AsyncUncaughtExceptionHandler asyncUncaughtExceptionHandler() {
        return (ex, method, params) -> {
            log.error("异步方法执行异常: method={}, params={}", 
                method.getName(), Arrays.toString(params), ex);
        };
    }
}

/**
 * 使用
 */
@Service
public class AsyncTaskService {
    
    @Async("taskExecutor")
    public void asyncTask() {
        log.info("异步任务执行,线程: {}", Thread.currentThread().getName());
        // 业务逻辑
    }
    
    @Async("taskExecutor")
    public CompletableFuture<String> asyncTaskWithResult() {
        // 带返回值的异步任务
        String result = "处理结果";
        return CompletableFuture.completedFuture(result);
    }
}
```

## 7.3 缓存注解

```java
@Configuration
@EnableCaching
public class CacheConfig {
    
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofMinutes(10))  // 默认过期时间10分钟
            .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
            .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
            .disableCachingNullValues();  // 不缓存null值
        
        return RedisCacheManager.builder(factory)
            .cacheDefaults(config)
            .build();
    }
}

@Service
public class ProductService {
    
    /**
     * @Cacheable:先查缓存,没有再执行方法,并缓存结果
     */
    @Cacheable(value = "product", key = "#id")
    public Product getById(Long id) {
        log.info("查询数据库: id={}", id);
        return productMapper.selectById(id);
    }
    
    /**
     * @CachePut:执行方法,并更新缓存
     */
    @CachePut(value = "product", key = "#product.id")
    public Product update(Product product) {
        productMapper.updateById(product);
        return product;
    }
    
    /**
     * @CacheEvict:删除缓存
     */
    @CacheEvict(value = "product", key = "#id")
    public void deleteById(Long id) {
        productMapper.deleteById(id);
    }
    
    /**
     * 删除所有缓存
     */
    @CacheEvict(value = "product", allEntries = true)
    public void deleteAll() {
        // ...
    }
    
    /**
     * 条件缓存:只缓存价格>100的商品
     */
    @Cacheable(value = "product", key = "#id", condition = "#result != null && #result.price > 100")
    public Product getExpensiveProduct(Long id) {
        return productMapper.selectById(id);
    }
}
```

## 7.4 重试机制

```java
@Configuration
@EnableRetry
public class RetryConfig {}

@Service
public class PaymentService {
    
    /**
     * @Retryable:自动重试
     * 
     * value:哪些异常需要重试
     * maxAttempts:最大重试次数
     * backoff:重试间隔策略
     */
    @Retryable(
        value = {RemoteServiceException.class},
        maxAttempts = 3,
        backoff = @Backoff(delay = 1000, multiplier = 2)  // 1秒、2秒、4秒
    )
    public PayResult pay(PayRequest request) {
        log.info("调用支付接口");
        
        // 调用第三方支付
        PayResult result = remotePayService.pay(request);
        
        if (!result.isSuccess()) {
            throw new RemoteServiceException("支付失败");
        }
        
        return result;
    }
    
    /**
     * @Recover:重试失败后的兜底方法
     */
    @Recover
    public PayResult recover(RemoteServiceException e, PayRequest request) {
        log.error("支付重试失败,执行兜底逻辑", e);
        
        // 兜底逻辑:记录失败订单,人工处理
        saveFailedOrder(request);
        
        return PayResult.fail("支付服务暂时不可用,请稍后重试");
    }
}
```

---

## 📝 面试速记卡

```
【网络编程】
RestTemplate | OkHttp | WebClient(异步)
WebSocket实时推送

【Stream流】
filter → map → collect
groupingBy → 分组统计
flatMap → 扁平化

【AOP】
@Around:操作日志、性能监控、防重复提交
切入点:execution | @annotation

【注解】
核心:@SpringBootApplication | @Configuration | @Bean
Web:@RestController | @RequestMapping | @Valid
注入:@Autowired | @Value | @ConfigurationProperties
条件:@ConditionalOnProperty | @ConditionalOnClass

【自定义注解】
@Target | @Retention | @Documented
配合AOP实现:限流、日志、权限

【设计模式】
策略模式:支付方式(微信/支付宝)
模板方法:订单流程(普通/秒杀/拼团)
责任链:订单校验(用户/商品/库存/限购)
观察者:订单事件(库存/积分/通知)
工厂模式:导出服务(Excel/PDF/CSV)

【其他】
CompletableFuture:异步编程
线程池:@Async + ThreadPoolTaskExecutor
缓存:@Cacheable | @CachePut | @CacheEvict
重试:@Retryable + @Recover
```

---

## 🎯 后端技术清单(补充)

除了已经写过的,这些也很重要:

### 已完成 ✅
1. ✅ Spring核心(IOC、AOP、事务)
2. ✅ MyBatis-Plus高阶
3. ✅ Redis(缓存、分布式锁)
4. ✅ MySQL(索引、事务、优化)
5. ✅ 运维DevOps(Linux、Docker、K8s、Nginx)
6. ✅ 流程引擎Flowable
7. ✅ 分库分表、信创改造
8. ✅ 网络编程、Stream、AOP、注解、设计模式

### 建议补充(可选)
9. **消息队列**:RabbitMQ/Kafka(发送、消费、死信队列、延迟消息)
10. **分布式**:Nacos(配置中心、服务注册)、Seata(分布式事务)
11. **搜索引擎**:Elasticsearch(全文检索、聚合分析)
12. **定时任务**:XXL-Job(分片、失败重试、监控)
13. **安全认证**:Shiro/Spring Security + JWT
14. **API网关**:Gateway(路由、限流、熔断)
15. **链路追踪**:Skywalking(性能监控、调用链路)

---

**文档版本**:v1.0  
**创建时间**:2026-01-19  
**适用场景**:Java核心编程与设计模式面试


评论