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

   日期:2020-07-08     浏览:98    评论:0    
核心提示:最近学习Spring的源码,发现一个利器BeanPostProcessor。这个后置处理器可以在bean初始化前后对bean进行操作。我们可以在初始化的时候对自己想要的bean进行缓存,进而实现自己需要处理的逻辑。背景当我们需要根据类型调用接口不同实现的时候,我们可以使用工厂模式实现。下面说下博主遇到过的两次需要使用工厂的场景。场景一:当有一个模块,我们需要根据数据库的类型实现不同的的sql。我们此时需要定义一个接口然后每一种数据库实现不同的sql。在调用时根据当前的数据库类型调用对应的实现类。

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

背景

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

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

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

工厂模式

静态工厂


@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实现


@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的工厂

  1. 首先定义一个注解,后续用来标示bean的处理类型
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Handler {

    @AliasFor(annotation = Component.class)
    String value() default "";

    
    Constant.HandlerType handlerType();

}
  1. 处理类型


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;
        }

    }

}
  1. 定义接口处理

public interface IHandler<T> {

    void handle(T data);

}

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

@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);
    }

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

@Handler(handlerType = Constant.HandlerType.HANDLE_TYEP_1 )
public class Type1Handler implements IHandler<String>{

    @Override
    public void handle(String data) {

    }
}
 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服