http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.htmlcss
mybatis的原身是ibatis,如今已經脫離了apache基金會,新官網是http://www.mybatis.org/。
html
2.定義拼裝sql的類java
3.無參數@SelectProvide方法
在Mapper接口方法上和@SelectProvide指定類方法上,均無參數:
UserMapper.java:spring
4.一個參數的@SelectProvide方法
對於只有一個參數的狀況,能夠直接使用,參見前面的getUser和selectUser。
可是,若是在getUser方法中,對userId方法使用了@Param註解的話,那麼相應selectUser方法必須接受Map<String, Object>作爲參數:
UserMapper.java:sql
SqlProvider.java:數據庫
5.更多參數的@SelectProvide方法
在超過一個參數的狀況下,@SelectProvide方法必須接受Map<String, Object>作爲參數,
若是參數使用了@Param註解,那麼參數在Map中以@Param的值爲key,以下例中的userId;
若是參數沒有使用@Param註解,那麼參數在Map中以參數的順序爲key,以下例中的password:apache
http://www.blogjava.net/dbstar/archive/2011/08/08/355825.html編程
最近在總結過去一年所作的項目,因爲開發週期或者對需求的把握不是太到位,每一個項目隨着所作的項目進度,從需求分析到code階段總或多或少有一些本身感受不是太完美或沒有盡善盡美的地方,使用開源框架和第三方接口只知道接口調用,對於其內部實現機理老是存在疑惑(這傢伙是怎麼作的,我怎麼沒有想到),雖然各個項目完成後一瘸一拐的仍是能知足當初的開發需求。可是對於追求完美、刨根問底性選手,心中總有根刺,感受不爽(不知道你們有沒有這種感受)。下面經過本身的理解使用java原生的註解方式實現 spring aop的運行機理 (還沒看過spring /mybatis的源代碼,過年的時候研究一下大俠們有好的想法能夠共享一下,話說獨樂樂不如衆樂樂哦)數組
先說說spring AOP使用上的一些限制:緩存
1.若是切點函數有重載時,定義的通知類中方法不能實現方法重載
2.spring AOP只支持方法層面的切口定義,固然這個也是spring的基本原則如spring mvc 與struts2的區別之一就是spring mvc是基於方法的設計struts2是基於類的設計;
3.spring aop 不支持參數級的切口定義,若有時候須要對傳入切口的參數進行安全性,規範性、合法性處理的時候是不支持的。固然對參數處理涉及到解析參數類型獲取、參數類型判斷,對於使用反射機制獲取這個是有必定難度滴。
下面經過詳細的代碼,來說解如何經過使用java的annotation自定義切點接口和經過反射機制實現spring AOP機制。
class層註解定義:
用途:類接口切點註解定義
package com.dbc.yangg.project;
import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * * @ClassName: MyClassAnnotation * @Description: 類層註解定義 * @author guoyang2011@gmail.com * @date 2014年1月18日 下午11:37:51 * */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface MyClassAnnotation { String value() default "firstAnno"; }
method層advice定義相似於Spring AOP中@Before,@After,@Around,@AfterThrowing,@AfterReturning等
用途:方法切點接口註解定義
package com.dbc.yangg.project;
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * * @ClassName: MySecondMethodAnnotation * @Description: 方法層註解定義 * @author guoyang2011@gmail.com * @date 2014年1月18日 下午11:44:44 * */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyPointcutAnnotation { /** * * @Title: className * @Description: TODO * @param @return advicer class type * @return Class<?> * @throws */ Class<?> className(); /** * * @Title: method * @Description: TODO * @param @return advicer method name * @return String * @throws */ String method();// }
method parameters 層advicer定義相似mybatis中@Param註解
功能:參數層面切點接口註解定義
package com.dbc.yangg.project;
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * * @ClassName: MyParameterAnnotation * @Description: 方法中參數層註解定義 * @author guoyang2011@gmail.com * @date 2014年1月18日 下午11:45:15 * */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface MyParameterAnnotation { /** * * @Title: opType * @Description: method 參數類型檢查 * @param @return * @return MyAopParameterOPType[] * @throws */ MyAopParameterOPType[] opType(); /** * * @Title: paraType * @Description: method 參數類型 * @param @return * @return Class<?> * @throws */ Class<?> paraType(); }
處理MyAopParameterOPType類型定義
功能:定義參數切口定義註解處理的類型
package com.dbc.yangg.project;
/** * * @ClassName: MyAopParameterOPType * @Description: TODO * @author guoyang2011@gmail.com * @date 2014年1月18日 下午12:07:25 * */ public enum MyAopParameterOPType { checkForDB("DB"),//特殊字符處理 ,通用轉碼或者其餘處理 checkForSecurity("security"),//參數是否合法等操做 checkDeleteAuthority("DeleteAuthority"), checkUpdateAuthority("UpdateAuthority"); private String value; private MyAopParameterOPType(String value){ this.value=value; } public String getValue(){ return this.value; } }
主要功能:自定義AOP處理類,負責解析實際調用切點函數定義的通知
package com.dbc.yangg.project;
import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.apache.ibatis.annotations.SelectProvider; /** * * @ClassName: MyAOPUtils * @Description: * @author guoyang2011@gmail.com * @date 2014年1月18日 下午12:01:05 * */ public class MyAOPUtils { /** * * @Title: myAopUtilsManager * @Description: 切點函數參數觸發通知事件,全部通知事件的處理接口 * @param @param advicerManagerClass * @param @param indexArg * @param @param paraValues * @param @param paraTypes * @param @return * @return boolean * @throws */ private static boolean parameterAdvicerUtils(Annotation advicerManagerClass,int indexArg,Object[] paraValues, Class<?>... paraTypes){ if(advicerManagerClass instanceof MyPointcutAnnotation){ //接口參數驗證經過後執行 //切點通知處理 MyPointcutAnnotation AdvicerClass=(MyPointcutAnnotation)advicerManagerClass; Class<?> adviceClass=AdvicerClass.className(); try { Method adviceMethod=adviceClass.getMethod(AdvicerClass.method(),paraTypes); adviceMethod.invoke(adviceClass.newInstance(), paraValues); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } }else if(advicerManagerClass instanceof MyParameterAnnotation){ //對輸入的參數作一些通用處理和安全性檢查等等 //通常用在DAO層sql拼裝特殊字符檢查,數據格式合法性檢查,轉碼或對調用者使用定義切點接口使用權限,安全性,等信息進行檢查和確認等場合;當切點參數經過通知類中定義的接口處理後再調用切點方法;如MyBatis中經過註解@SelectProvider方式生成合法的SQL語句須要對拼裝的sql語句傳入的參數進行驗證等,還有就是從安全新考慮對傳入的模塊調用者身份進行檢查,MyBatis經過註解方式定義接口實現動態SQL生成中關鍵就是對數據類型的解析 if(indexArg<0){ return true; } MyParameterAnnotation AdvicerClass=(MyParameterAnnotation)advicerManagerClass; //處理切點方法參數的通知,大概思路以下: //1.解析參數類型 //2.獲取參數值 //3.調用通知處理接口檢查參數合法性 //4.返回檢查結果 true:false } return true; } /** * * @Title: myAopUtilsManager * @Description: Pointcut method execute advice interface * @param @param advicerManagerClass 類型 * @param @param paraValues pointcut傳入參數 * @param @param paraTypes pointcut傳入參數類型 * @return void * @throws */ private static boolean methodAdvicerUtils(Annotation advicerManagerClass,Object[] paraValues, Class<?>... paraTypes){ return parameterAdvicerUtils(advicerManagerClass,-1,paraValues,paraTypes);