mybatis动态代理
文章目錄
- 動態SQL
- if關鍵字
- where 標簽
- where和if聯合使用
- set標簽
- trim標簽
- foreach標簽
- 動態代理
- JDK自帶動態代理
- CGLib代理
- 演示
- MyBatis中的動態代理
動態SQL
采用OGNL表達式來進行SQL的淘汰不需要的元素。根據不同的添加進行動態的SQL的組裝和拼接
if關鍵字
if標簽:包含test表達式 必填,通過ognl表達式進行判斷,true和false,
如果為真,會執行if中的SQL
如果為假,則不執行if中的SQL
where 標簽
where標簽作用:如果where標簽包含了具有返回值時,就會插入一個where,如果where后面的字符串以and 和or開頭的,則將他剔除
where和if聯合使用
where表達式一般和if表達式一塊使用,如果一個條件都不滿足,則不拼接where到SQL中,如果有一個或者多個if表達式成立,where會直接拼接在SQL上,并且緊隨where的表達式的and或者or會被忽略
<select id="selectClass" resultType="org.example.pojo.Class">select * from<where><if test="c_id!=null">and c_id=#{c_id}</if><if test="c_name!=c_name">and c_name=#{c_name}</if></where>如果傳入c_id則SQL語句為: select * from wherec_id=#{c_id}
兩個都傳入則SQL語句為:select * from c_id=#{c_id}
set標簽
set標簽的作用,如果set標簽中的元素有返回值,就插入一個set,如果set后的字符串以逗號為結尾,則將最后的逗號剔除
set標簽和if表達式一塊使用,如果有條件滿足時,會直接拼接一個set到SQL上,并將最后一個SQL的逗號去掉
trim標簽
trim標簽使用來去除SQL語句中多余的and關鍵字、逗號,或者給SQL拼接的where、set或者values等前后綴,可以選擇性的進行插入、更顯,或者添加查詢操作
*prefix:前綴
prefixoverride:去掉第一個and或者是or
suffix:后綴
suffixoverride:去掉最后一個逗號(也可以是其他的標記,就像是上面前綴中的and一樣)
foreach標簽
批量處理
如:
insert table_name (id,name,age) values((1,1,1),(2,2,2))
select * from Student where SID in(1,2,3,4,5);
foreach標簽實現批量數據處理,遍歷集合對象
各屬性解釋
動態代理
代理模式是設計模式之一
委托類(RealSubject):真正實現功能或者提供真實服務
代理類(Proxy):并不提供真正實現服務,而是通過調用委托類的對象的相關方法提供特定服務,可以在該服務基礎上提供一些其他的服務
subject:代理類和委托類共有的接口或者服務,提供了代理類和委托類共有方法
Client需要的服務是是通過代理類來獲取的,而真正的服務是有委托類提供的
JDK自帶動態代理
接口:
/*** 代理類和委托類共有的接口*/ public interface Iuser {void eate(); }委托類:
/*** 委托類:具體實現接口中方法*/ public class User implements Iuser{@Overridepublic void eate() {System.out.println("User實現了eate方法");} }代理輔助類:
/*** 代理輔助類* 要實現動態代理,則需要給定一個實現類invocationHandler接口的實現類* 該類中需要持有IUser實現類的引用*/ public class UserProxy implements InvocationHandler {private Iuser user;public UserProxy(Iuser user){this.user=user;}/*** 實現InvocationHandler接口* 重寫invoke方法* @param proxy :產生的代理對象* @param method:調用的方法* @param args :表示方法的參數* @return* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("代理類自定義業務邏輯1");//調用委托類的方法method.invoke(user,args);System.out.println("代理類自定義業務邏輯2");return null;}產生代理類的形式:
public static void main(String[] args) {/*** ClassLoader loader,指定代理輔助類的加載器* Class<?>[] interfaces,當前被代理的接口* InvocationHandler h :代理輔助類*///產生的代理類Iuser user = (Iuser) Proxy.newProxyInstance(UserProxy.class.getClassLoader(), new Class[]{Iuser.class}, new UserProxy(new User()));user.eate();}運行結果:
通過分析:動態打理的對象的產生通過Proxy.newProxyInstance()調用產生了代理對象
代理對象調用eate方法,通過打印結果可知,其調用了invocationHandler輔助類的invoke方法,該方法下來調用委托類User的eate實現
CGLib代理
JDK自帶的動態代理使用比較簡單,缺點也是明顯的,需要目標對象實現一個或多個接口
當代理沒有接口的類,此時Proxy和InvocationHandler機制就不能使用了,此時就需要使用cglib
cglib采用字節碼技術,通過對字節碼為一個類創建子類,并在子類中采用方法攔截的技術,攔截所有父類方法的調用,順勢織入橫切技術
AOP技術的實現是使用到了JDK自帶的動態代理和CGLib動態代理的
演示
引入依賴:
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.2.2</version></dependency>委托類:
public class CCGlibSuper {public void doing(){System.out.println("委托類");} }輔助類:
/*** 產生CGlib代理對象的輔助類* 實現MethodInterceptor* 該接口中的intercept方法需要實現*/ public class CGLibProxy implements MethodInterceptor {private Enhancer enhancer = new Enhancer();public <T> T getProxy(Class<T> tClass){//設置父類enhancer.setSuperclass(tClass);enhancer.setCallback(this);//通過字節碼技術創建子類實例return (T)enhancer.create();}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("代理類使用前");Object o1 = methodProxy.invokeSuper(o, objects);System.out.println("代理類使用后");return o1;}public static void main(String[] args) {CGLibProxy cgLibProxy = new CGLibProxy();CCGlibSuper proxy = cgLibProxy.getProxy(CCGlibSuper.class);proxy.doing();} }MyBatis中的動態代理
MyBatis中使用的是 JDK自帶動態代理模式
添加接口信息如下
addMapper方法實現:
Configuration類:
mapper實際上被添加到了mapperRegistry中
MapperRegistry類:
mybatis在執行configuration.addMapper(StudentMapper.class),最終將接口信息放到HashMap中,名稱為knownMappers,knownMappers是MapperRegistry類的私有屬性,是一個HashMap,key為當前class對象,value為一個MapperProxyFactory類型的實例
繼續看getMapper的代碼跟蹤
//通過動態代理機制(反射)產生了一個代理類(重點:動態代理模式,源碼實現)StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);getMapper實現類通過debug測試確定為DefaultSQLSession類
DefaultSQLSession類:
該代碼直接調用Configuration類中的getMapper方法
Configuration類:
通過代碼是通過Proxy.newProxyInstance產生了一個StudentMapper接口的代理對象,mybatis為了完成mapper接口的實現運用了代理模式
總結
以上是生活随笔為你收集整理的mybatis动态代理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: netty使用
- 下一篇: mybatis缓存机制