詳解使用Spring的BeanPostProcessor優(yōu)雅的實現(xiàn)工廠模式
最近學(xué)習(xí)Spring的源碼,發(fā)現(xiàn)一個利器BeanPostProcessor。這個后置處理器可以在bean初始化前后對bean進(jìn)行操作。我們可以在初始化的時候?qū)ψ约合胍腷ean進(jìn)行緩存,進(jìn)而實現(xiàn)自己需要處理的邏輯。
背景
當(dāng)我們需要根據(jù)類型調(diào)用接口不同實現(xiàn)的時候,我們可以使用工廠模式實現(xiàn)。下面說下博主遇到過的兩次需要使用工廠的場景。
場景一:
當(dāng)有一個模塊,我們需要根據(jù)數(shù)據(jù)庫的類型實現(xiàn)不同的的sql。我們此時需要定義一個接口然后每一種數(shù)據(jù)庫實現(xiàn)不同的sql。在調(diào)用時根據(jù)當(dāng)前的數(shù)據(jù)庫類型調(diào)用對應(yīng)的實現(xiàn)類。
場景二:
我們業(yè)務(wù)需要對接不同的傳感器設(shè)備,但是總體業(yè)務(wù)邏輯就是獲取數(shù)據(jù),發(fā)送心跳。每一種設(shè)備的數(shù)據(jù)協(xié)議又不一樣。所以需要使用工廠,根據(jù)不同的設(shè)備調(diào)用對應(yīng)的實現(xiàn)類。
工廠模式
靜態(tài)工廠
/**
* @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);
}
}
動態(tài)工廠,通過class實現(xiàn)
/**
* @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);
}
}
進(jìn)入主題
BeanPostProcessor實現(xiàn)相同接口的不同實現(xiàn)bean的工廠
首先定義一個注解,后續(xù)用來標(biāo)示bean的處理類型
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Handler {
@AliasFor(annotation = Component.class)
String value() default "";
/**
* 業(yè)務(wù)處理類型
* @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實現(xiàn)對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);
}
}
自定義處理器實現(xiàn),每一種實現(xiàn)一次。
/**
* @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) {
}
}
到此這篇關(guān)于詳解使用Spring的BeanPostProcessor優(yōu)雅的實現(xiàn)工廠模式的文章就介紹到這了,更多相關(guān)Spring BeanPostProcessor 工廠模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Spring BeanPostProcessor接口使用詳解
- Spring中的后置處理器BeanPostProcessor詳解
- SpringBoot之通過BeanPostProcessor動態(tài)注入ID生成器案例詳解
- Spring BeanPostProcessor(后置處理器)的用法
- Spring?BeanPostProcessor后處理器源碼解析
- Spring探秘之如何妙用BeanPostProcessor
- Spring源碼解析之BeanPostProcessor知識總結(jié)
- Spring BeanPostProcessor源碼示例解析
- Spring注解驅(qū)動之BeanPostProcessor后置處理器講解
- Spring組件初始化擴展點:BeanPostProcessor
相關(guān)文章
Java 并發(fā)編程之ThreadLocal詳解及實例
這篇文章主要介紹了Java 并發(fā)編程之ThreadLocal詳解及實例的相關(guān)資料,需要的朋友可以參考下2017-02-02
MyBatis使用標(biāo)簽動態(tài)操作數(shù)據(jù)庫詳解
這篇文章主要介紹了MyBatis中使用標(biāo)簽動態(tài)操作數(shù)據(jù)庫的方法,動態(tài)SQL是指在運行PL/SQL塊時動態(tài)輸入SQL語句,是Mybatis的強大特性之?,能夠完成不同條件下不同的sql拼接,需要的朋友可以參考下2024-05-05
spring @Scheduled定時任務(wù)注解使用方法及注意事項小結(jié)
Spring的@Scheduled注解用于定時任務(wù)調(diào)度,默認(rèn)單線程依次執(zhí)行,可以通過配置多線程調(diào)度器或使用@Async注解實現(xiàn)并行執(zhí)行,常見參數(shù)包括cron、fixedRate、fixedDelay、initialDelay等,本文介紹spring @Scheduled定時任務(wù)注解使用方法,感興趣的朋友一起看看吧2025-02-02

