美文网首页Java架构技术栈
详解使用Spring的BeanPostProcessor优雅的实

详解使用Spring的BeanPostProcessor优雅的实

作者: 若丨寒 | 来源:发表于2020-07-08 14:24 被阅读0次

    写在前面:2020年面试必备的Java后端进阶面试题总结了一份复习指南在Github上,内容详细,图文并茂,有需要学习的朋友可以Star一下!
    GitHub地址:https://github.com/abel-max/Java-Study-Note/tree/master

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

    最近学习Spring的源码,发现一个利器BeanPostProcessor。这个后置处理器可以在bean初始化前后对bean进行操作。我们可以在初始化的时候对自己想要的bean进行缓存,进而实现自己需要处理的逻辑。

    背景

    当我们需要根据类型调用接口不同实现的时候,我们可以使用工厂模式实现。下面说下博主遇到过的两次需要使用工厂的场景。

    场景一:

    当有一个模块,我们需要根据数据库的类型实现不同的的sql。我们此时需要定义一个接口然后每一种数据库实现不同的sql。在调用时根据当前的数据库类型调用对应的实现类。

    场景二:

    我们业务需要对接不同的传感器设备,但是总体业务逻辑就是获取数据,发送心跳。每一种设备的数据协议又不一样。所以需要使用工厂,根据不同的设备调用对应的实现类。

    工厂模式

    静态工厂

    /**
     * @Description
     * @Author Singh
     * @Date 2020-07-06 21:54
     * @Version
     **/
    @Service
    public class HandlerService1 {
    
      public <T> void handle(Constant.HandlerType handlerType, T dataDO) {
        IHandler handler = null;
        if(handlerType.getType().intValue() == Constant.HandlerType.HANDLE_TYEP_1.getType()){
          handler = new Type1Handler();
        }else if(handlerType.getType().intValue() == Constant.HandlerType.HANDLE_TYEP_2.getType()){
          handler = new Type2Handler();
        }else if(handlerType.getType().intValue() == Constant.HandlerType.HANDLE_TYEP_3.getType()){
          handler = new Type3Handler();
        }else if(handlerType.getType().intValue() == Constant.HandlerType.HANDLE_TYEP_4.getType()){
          handler = new Type4Handler();
        }else{
          throw new RuntimeException("类型错误");
        }
        handler.handle(dataDO);
      }
    }
    

    动态工厂,通过class实现

    /**
     * @Description
     * @Author Singh
     * @Date 2020-07-06 21:54
     * @Version
     **/
    @Service
    public class HandlerService2 {
    
      public <T,H extends IHandler> void handle(Class<H> clzz, T dataDO) throws IllegalAccessException, InstantiationException {
        IHandler handler = clzz.newInstance();
        handler.handle(dataDO);
      }
    
    }
    

    进入主题

    BeanPostProcessor实现相同接口的不同实现bean的工厂

    首先定义一个注解,后续用来标示bean的处理类型

    @Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface Handler {  @AliasFor(annotation = Component.class)  String value() default "";  /**   * 业务处理类型   * @return   */  Constant.HandlerType handlerType();}
    

    处理类型

    /**
     * @Description
     * @Author Singh
     * @Date 2020-07-06 21:25
     * @Version
     **/
    
    public class Constant {
    
      public enum HandlerType{
        HANDLE_TYEP_1(1),
        HANDLE_TYEP_2(2),
        HANDLE_TYEP_3(3),
        HANDLE_TYEP_4(4);
        private Integer type;
    
        HandlerType(Integer type) {
          this.type = type;
        }
    
        public Integer getType() {
          return type;
        }
    
      }
    }
    

    定义接口处理

    /**
     * @Description
     * @Author Singh
     * @Date 2020-07-06 21:29
     * @Version
     **/
    public interface IHandler<T> {
    
      void handle(T data);
    
    }
    

    BeanPostProcessor实现对bean后置处理。通过注解的类型缓存bean对象。

    /**
     * @Description
     * @Author Singh
     * @Date 2020-07-06 21:29
     * @Version
     **/
    @Service
    public class HandleService implements BeanPostProcessor {
    
      private Map<Integer,IHandler> reportDataHandlerMap = new ConcurrentHashMap<>();
    
      public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof IHandler){
          Handler[] reportHandlers = bean.getClass().getAnnotationsByType(Handler.class);
          if(reportHandlers == null || reportHandlers.length == 0){
            return bean;
          }
          Handler reportHandler = reportHandlers[0];
          reportDataHandlerMap.put(reportHandler.handlerType().getType(), (IHandler) bean);
        }
        return bean;
      }
    
      public <T> void handle(Constant.HandlerType handlerType, T dataDO) {
        IHandler reportDataHandler = reportDataHandlerMap.get(handlerType.getType());
        if(reportDataHandler == null){
          throw new RuntimeException("类型错误");
        }
        reportDataHandler.handle(dataDO);
      }
    }
    

    自定义处理器实现,每一种实现一次。

    /**
     * @Description
     * @Author Singh
     * @Date 2020-07-06 21:32
     * @Version
     **/
    @Handler(handlerType = Constant.HandlerType.HANDLE_TYEP_1 )
    public class Type1Handler implements IHandler<String>{
    
      @Override
      public void handle(String data) {
    
      }
    }
    

    来源:https://www.tuicool.com/articles/EJVfUj7

    相关文章

      网友评论

        本文标题:详解使用Spring的BeanPostProcessor优雅的实

        本文链接:https://www.haomeiwen.com/subject/focccktx.html