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

 更新时间:2020年07月08日 10:27:22   作者:爱唱歌的Coder  
这篇文章主要介绍了详解使用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
@Component
public @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) {

  }
}

到此这篇关于详解使用Spring的BeanPostProcessor优雅的实现工厂模式的文章就介绍到这了,更多相关Spring BeanPostProcessor 工厂模式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 推荐几款非常实用的IDEA插件小结

    推荐几款非常实用的IDEA插件小结

    这篇文章主要介绍了推荐几款非常实用的IDEA插件小结,解决你开发中可望而又不好找的插件,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • 一文吃透消息队列RocketMQ实现消费幂等原理

    一文吃透消息队列RocketMQ实现消费幂等原理

    这篇文章主要介绍了消息队列RocketMQ实现消费幂等的全面讲解,帮助大家吃透RocketMQ消息队列消费幂等,更好的的应用与工作实践,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • springboot集成Mybatis的详细教程

    springboot集成Mybatis的详细教程

    今天给大家带来的还是关于springboot的相关知识,文章围绕着springboot集成Mybatis的详细教程展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下
    2021-06-06
  • JAVA进阶之HashMap底层实现解析

    JAVA进阶之HashMap底层实现解析

    Hashmap是java面试中经常遇到的面试题,大部分都会问其底层原理与实现,为了能够温故而知新,特地写了这篇文章,以便时时学习
    2021-11-11
  • java 获取子串速率比较分析

    java 获取子串速率比较分析

    这篇文章主要为大家介绍了java 获取子串速率比较分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • SpringBoot yaml中的数组类型取值方式

    SpringBoot yaml中的数组类型取值方式

    这篇文章主要介绍了SpringBoot yaml中的数组类型取值方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • 详解Java中多进程编程的实现

    详解Java中多进程编程的实现

    这篇文章主要介绍了详解Java中多进程编程的实现,和多线程一样,多进程同样是实现并发的一种方式,需要的朋友可以参考下
    2015-11-11
  • IDEA使用JDBC安装配置jar包连接MySQL数据库

    IDEA使用JDBC安装配置jar包连接MySQL数据库

    这篇文章介绍了IDEA使用JDBC安装配置jar包连接MySQL数据库的方法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-01-01
  • SpringBoot Actuator未授权访问漏洞修复详解

    SpringBoot Actuator未授权访问漏洞修复详解

    这篇文章主要介绍了SpringBoot Actuator未授权访问漏洞修复详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • idea 实现纵列选择和大小写转换操作

    idea 实现纵列选择和大小写转换操作

    这篇文章主要介绍了idea 实现纵列选择和大小写转换操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02

最新评论