在职责链模式中,多个处理器(也就是刚刚定义中说的“接收对象”)依次处理同一个请求。一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责,所以叫作职责链模式。
下面我们在 Spring 框架的基础上,总结梳理实现动态添加职责链处理器、按指定顺序执行处理器,从而获取购物车详情信息,那么现在开始吧。
首先自定义如下注解,其中 order 属性标识顺序:
1 2 3 4 5 6
| @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) @Documented public @interface CartBusiness { int order() default 0; }
|
定义抽象处理器 AbstractBaseHandler:
1 2 3 4 5 6 7 8 9 10 11 12 13
| public abstract class AbstractBaseHandler<GetUserCartRequest, GetUserCartResponse> { private int order;
public int getOrder() { return order; }
public void setOrder(int order) { this.order = order; }
public abstract boolean doOrder(GetUserCartRequest request, GetUserCartResponse response); }
|
分别实现购物车商品配送处理器和购物车商品明细处理器,注解 @CartBusiness 表明该处理器是我们需要执行的处理器,order 表示该处理器的执行顺序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @CartBusiness(order = 1) @Component public class GoodsDeliveryHandler extends AbstractBaseHandler<GetUserCartRequest, GetUserCartResponse> { @Override public boolean doOrder(GetUserCartRequest request, GetUserCartResponse response) { System.out.println("购物车商品配送处理器..."); return true; } } @CartBusiness(order = 2) @Component public class GoodsDetailHandler extends AbstractBaseHandler<GetUserCartRequest, GetUserCartResponse> { @Override public boolean doOrder(GetUserCartRequest request, GetUserCartResponse response) { System.out.println("购物车商品明细处理器..."); return true; } }
|
如下定义职责链处理器 CartInfoChain,CartInfoChain 实现 Spring 框架的 BeanPostProcessor 接口,实现 postProcessAfterInitialization 方法,以从 IOC 容器中获取标有 @CartBusiness 注解的 Bean 按注解中的顺序添加到 handlers 中。其中 execute 方法为职责链执行入口,轮询的执行每个 handler,直到某个 handler 返回 false 则停止执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| @Component public class CartInfoChain implements BeanPostProcessor {
private List<AbstractBaseHandler<GetUserCartRequest, GetUserCartResponse>> handlers = new ArrayList<>();
@Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { CartBusiness cartBusiness = AnnotationUtils.findAnnotation(bean.getClass(), CartBusiness.class); if (cartBusiness != null && bean instanceof AbstractBaseHandler) { AbstractBaseHandler<GetUserCartRequest, GetUserCartResponse> handler = (AbstractBaseHandler) bean; handler.setOrder(cartBusiness.order()); handlers.add(handler); sortHandlers(); } return bean; }
private void sortHandlers() { if (!CollectionUtils.isEmpty(handlers)) { handlers.sort(Comparator.comparingInt(AbstractBaseHandler::getOrder)); } }
public void execute(GetUserCartRequest request, GetUserCartResponse response) { for (AbstractBaseHandler<GetUserCartRequest, GetUserCartResponse> handler : handlers) { boolean next = handler.doOrder(request, response); if (!next) { break; } } } }
|
执行入口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @SpringBootTest(classes = SpringBootMainApplication.class) @RunWith(SpringRunner.class) public class App { @Resource CartInfoChain cartInfoChain;
@Test public GetUserCartResponse getUserCart(GetUserCartRequest request) { GetUserCartResponse response = new GetUserCartResponse(); cartInfoChain.execute(request, response); return response; }
}
|