详解使用Spring的BeanPostProcessor优雅的实现工厂模式
作者:爱唱歌的Coder 发布时间:2023-01-14 02:15:53
标签: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) {
}
}
来源:https://blog.csdn.net/m0_37954663/article/details/107168564


猜你喜欢
- 本文实例为大家分享了android自定义控件实现简易时间轴的具体代码,供大家参考,具体内容如下之前项目需要写一个消费记录,类似于时间轴似的控
- 1基本输入输出 static void main(string[] args) { cons
- Gizmos是场景视图里的一个可视化调试工具。在做项目过程中。我们常常会用到它,比如:绘制一条射线等。Unity3D 4.2版本号截至。眼下
- 本文实例讲述了C#封装的常用文件操作类。分享给大家供大家参考。具体如下:这个C#类封装了我们经常能用到的文件操作方法,包括读写文件、获取文件
- 前言最近做了个滑动选择的小控件,拿出来给大家分享一下,先上图运行效果实现步骤这里分解为3个动作:Down、Move、Up来进行分析,博主文采
- 简介MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)
- 本文实例讲述了Android游戏开发学习①弹跳小球实现方法。分享给大家供大家参考。具体如下:在学习了一点点Android之后,觉得有必要记录
- 一、背景1.1 应用系统的架构历史1.2 什么是微服务?起源:微服务的概念源于 2014 年 3 月 Martin Fowler 所写的一篇
- 前言本文主要给大家分享了关于java文字转语音播报的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧方法如下一、po
- 在 Android 系统中,一般使用 AudioRecord 或者 MediaRecord 来采集音频。AudioRecord 是一个比较偏
- 前言本章是关于Java数组的最全汇总,本篇为汇总中篇,主要讲了二维数组和不规则的数组的相关内容。数组是最常见的一种数据结构,它是相同类型的用
- 基本配置、测试1、导入依赖<dependency> <groupId>org.springframewo
- 项目结构:运行效果:========================================================下面是代
- 包装类包装类其实就是8种基本数据类型对应的引用类型。基本数据类型引用数据类型byteByteshortShortintIntegerlong
- ErrorPageFilter的实际应用Spring框架错误页过滤器springboot提供了一个ErrorPageFilter,用来处理当
- 一、微服务结构微服务这种方案需要技术框架来落地,全球的互联网公司都在积极尝试自己的微服务落地技术。在国内最知名的就是SpringCloud和
- 本文实例讲述了java中response对象用法。分享给大家供大家参考,具体如下:<jsp:forward>动作元素用于运行时在
- Windows的画图板相信很多人都用过,这次我们就来讲讲Java版本的简易画板的实现。基本的思路是这样的:画板实现大致分三部分:一是画板界面
- 问题描述Feign 在请求时是不会将 request 的请求头带着请求的,导致假如 Feign 调用的接口需要请求头的信息,比如当前用户的
- 方法一:利用两个指针p,q,首先将q往链表尾部移动n位,然后再将p、q一起往后移,那么当q达到链表尾部时,p即指向链表的倒数第n个节点。no