最近在学习状态设计模式时,发现一个实现工厂模式的优雅方式,那就是借助注解和Spring的BeanPostProcessor。使用处理器BeanPostProcessor可以在bean初始化的前后对bean进行操作,所以我们可以在bean初始化后对自己的目标bean进行缓存,进而实现我们想要的处理逻辑。
BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口,点击源码可以查看到BeanPostProcessor中有两个方法:
- (1)postProcessBeforeInitialization方法;
- (2)postProcessAfterInitialization方法;
两个方面的运行顺序如下:
- (1)Spring IOC容器实例化Bean
- (2)调用BeanPostProcessor的postProcessBeforeInitialization方法
- (3)调用bean实例的初始化方法
- (4)调用BeanPostProcessor的postProcessAfterInitialization方法
注意:实测项目中只能有一个BeanPostProcessor的实现,当出现多个时,只是加载了一次。注意此点,避免踩坑。
背景
当我们需要根据不同的状态调用接口不同的实现时,可以使用工厂模式实现。而之前最常用的方式就是通过多个if else的静态工厂方式进行处理。
进入主题
通过BeanPostProcessor实现相同接口的不同实现bean的工厂。
1 定义一个注解,用于标记不同的实现bean
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Component public @interface OrderStatusProcessor { /** * 状态枚举 */ OrderStatusEnum status() ; }
状态枚举定义:
@Getter @AllArgsConstructor public enum OrderStatusEnum { CREATE(1, "新建"), COMPLETE(2, "完成"), CANCLE(3, "取消"); private final Integer statusCode; private final String statusDesc; public static OrderStatusEnum getEnumByCode(Integer statusCode) { if (statusCode == null) { return null; } return Arrays.stream(values()).filter(e -> e.getStatusCode().equals(statusCode)).findFirst().orElse(null); } }
2 定义接口处理类
public interface StatusProcessor { public boolean action(OrderInfo orderInfo); }
Model定义:
@Data @Builder public class OrderInfo { /** * 订单编号 */ private Long orderId; /** * 订单状态:1-新建;2-完成;3-取消; */ private Integer orderStatus; }
3 自定义处理器实现,并用自定义的注解进行标识
@Slf4j @OrderStatusProcessor(status = OrderStatusEnum.CREATE) public class StatusCreateProcessor implements StatusProcessor { @Override public boolean action(OrderInfo orderInfo) { log.info("订单==>编号:({}),执行({})操作。",orderInfo.getOrderId(),OrderStatusEnum.getEnumByCode(orderInfo.getOrderStatus()).getStatusDesc()); return false; } }
@Slf4j @OrderStatusProcessor(status = OrderStatusEnum.COMPLETE) public class StatusCompleteProcessor implements StatusProcessor { @Override public boolean action(OrderInfo orderInfo) { log.info("订单==>编号:({}),执行({})操作。",orderInfo.getOrderId(),OrderStatusEnum.getEnumByCode(orderInfo.getOrderStatus()).getStatusDesc()); return false; } }
@Slf4j @OrderStatusProcessor(status = OrderStatusEnum.CANCLE) public class StatusCancleProcessor implements StatusProcessor { @Override public boolean action(OrderInfo orderInfo) { log.info("订单==>编号:({}),执行({})操作。",orderInfo.getOrderId(),OrderStatusEnum.getEnumByCode(orderInfo.getOrderStatus()).getStatusDesc()); return false; } }
4 通过BeanPostProcessor实现对bean后置处理,对注解的类型bean对象进行缓存
@Slf4j @Component public class StatusProcessRegistry implements BeanPostProcessor { /** * 第一层key是订单状态。 * 第二层是对应的处理器。 */ private static Map<Integer, StatusProcessor> statusProcessMap = new ConcurrentHashMap<>(); @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { log.info("beanName =============>"+beanName); if (bean instanceof StatusProcessor && bean.getClass().isAnnotationPresent(OrderStatusProcessor.class)) { OrderStatusProcessor annotation = bean.getClass().getAnnotation(OrderStatusProcessor.class); OrderStatusEnum orderStatusEnum = annotation.status(); Integer statusCode = orderStatusEnum.getStatusCode(); if (!statusProcessMap.containsKey(statusCode)){ statusProcessMap.put(statusCode,(StatusProcessor)bean); } } return bean; } public StatusProcessor acquireStatusProcess(Integer statusCode) { return statusProcessMap.get(statusCode); } }
5 状态机引擎处理类定义
@AllArgsConstructor @Component public class OrderOperatorEngine { private final StatusProcessRegistry statusProcessRegistry; public boolean operate(OrderInfo orderInfo) throws Exception{ // 获取当前事件处理器 StatusProcessor statusProcessor = statusProcessRegistry.acquireStatusProcess(orderInfo.getOrderStatus()); if (statusProcessor == null) { throw new Exception("NOT_FOUND_PROCESSOR"); } // 执行处理逻辑 return statusProcessor.action(orderInfo); } }
6 Rest Controller定义
@Slf4j @AllArgsConstructor @RestController @RequestMapping("/myorder") public class OrderController { private final OrderOperatorEngine orderOperatorEngine; @GetMapping("/update/{orderId}/{orderStatus}") public void accept(@PathVariable(value = "orderId") Long orderId, @PathVariable(value = "orderStatus") Integer orderStatus) { OrderInfo orderInfo = OrderInfo.builder() .orderId(orderId) .orderStatus(orderStatus) .build(); log.info("updateOrder info:{}", JSON.toJSONString(orderInfo)); try { orderOperatorEngine.operate(orderInfo); } catch (Exception e) { log.error(e.getMessage()); } } }
7 演示日志
###|||2021-10-19 21:49:21.651|||INFO|||656c12ff21d64eec9226f68d9db5d999.201.16346513616080000|||-|||http-nio-8080-exec-3|||OrderController--->updateOrder info:{"orderId":10001,"orderStatus":2} ###|||2021-10-19 21:49:21.652|||INFO|||656c12ff21d64eec9226f68d9db5d999.201.16346513616080000|||-|||http-nio-8080-exec-3|||StatusCompleteProcessor--->订单==>编号:(10001),执行(完成)操作。 ###|||2021-10-19 21:49:29.350|||INFO|||656c12ff21d64eec9226f68d9db5d999.204.16346513693480000|||-|||http-nio-8080-exec-6|||OrderController--->updateOrder info:{"orderId":10001,"orderStatus":1} ###|||2021-10-19 21:49:29.350|||INFO|||656c12ff21d64eec9226f68d9db5d999.204.16346513693480000|||-|||http-nio-8080-exec-6|||StatusCreateProcessor--->订单==>编号:(10001),执行(新建)操作。 ###|||2021-10-19 21:49:38.690|||INFO|||656c12ff21d64eec9226f68d9db5d999.208.16346513786880000|||-|||http-nio-8080-exec-10|||OrderController--->updateOrder info:{"orderId":10001,"orderStatus":3} ###|||2021-10-19 21:49:38.690|||INFO|||656c12ff21d64eec9226f68d9db5d999.208.16346513786880000|||-