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

网友投稿 439 2022-12-01


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

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

背景

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

场景一:

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

场景二:

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

工厂模式

静态工厂

/**

* @Description

* @Author Singh

* @Date 2020-07-06 21:54

* @Version

**/

@Service

public class HandlerService1 {

public 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 void handle(Class 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 {

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 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 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{

@Override

public void handle(String data) {

}

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:MyBatis开启二级缓存实现过程解析
下一篇:详解SpringBoot Redis自适应配置(Cluster Standalone Sentinel)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~