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

作者:爱唱歌的Coder 时间:2023-01-14 02:15:53 

最近学习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) {

}
}

来源:https://blog.csdn.net/m0_37954663/article/details/107168564

标签:Spring,BeanPostProcessor,工厂模式
0
投稿

猜你喜欢

  • 判断java文件类型TikaToolKit的实例

    2021-06-29 02:31:09
  • Java中的Set、List、Map的用法与区别介绍

    2022-10-03 04:11:48
  • android底层去掉虚拟按键的实例讲解

    2022-01-29 17:53:14
  • C# Record构造函数的行为更改详解

    2022-01-21 04:50:11
  • 剖析设计模式编程中C#对于组合模式的运用

    2023-04-09 07:48:17
  • Android 关机弹出选择菜单的深入解析

    2023-03-19 20:56:09
  • Android编程设计模式之原型模式实例详解

    2021-09-14 02:20:47
  • spring装配bean的3种方式总结

    2023-01-05 07:01:47
  • Android自定义view实现输入控件

    2022-12-11 10:08:06
  • 利用java制作简单的音乐播放器

    2022-01-21 11:39:32
  • SpringBoot实现任意位置获取HttpServletRequest对象

    2023-07-07 10:26:40
  • Java SSM配置文件案例详解

    2022-10-14 09:43:19
  • 深入理解Java中的接口

    2023-11-08 23:52:43
  • Java实现接口的枚举类示例

    2023-06-18 01:22:04
  • Unity实现弹球打砖块游戏

    2021-09-24 16:13:08
  • 一文详解Jetpack Android新一代导航管理Navigation

    2022-12-08 20:40:14
  • idea 实现搜索jdk中的类和包操作

    2022-06-02 22:54:47
  • Android利用SAX对XML进行增删改查操作详解

    2023-02-05 00:03:32
  • C# 语言入门基础介绍

    2022-03-02 13:32:33
  • Android Notification 使用方法详解

    2021-07-14 14:42:01
  • asp之家 软件编程 m.aspxhome.com