使用Spring的BeanPostProcessor优雅的实现工厂模式

简介: 使用Spring的BeanPostProcessor优雅的实现工厂模式

最近在学习状态设计模式时,发现一个实现工厂模式的优雅方式,那就是借助注解和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|||-


相关文章
|
前端开发 Java Spring
Spring Boot 实现图片上传并回显
Spring Boot 实现图片上传并回显
|
4月前
|
Java Spring
Spring中那些BeanPostProcessor在Bean实例化过程中的作用
Spring中那些BeanPostProcessor在Bean实例化过程中的作用
48 1
|
7月前
|
XML 开发框架 Java
聊聊Spring扩展点BeanPostProcessor和BeanFactoryPostProcessor
今天聊一聊spring中很重要的两个扩展点BeanPostProcessor和BeanFactoryPostProcessor,spring之所以如次强大,是因为它提供了丰富的功能给我们使用,但是我觉得最强大的是它扩展点,因为有了各种扩展点,我们才能去开发一些自己的需求,一个框架的强大之处也在于它能否灵活的配置,能够支持很好的扩展。
37 0
|
8月前
|
Java Spring 容器
深入理解Spring源码之bean的生命周期控制器BeanPostProcessor
深入理解Spring源码之bean的生命周期控制器BeanPostProcessor
|
8月前
|
设计模式 前端开发 Java
【Spring】工厂模式
【Spring】工厂模式
|
9月前
|
前端开发 JavaScript Java
浅谈Spring的相关概念性问题 IOC DI AOP 工厂模式 单例
浅谈Spring的相关概念性问题 IOC DI AOP 工厂模式 单例
|
9月前
|
设计模式 Java Spring
java spring设计模式 之 工厂模式
java spring设计模式 之 工厂模式
|
10月前
|
缓存 Java 开发者
Spring高手之路6——Bean生命周期的扩展点:BeanPostProcessor
在本篇文章中,我们将深入探讨Spring框架中的重要组件——BeanPostProcessor。首先,我们将了解其设计理念和目标,然后通过实际的例子学习如何基础使用它,如何通过BeanPostProcessor改变Bean的初始化结果以及如何利用它修改Bean的属性。最后,我们将深入理解后置处理器在Bean生命周期中的作用和执行时机,帮助读者更好地理解和使用这个强大的工具。
65 1
Spring高手之路6——Bean生命周期的扩展点:BeanPostProcessor
|
10月前
|
SQL 人工智能 Java
Spring中使用工厂模式解耦详解
Spring中使用工厂模式解耦详解
|
10月前
|
XML Java 数据库连接
深入理解Spring IOC之扩展篇(二)、BeanFactoryPostProcessor和BeanPostProcessor
深入理解Spring IOC之扩展篇(二)、BeanFactoryPostProcessor和BeanPostProcessor
64 1