Java基礎----jdk1.8 反射實驗


(寫在最前:還沒入門的搬磚工的一本正經的胡說八道)

引言:  最近做到的項目中,需要給對接方提供一個公共接口,根據對方傳入的XML文件的rootelement分發調用接口,最簡單的使用if-else if 模式,但是看着實在太蠢。

場景一:需要根據關鍵字,進行接口分發

使用if-else模式缺點:

  1. 看着蠢
  2. 不易閱讀(個人觀點)
  3. 不易維護
  4. balabala...不想編了,就是看着不爽

如果只有一兩個方法還好,如果方法多了,額。。。如下,自行體會。

 1 public class TestMethod {
 2 
 3     public Object dispatchMethod(String name, String data) {
 4         Object obj = null;
 5 
 6         if ("methodA".equal(name)) {
 7             obj = methodA(data);
 8         } else if ("methodB".equal(name)) {
 9             obj = methodB(data);
10         } else if (...) {
11             ...
12         }
13         return obj;
14     }
15 
16     private Object methodA(String data) {
17         ...
18     }
19 
20     private Object methodB(String data) {
21         ...
22     }
23 
24     ...
25 }

那么步入正題,我才用的反射模式,匹配目標方法,我認為可以降低維護和閱讀成本

開發環境:jdk1.8

實現代碼:

  • 定義目標方法枚舉,包含rootelement信息,調用方法說明,目標方法targetName
 1 public enum MethodEnum {
 2 
 3     METHODA("MethodA","調用方法A","methodA"),
 4     METHODB("MethodB","調用方法B","methodB"),
 5     ;
 6     
 7     @Getter
 8     private String code; //rootelement
 9     
10     @Getter
11     private String message; 
12     
13     @Getter
14     private String name; //目標方法名
15 
16     private MethodEnum (String code,String message,String name) {
17         this.code = code;
18         this.message = message;
19         this.name = name;
20     }
21     
22     public static MethodEnum fromCode(String code) { //根據傳入code,篩選目標方法
23         for (DockingFliggyHotelEnum p : DockingFliggyHotelEnum.values()) {
24             if(p.code.equalsIgnoreCase(code)) {
25                 return p;
26             }
27         }
28         return null;
29     } 
32 }
  • 定義反射方法工具類
 1 /**
 2  *  定義工具類 
 3 **/
 4 public class MethodUtil {
 5 
 6     public static Method getTargetMethod(Class clazz, String methodName) {
 7         Method[] methods = clazz.getDeclaredMethods(); //獲取所有方法,包含private
 8         if (methods != null && methods.length > 0) {
 9             String regEx  = "^" + methodName +"$";//獲取所要查找到的方法名稱要匹配此正則
10             Pattern pattern = Pattern.compile(regEx);
11             for (Method method : methods) {
12                 Matcher matcher = pattern.matcher(method.getName());
13                 boolean rs = matcher.find();
14                 if(rs){
15                     return method;
16                 }
17             }
18         }
19         return null;
20     }
21 
22     public static Object executeTargrtMethod(Class clazz, String methodName, String xmlData) {
23         Object obj = null;
24         try {
25             Method method = getTargetMethod(clazz, methodName);
26             obj = method.invoke(clazz, xmlData);
27         } catch (Exception e) {
28             
29         }
30         return obj;
31     }
32 
33 }
  • 具體分發
 1 public class TestDispatch {
 2 
 3     public Object dispatch(String root, String xml) {
 4         String name = MethodEnum.fromCode(root).name;
 5         Object obj = executeTargrtMethod(this.getClass(), name, xml)
 6         return obj;
 7     }
 8 
 9     private Object methodA(String xml) {
10         Object obj = null;
11         ...
12         return obj;
13     }
14 
15     private Object methodB(String xml) {
16         Object obj = null;
17         ...
18         return obj;
19     }
20 
21     ...
22 }

對於業務代碼結構清晰明了,是不是看着爽多了。

對於類似的場景很多,都可以使用反射機制。

場景二:項目中多處需要大批量插入數據,提取一個公共方法,減少代碼行數,何樂而不為呢?

對了,順便說一下這個批量插入方法,數據庫使用mysql,項目框架springboot,jdk1.8,5000條數據插入一次,耗時0.8s左右。

 1    /**
 2      * @param batchCount 一次批量插入數據量
 3      * @param target 目標方法關鍵字
 4      * @param list 需要插入的大批量數據
 5      * @throws Exception
 6      */
 7     public static void batchInsert(Class clazz, int batchCount, String target, List<?> list) throws Exception{
 8         Method method = getTargetMethod(target);
 9         int batchLastIndex = batchCount - 1;//每批最后一個的下標
10         for(int index = 0; index < list.size()-1;){
11             if(batchLastIndex > list.size()-1){
12                 batchLastIndex = list.size() - 1;
13                 if (method != null) {
14                     method.invoke(clazz,list.subList(index, batchLastIndex));
15                 }
16                 break;//數據插入完畢,退出循環
17             }else{
18                 if (method != null) {
19                     method.invoke(clazz,list.subList(index, batchLastIndex));
20                 }
21                 index = batchLastIndex + 1;//設置下一批下標
22                 batchLastIndex = index + (batchCount - 1);                
23             }                
24         }
25     }

實驗結束,代碼分析下次在寫了。

寫在最后

代碼是偽代碼,可能啥地方寫得不對,歡迎指正

對於以上兩種場景,我目前只能想到這種方法。。。如果你有更好的,歡迎來懟我


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM