1. 程式人生 > 程式設計 >詳解使用Spring的BeanPostProcessor優雅的實現工廠模式

詳解使用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 工廠模式內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!