第四节 AOP编程范式

80 阅读3分钟

1.4 AOP编程范式

1.4.1 代理模式底层原理剖析(字节码级解析)

代理机制对比矩阵

| 维度           | JDK动态代理                     | CGLIB字节码增强               |
|----------------|--------------------------------|------------------------------|
| 代理对象类型    | 接口代理                       | 类代理(final类除外)          |
| 性能开销       | 反射调用(约300ns/次)         | 直接方法调用(约50ns/次)       |
| 依赖限制       | 需实现接口                     | 无特殊要求                    |
| 生成方式       | Proxy.newProxyInstance         | Enhancer.create               |
| 方法拦截       | InvocationHandler              | MethodInterceptor             |
| 适用场景       | 轻量级代理/接口明确场景         | 需要继承/性能敏感场景           |

JDK动态代理实现原理

// 1. 定义业务接口
public interface UserService {
    void createUser(String name);
}

// 2. 实现InvocationHandler
public class AuditHandler implements InvocationHandler {
    private final Object target;

    public AuditHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) {
        long start = System.nanoTime();
        Object result = method.invoke(target, args);
        System.out.printf("方法 %s 执行耗时 %dns%n", 
                         method.getName(), 
                         System.nanoTime()-start);
        return result;
    }
}

// 3. 生成代理对象
UserService proxyInstance = (UserService) Proxy.newProxyInstance(
    UserService.class.getClassLoader(),
    new Class[]{UserService.class},
    new AuditHandler(new UserServiceImpl())
);

CGLIB字节码增强示例

// 1. 定义方法拦截器
public class CacheInterceptor implements MethodInterceptor {
    private final Map<String, Object> cache = new ConcurrentHashMap<>();

    @Override
    public Object intercept(Object obj, Method method, 
                           Object[] args, MethodProxy proxy) {
        String key = method.getName() + Arrays.toString(args);
        return cache.computeIfAbsent(key, k -> {
            try {
                return proxy.invokeSuper(obj, args);
            } catch (Throwable e) {
                throw new RuntimeException(e);
            }
        });
    }
}

// 2. 生成增强类
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(ProductService.class);
enhancer.setCallback(new CacheInterceptor());
ProductService cachedService = (ProductService) enhancer.create();

1.4.2 声明式事务控制实战(金融交易案例)

事务配置全流程

// 1. 配置事务管理器
@Configuration
@EnableTransactionManagement
public class TransactionConfig {
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

// 2. 服务层事务控制
@Service
public class BankTransferService {
    private final JdbcTemplate jdbcTemplate;

    @Autowired
    public BankTransferService(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    @Transactional(
        isolation = Isolation.REPEATABLE_READ,
        propagation = Propagation.REQUIRED,
        rollbackFor = {BalanceInsufficientException.class}
    )
    public void transfer(String from, String to, BigDecimal amount) {
        // 扣款操作
        jdbcTemplate.update(
            "UPDATE account SET balance = balance - ? WHERE id = ?",
            amount, from
        );
        
        // 模拟业务异常
        if (amount.compareTo(BigDecimal.valueOf(10000)) > 0) {
            throw new FraudDetectionException("大额交易需人工审核");
        }

        // 入账操作
        jdbcTemplate.update(
            "UPDATE account SET balance = balance + ? WHERE id = ?",
            amount, to
        );
    }
}

事务传播机制实验

@Service
public class OrderService {
    @Autowired
    private InventoryService inventoryService;

    @Transactional
    public void createOrder(Order order) {
        // 主事务方法
        saveOrder(order);
        
        try {
            inventoryService.deductStock(order.getItems());
        } catch (Exception e) {
            // 独立事务中的异常不会导致主事务回滚
            log.error("库存扣减失败", e);
        }
    }
}

@Service
public class InventoryService {
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void deductStock(List<OrderItem> items) {
        items.forEach(item -> {
            jdbcTemplate.update(
                "UPDATE product SET stock = stock - ? WHERE id = ?",
                item.getQuantity(), 
                item.getProductId()
            );
        });
    }
}

1.4.3 自定义审计日志实现(电商系统案例)

审计注解定义

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AuditLog {
    String module() default "";
    OperationType type();
    
    enum OperationType {
        CREATE, UPDATE, DELETE, QUERY
    }
}

切面实现细节

@Aspect
@Component
public class AuditAspect {
    private final AuditLogRepository logRepository;
    
    @Autowired
    public AuditAspect(AuditLogRepository logRepository) {
        this.logRepository = logRepository;
    }

    @Around("@annotation(auditLog)")
    public Object logOperation(ProceedingJoinPoint pjp, AuditLog auditLog) 
        throws Throwable {
        
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        String methodName = signature.getName();
        Object[] args = pjp.getArgs();

        AuditLogEntity log = new AuditLogEntity();
        log.setModule(auditLog.module());
        log.setOperationType(auditLog.type().name());
        log.setMethod(methodName);
        log.setParameters(serializeArguments(args));
        log.setOperator(getCurrentUser());

        long start = System.currentTimeMillis();
        try {
            Object result = pjp.proceed();
            log.setSuccess(true);
            log.setResult(serializeResult(result));
            return result;
        } catch (Exception e) {
            log.setSuccess(false);
            log.setErrorMsg(e.getMessage());
            throw e;
        } finally {
            log.setDuration(System.currentTimeMillis() - start);
            logRepository.save(log);
        }
    }

    private String serializeArguments(Object[] args) {
        return Arrays.stream(args)
                   .map(arg -> {
                       if (arg instanceof MultipartFile) {
                           return ((MultipartFile) arg).getOriginalFilename();
                       }
                       return arg.toString();
                   })
                   .collect(Collectors.joining(", "));
    }
}

业务层使用示例

@Service
public class ProductService {
    @AuditLog(module = "商品管理", type = AuditLog.OperationType.CREATE)
    public Product createProduct(Product product) {
        // 创建商品逻辑
    }

    @AuditLog(module = "商品管理", type = AuditLog.OperationType.UPDATE)
    public Product updateProduct(Long id, Product product) {
        // 更新商品逻辑
    }
}

1.4.4 AOP在微服务监控中的创新应用

监控指标采集方案

@Aspect
@Component
@RequiredArgsConstructor
public class MetricsAspect {
    private final MeterRegistry meterRegistry;

    @Around("execution(* com.example..*Controller.*(..))")
    public Object collectMetrics(ProceedingJoinPoint pjp) throws Throwable {
        String className = pjp.getTarget().getClass().getSimpleName();
        String methodName = pjp.getSignature().getName();
        Timer.Sample sample = Timer.start(meterRegistry);

        try {
            Object result = pjp.proceed();
            sample.stop(Timer.builder("http_requests")
                           .tags("class", className, "method", methodName, "status", "200")
                           .register(meterRegistry));
            return result;
        } catch (Exception e) {
            sample.stop(Timer.builder("http_requests")
                           .tags("class", className, "method", methodName, "status", "500")
                           .register(meterRegistry));
            throw e;
        }
    }
}

// Prometheus配置示例
@Bean
public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
    return registry -> registry.config().commonTags(
        "application", "order-service",
        "environment", System.getenv("APP_ENV")
    );
}

熔断监控集成

@Aspect
@Component
public class CircuitBreakerAspect {
    private final CircuitBreakerRegistry registry;

    @Autowired
    public CircuitBreakerAspect(CircuitBreakerRegistry registry) {
        this.registry = registry;
    }

    @Around("@annotation(cbAnnotation)")
    public Object protect(ProceedingJoinPoint pjp, CircuitBreakerDef cbAnnotation) 
        throws Throwable {
        
        CircuitBreaker breaker = registry.circuitBreaker(cbAnnotation.name());
        return breaker.executeSupplier(() -> {
            try {
                return pjp.proceed();
            } catch (Throwable e) {
                throw new RuntimeException(e);
            }
        });
    }
}

// 业务方法使用示例
@Service
public class PaymentService {
    @CircuitBreakerDef(name = "paymentService", 
                      failureRateThreshold = 50,
                      waitDurationInOpenState = 10000)
    public PaymentResult processPayment(PaymentRequest request) {
        // 支付处理逻辑
    }
}