// 堆代码 duidaima.com // 贫血模型的典型实现 public class Order { @Autowired private PaymentService paymentService; // 违反单一职责原则 public void pay() { paymentService.process(this); } }
@Primary publicclass SpringContext implements ApplicationContextAware, PriorityOrdered, ApplicationRunner { privatestatic ApplicationContext applicationContext; // 初始化完成的信号 privatestaticfinal CountDownLatch INITIALIZATION_LATCH = new CountDownLatch(1); @Override public void run(ApplicationArguments args) throws Exception { // 通知等待的线程初始化已完成 INITIALIZATION_LATCH.countDown(); } public void setApplicationContext(ApplicationContext applicationContext) { SpringContext.applicationContext = applicationContext; } publicstatic <T> T getBean(Class<T> clazz) { return applicationContext.getBean(clazz); } // 获取Bean,需等待应用完全启动 publicstatic <T> T getBeanSync(Class<T> clazz) { try { // 阻塞等待初始化完成,最多等待 1 分钟 if (!INITIALIZATION_LATCH.await(1, TimeUnit.MINUTES)) { thrownew IllegalStateException("应用初始化超时"); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); thrownew RuntimeException("获取Bean时线程被中断", e); } return applicationContext.getBean(clazz); } @Override public int getOrder() { return PriorityOrdered.HIGHEST_PRECEDENCE; } }在订单领域模型中,我们通过显式获取的方式维护领域模型的纯粹性:
public class Order { private Long orderId; private BigDecimal amount; private OrderStatus status; // 保持领域模型的纯洁性 public void pay() { PaymentService paymentService = SpringContext.getBean(PaymentService.class); PaymentResult result = paymentService.execute(this); if (result.isSuccess()) { this.status = OrderStatus.PAID; DomainEventPublisher.publish(new OrderPaidEvent(this)); } } }优势对比表:
维度 | 自动注入方案 | 显式获取方案 |
---|---|---|
领域模型纯净度 | 依赖容器 | 完全POJO |
可测试性 | 需要Spring环境 | 普通Mock即可 |
依赖可见性 | 隐式 | 显式 |
循环依赖风险 | 高 | 无 |
代码可读性 | 需要IDE辅助 | 一目了然 |
public class AsyncBeanAccessor { public static <T> Mono<T> getBeanReactive(Class<T> beanClass) { return Mono.fromCallable(() -> SpringContext.getBean(beanClass)).subscribeOn(Schedulers.boundedElastic()); } }测试支持方案通过自定义Mock策略实现依赖隔离:
@Test public void testOrderPayment() { // 配置Mock环境 SpringContextMock.registerMock(PaymentService.class, mockService); Order order = new Order(/*...*/); order.completePayment(); assertThat(order.getStatus()).isEqualTo(PAID); }0x4
演进式设计:保持领域模型的技术中立性,为未来可能的框架迁移预留可能性