国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

Mybatis插件

2019-11-08 20:42:37
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

1.插件接口

在Mybatis中使用插件的時(shí)候,就必須實(shí)現(xiàn)Interceptor接口。

public interface Interceptor{

         Objectintercept(Invocation invocation) throws Throwable;

         Objectplugin (Object target);

         voidsetPRoperties(Properties properties);

}

Intercept方法:插件的核心方法,它將直接覆蓋你所攔截對(duì)象原有的方法。參數(shù)Invocation對(duì)象,通過它可以反射調(diào)度原來(lái)對(duì)象的方法。

Plugin方法:target是攔截的對(duì)象,它的作用是給攔截對(duì)象生成一個(gè)代理對(duì)象,并返回它。為了方便Mybatis使用org.apache.ibatis.plugin.Plugin中的wrap靜態(tài)方法提供生成代理對(duì)象,我們往往使用plugin方法便可以生成一個(gè)代理對(duì)象。

setProperties方法:允許在plugin元素中配置所需要的參數(shù),方便在插件初始化的時(shí)候就被調(diào)用一次,然后把插件對(duì)象存存入到配置中,以便以后在取出。

 2. 插件的初始化

插件的初始化是在Mybatis初始化的時(shí)候完成的,這點(diǎn)可以通過xmlConfigBuilder中的代碼可以知道。

publicvoid pluginElment(XNode parent) throws Exception{

if(parent!=null){

           for(XNode child:parent.getChildren()){

                    Stringinterceptor=child.getStringAtrribute("interceptor");

                    Propertiesproperties=child.getChildrenasproperties();

                    Interceptor interceptorInstance=(Interceptor)resolveClass(interceptor).newInstance();

                    interceptorInstance.setProperties(properties);

                    Configuration.addInterceptor(interceptorInstance);

           }

}       

}

     在解析配置文件的時(shí)候,在Mybatis的上下文初始化過程中,就開始讀入插件的節(jié)點(diǎn)和我們配置的信息,同時(shí)使用反射技術(shù)生成對(duì)應(yīng)的插件實(shí)例,然后調(diào)用setProperties方法,設(shè)置我們配置的參數(shù),然后將插件的實(shí)例保存到配置的對(duì)象中,以便以后的讀取和使用它。插件的初始化是在Mybatis的初始化的時(shí)候進(jìn)行的初始化,而不是在使用的時(shí)候才被初始化,這樣可以提高性能。

3. 插件的代理和反射的設(shè)計(jì)

      插件用的是責(zé)任鏈的模式實(shí)現(xiàn)的。

     所謂責(zé)任鏈就是,一個(gè)對(duì)象在Mybatis中可能是四大對(duì)象(Excetor、StatementHandler、ParameterHandler、ResultHandler)中的一個(gè),在多個(gè)角色中傳遞,處在責(zé)任鏈上的任何角色都有處理它的機(jī)會(huì)。

     作用:讓每一個(gè)責(zé)任鏈上的角色都有機(jī)會(huì)去攔截這個(gè)對(duì)象,在將來(lái)有新的角色也可以輕松攔截請(qǐng)求對(duì)象,進(jìn)行處理。

     Mybatis的責(zé)任鏈?zhǔn)怯胕nterceptorChain去定義的。我們知道plugin方法是生成代理對(duì)象的方法,當(dāng)它取出插件的時(shí)候從Configuration對(duì)象中去取出。從第一對(duì)象開始,將對(duì)象傳遞給plugin方法,然后返回一個(gè)代理;如果存在第二個(gè)插件,那么我們就拿到第一個(gè)代理對(duì)象,傳遞給plugin方法在返回第一代理對(duì)象的代理….一次類推,有多少個(gè)攔截器就生成多少個(gè)代理對(duì)象。

     在初始化的時(shí)候,我們一個(gè)個(gè)的加載插件實(shí)例,并用setProperties方法進(jìn)行初始化,我們可以使用Mybatis提供的Plugin.wrap方法來(lái)生成代理對(duì)象,在一層層的使用Invaction對(duì)象的proceed()方法來(lái)推動(dòng)代理對(duì)象的運(yùn)行。在多個(gè)插件的環(huán)境下,調(diào)度proceed()方法時(shí),Mybatis總是從最后一個(gè)代理對(duì)象運(yùn)行到第一代理對(duì)象,最后是真實(shí)被攔截的對(duì)象方法被運(yùn)行。

4.常用的工具類—MeteObject

在Mybatis插件中常用到一個(gè)工具類是MeteObject。

作用:可以有效的讀取或者修改一些重要對(duì)象的屬性。

常用的方法:

MeteObject forObject(Object object,ObjectFactoryobjectFactory,ObjectWrapperFactory objectWrapperFactory);

用于封裝對(duì)象,這個(gè)是已經(jīng)過時(shí)了,現(xiàn)在使用SystemMetaObject(Object obj)

Object getValue(String name)方法:用于獲取對(duì)象的屬性值,支持OGNL。

void setValue(String name,Object value)方法:用于修改對(duì)象的屬性值,支持OGNL。

在Mybatis對(duì)象中大量使用這個(gè)類進(jìn)行包裝,包括四大對(duì)象,使得我們可以通過它來(lái)給四大對(duì)象的某些屬性賦值從而滿足我們的需要。

5.  插件的開發(fā)步驟

(1)確定需要攔截的簽名

A:確定要攔截的對(duì)象

Exector對(duì)象:執(zhí)行SQL全過程,包含組裝參數(shù),組裝結(jié)果集返回和執(zhí)行SQL過程,都可以攔截,較為廣泛,一般在實(shí)際中用的不多。

StatementHandler對(duì)象:執(zhí)行SQL的過程,我們可以重寫執(zhí)行SQL的過程,實(shí)際常用攔截對(duì)象。

ParamterHandler對(duì)象:主要是攔截執(zhí)行SQL的參數(shù)組裝,可以重寫組裝參數(shù)規(guī)則。

ResultSetHandler對(duì)象:主要是攔截執(zhí)行結(jié)果的組裝,可以重寫組裝結(jié)果規(guī)則。

B:攔截的方法和參數(shù)

public interface StatementHandler{

       Statementprepare(Connection connection)throws SQLException;

       voidparameterize(Statement statement)throws SQLException;

       void batch(Statement statement)throwsSQLException;

       int update(Statementstatement)throws SQLException;

       <E>List<E>Query(Statementstatement,ResultHandler resultHandler)throws SQLException;

       BoundSql getBoundSql();

       ParameterHandlergetParameterHandler();

}

定義插件簽名

@Inteceptor({@signature(type=Statement.class,method=”prepare”,args={Connection.class})

})

Public class Myplugin implements Interceptor{

}

   (2)實(shí)現(xiàn)攔截的方法

package com.zl.mybatis.test;

import java.util.Properties;

import org.apache.ibatis.executor.Executor;

importorg.apache.ibatis.mapping.MappedStatement;

importorg.apache.ibatis.plugin.Interceptor;

import org.apache.ibatis.plugin.Intercepts;

import org.apache.ibatis.plugin.Invocation;

import org.apache.ibatis.plugin.Plugin;

import org.apache.ibatis.plugin.Signature; 

/**

 *@author fab

 *

 */

@Intercepts({ @Signature(type =Executor.class, // 確定攔截的對(duì)象

method = "update", // 確定攔截的方法

args = { MappedStatement.class,Object.class }// 確定攔截的參數(shù)

) })

public class MyPlugin implementsInterceptor {

         Propertiesprops = null;

         /**

          * 代替攔截對(duì)象方法的內(nèi)容

          * @param invocation

          *           責(zé)任鏈對(duì)象

          */

         @Override

         publicObject intercept(Invocation invocation) throws Throwable {

                   //TODO Auto-generated method stub

                   System.out.println("before.......");

                   //如果當(dāng)前代理的是一個(gè)非代理對(duì)象,那么它就回調(diào)用真實(shí)攔截對(duì)象的方法,如果不是它將會(huì)調(diào)度下一個(gè)插件代理對(duì)象的invoke方法

                   Objectobject = invocation.proceed();

                   System.out.println("after.....");

                   returnobject;

         }

         /***

          * 生成對(duì)象的代理,這用常用Mybatis提供的Plugin類的wrap方法

          * @param target

          *    被代理的對(duì)象

          */

         @Override

         publicObject plugin(Object target) {

                   //TODO Auto-generated method stub

                   //使用Mybatis提供的Plugin類生成代理對(duì)象

                   System.out.println("調(diào)用生成代理對(duì)象.....");

                   returnPlugin.wrap(target, this);

         }

         /***

          * 獲取插件配置的屬性,在Mybatis的配置文件里面去配置

          * @param props    Mybatis的配置參數(shù)

          *

          */

         @Override

         publicvoid setProperties(Properties props) {

                   //TODO Auto-generated method stub

                   System.out.println(props.get("dbType"));

                   this.props= props;

         }

}

(3)配置

配置插件:

<plugins>

   <plugininteceptor=” com.zl.mybatis.test.MyPlugin”>

     <property name=”dbType” value=”MySQL”>

</plugin>

</plugins>

(4) 運(yùn)行結(jié)果

調(diào)用生成代理對(duì)象.....

before.......

調(diào)用生成代理對(duì)象.....

調(diào)用生成代理對(duì)象.....

調(diào)用生成代理對(duì)象.....

after.....

7.簡(jiǎn)單說

Mybatis插件的實(shí)現(xiàn)方法:

    需要實(shí)現(xiàn)Interceptor接口,實(shí)現(xiàn)三個(gè)方法。

public Object intercept(Invocation invocation);

作用:插件的具體實(shí)現(xiàn)的地方,這是最復(fù)雜的地方。

public Object plugin(Object target);

作用:利用Mybatis自身的Plugin的Wrap()方法來(lái)獲得代理對(duì)象。

public void setProperties(Properties props);

作用:初始化一些基本設(shè)置,這些配置在Mybatis的.xml文件中體現(xiàn)。

需要明確:攔截那個(gè)對(duì)象,攔截那個(gè)方法,攔截那個(gè)參數(shù)。

8.總結(jié)

使用插件應(yīng)注意的六點(diǎn):

(1)  能不用插件盡量不用插件,因?yàn)樗鼘⑿薷腗ybatis的底層設(shè)計(jì)。

(2)      插件生成的是層層代理對(duì)象的責(zé)任鏈模式,通過反射方法運(yùn)行,性能不高,所以減少插件就能減少代理,從而提高系統(tǒng)的性能。

(3)      編寫插件需要了解Mybatis的運(yùn)行原理,了解四大對(duì)象及其方法的作用,準(zhǔn)確判斷需要攔截什么對(duì)象,什么方法,參數(shù)是什么,才能確定簽名如何編寫。

(4)    在插件中往往需要讀取和修改Mybatis映射器的對(duì)象屬性,你需要熟練掌握關(guān)于Mybatis映射器內(nèi)部組成的知識(shí)。

(5)   插件的編寫需要考慮全面,特別是多個(gè)插件層層代理的時(shí)候,要保證邏輯的正確性。

(6)    盡量小改動(dòng)Mybatis底層的東西,以減少錯(cuò)誤的發(fā)生。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 城步| 民县| 浑源县| 平利县| 丹东市| 健康| 万年县| 望城县| 元谋县| 鹤峰县| 安西县| 丹东市| 长武县| 江阴市| 绥中县| 沁源县| 同心县| 西吉县| 舒城县| 康马县| 响水县| 鄱阳县| 民权县| 玛曲县| 甘谷县| 虹口区| 巨野县| 临城县| 阳泉市| 大荔县| 海丰县| 加查县| 永仁县| 武宁县| 鄂伦春自治旗| 凤山县| 双江| 文安县| 东丰县| 安溪县| 奈曼旗|