<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在spring中設定切面或者資料庫的事務會要求:對具體方法或者是一類特徵相同的方法新增紀錄檔,事務,或者其他對原方法的增強。這時候就會用到pointcut表示式對方法進行過濾,篩選出符合要求的方法;
既然會涉及到篩選具體的方法,那pointcut一定要匹配出完整的方法路徑:全限定類名+方法名;在同一個類中,方法可能被重寫而區分重寫的方法就是:參數列;因此pointcut表示式中必須包含這3部分:全限定類名+方法名+參數列;在spring中還有:存取修飾符,返回值型別;這2個不是必須的;pointcut整體結構:
有了pointcut的整體結構之後就可以根據自己的規則,分別寫這幾部分的正規表示式了;
1.1 ACCESS_MODIFIER 存取修飾符
存取修飾符有四種取值:public,private,protected,defalut; " * " ,對存取修飾符不加限制;
1.2 RETURN_TYPE 返回值型別
返回值型別可以是任意型別:8個基礎型別 + 物件 + 陣列 + void;
最後結合返回值:void, * (表示任意型別);返回值的所有可能取值的正規表示式:(void|PARAM_TYPE|\*)
1.3 CLASS_PATH 全限定類名
有一個特點:(packageName + “.”) * + className;包名,類名都可以用同一個正規表示式;
CLASS_PATH = "((\*?\w+\*?|\*)\.)*(\*?\w+\*?|\*)";
1.4 EXECUTION 表示式
METHOD_NAME,PARAM_LIST這2個的匹配分別參照:全限定類名,返回值型別的正規表示式;將這些部分分別寫完之後,再按順序組合一下就可以得到完整的表示式了;再考慮到,寫表示式的時候,會習慣性的敲空格,因此可以在合適的地方允許空格;
public class PointcutUtils { private static final String ACCESS_MODIFIER = "(public|private|protected|default|\*)"; private static final String RETURN_TYPE; private static final String CLASS_PATH = "((\*?\w+\*?|\*)\.)*(\*?\w+\*?|\*)"; private static final String METHOD_NAME = "(\*?\w+\*?|\*)"; private static final String PARAM_LIST ; private static final String EXECUTION ; //基礎型別 private static final String BASIC_TYPE="(byte|char|boolean|short|int|long|double|float)"; //引數型別 private static final String PARAM_TYPE; static{ //引數型別:基礎型別 + Object + 陣列型別 PARAM_TYPE = "("+BASIC_TYPE+"|[A-Z]\w*)(\[\])*"; //返回值型別:void + 引數型別 RETURN_TYPE="(void|"+PARAM_TYPE+"|\*)"; //參數列 PARAM_LIST = "(\.\.|"+PARAM_TYPE+"(\s*,\s*"+PARAM_TYPE+")*" +"|)"; //execution表示式 EXECUTION = "\s*execution\s*\(\s*"+ACCESS_MODIFIER+"\s+"+RETURN_TYPE+"\s+"+CLASS_PATH+"\s+"+METHOD_NAME+"\(\s*"+PARAM_LIST+"\s*\)\s*"+"\s*\)\s*"; } //檢測pointcut是否是正確的 static boolean checkPointcut(String pointcutReg){ return pointcutReg == null ? false : pointcutReg.matches(EXECUTION); } }
得到的EXECUTION表示式可以用來檢測pointcut表示式是否寫正確;
測試:
String pointcut = "execution ( default int[][] * rr( .. ) ) "; //default存取修飾符,int[][]二維陣列 ; // * 不限定類名; rr 方法名; .. 任意型別的參數列;符合定義的規則,預期結果為 true boolean correct = PointcutUtils.checkPointcut(pointcut ); System.out.println(correct);//結果:true
拆分流程:
程式碼:
//拆分pointcut public static Pointcut parsePointcut(String pointcut){ if(!checkPointcut(pointcut))throw new IllegalArgumentException("execution grammar format error."); String exeReg = getBracketStr(pointcut);//獲取execution();中括號包裹的部分; String paramList = getBracketStr(exeReg).replaceAll(" ",""); int start = exeReg.indexOf("("); exeReg = exeReg.substring(0,start); String[] regs = exeReg.split("\s+"); String accessModifier = regs[0]; String returnType = regs[1]; String classPath = regs[2]; String methodName = regs[3]; return new Pointcut(accessModifier,returnType,classPath,methodName,paramList); } static String getBracketStr(String str){ int start = str.indexOf("("); int end = str.lastIndexOf(")"); return str.substring(start+1,end).trim(); }
分別匹配class和method;在拿到pointcut的時候,如何匹配class和method呢?這個時候要對類路徑的正規表示式做一下處理;比如:pointcut的classpath部分:
"*weqq*.dgdfgfg.df*"
*weqq*:我們希望能匹配到包名含有 weqq的包;直接使用這個作為正規表示式去匹配類路徑肯定是不行的;
* ====》 重複匹配0次或多次前一個字元或者表示式;
如何能達到要求呢?只需要做一下簡單處理就好了:*weqq* ====》 \w*weqq\w*;將 * 替換成 \w* 就可以匹配字元了
還有需要注意的是 ".",在正規表示式中表示匹配任意字元;
而我們希望它只是包的分割符,它只表示" . ",而不需要有任何其他的含義,因此需要將 "."轉換成普通字元 : . ===> \.
匹配class的類名
public static boolean matchClass(Pointcut pointcut,Class cla){ if(pointcut.getClassPath().equals("*"))return true; return cla.getTypeName().matches(pointcut.getClassPath().replaceAll("\*","\\w*").replaceAll("\.","\\.")); }
匹配方法:存取修飾符,返回值,方法名,參數列
public static boolean matchMethod(Pointcut pointcut, Method method){ return matchModifier(pointcut.getAccessModifier(),method) && matchReturnType(pointcut.getReturnType(),method) && matchMethodName(pointcut.getMethodName(),method) && matchParamList(pointcut.getParamList(),method); } static boolean matchModifier(String modifier,Method method){ int modifiers = method.getModifiers(); switch (modifier){ case "default" :return method.isDefault(); case "public" :return Modifier.isPublic(modifiers); case "private" :return Modifier.isPrivate(modifiers); case "protected":return Modifier.isProtected(modifiers); case "*" :return true; default: return false; } } static boolean matchReturnType(String returnType,Method method){ if(returnType.equals("*"))return true; return returnType.equals(method.getReturnType().getSimpleName()); } static boolean matchMethodName(String name,Method method){ if(name.equals("*"))return true; return method.getName().matches(name.replaceAll("\*","\\w*")); } static boolean matchParamList(String paramList,Method method){ if(paramList.equals(".."))return true; Class<?>[] parameterTypes = method.getParameterTypes(); if((paramList.equals("")) ){ if( parameterTypes.length == 0 )return true; else return false; } StringBuilder methodParamList = new StringBuilder(); for (Class<?> parameterType : parameterTypes) { methodParamList.append(","+parameterType.getSimpleName()); } String methodParam = methodParamList.toString().substring(1); return methodParam.equals(paramList); }
同時匹配上類和方法,就可以對方法增強了;其實可以看到在實現pointcut表示式只用到了少量的正規表示式的知識;execution整體拼湊起來有點多,但是分開來看每部分還是簡單的;只需要瞭解簡單的正則和反射,就可以自定義一個pointcut過濾器了。有了這個之後,就可以自己定義實現選擇性AOP了;
到此這篇關於spring的pointcut正規表示式的實現的文章就介紹到這了,更多相關spring pointcut正規表示式內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45