最近學習Spring的源碼,發現一個利器BeanPostProcessor。這個后置處理器可以在bean初始化前后對bean進行操作。我們可以在初始化的時候對自己想要的bean進行緩存,進而實現自己需要處理的邏輯。
背景
當我們需要根據類型調用接口不同實現的時候,我們可以使用工廠模式實現。下面說下博主遇到過的兩次需要使用工廠的場景。
場景一:
當有一個模塊,我們需要根據數據庫的類型實現不同的的sql。我們此時需要定義一個接口然后每一種數據庫實現不同的sql。在調用時根據當前的數據庫類型調用對應的實現類。
場景二:
我們業務需要對接不同的傳感器設備,但是總體業務邏輯就是獲取數據,發送心跳。每一種設備的數據協議又不一樣。所以需要使用工廠,根據不同的設備調用對應的實現類。
工廠模式
靜態工廠
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
/** * @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實現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/** * @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的處理類型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@Target ({ElementType.TYPE}) @Retention (RetentionPolicy.RUNTIME) @Documented @Component public @interface Handler { @AliasFor (annotation = Component. class ) String value() default "" ; /** * 業務處理類型 * @return */ Constant.HandlerType handlerType(); } |
處理類型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
/** * @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; } } } |
定義接口處理
1
2
3
4
5
6
7
8
9
10
11
|
/** * @Description * @Author Singh * @Date 2020-07-06 21:29 * @Version **/ public interface IHandler<T> { void handle(T data); } |
BeanPostProcessor實現對bean后置處理。通過注解的類型緩存bean對象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
/** * @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); } } |
自定義處理器實現,每一種實現一次。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/** * @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 工廠模式內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/m0_37954663/article/details/107168564