欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

mybatis 自定義實(shí)現(xiàn)攔截器插件Interceptor示例

 更新時(shí)間:2020年10月26日 15:59:39   作者:溪~源  
這篇文章主要介紹了mybatis 自定義實(shí)現(xiàn)攔截器插件Interceptor,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

首先熟悉一下Mybatis的執(zhí)行過(guò)程,如下圖:

在這里插入圖片描述

類(lèi)型

先說(shuō)明Mybatis中可以被攔截的類(lèi)型具體有以下四種:

1.Executor:攔截執(zhí)行器的方法。
2.ParameterHandler:攔截參數(shù)的處理。
3.ResultHandler:攔截結(jié)果集的處理。
4.StatementHandler:攔截Sql語(yǔ)法構(gòu)建的處理。

規(guī)則

Intercepts注解需要一個(gè)Signature(攔截點(diǎn))參數(shù)數(shù)組。通過(guò)Signature來(lái)指定攔截哪個(gè)對(duì)象里面的哪個(gè)方法。@Intercepts注解定義如下:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Intercepts {
 /**
  * 定義攔截點(diǎn)
  * 只有符合攔截點(diǎn)的條件才會(huì)進(jìn)入到攔截器
  */
 Signature[] value();
}

Signature來(lái)指定咱們需要攔截那個(gè)類(lèi)對(duì)象的哪個(gè)方法。定義如下:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({})
public @interface Signature {
 /**
 * 定義攔截的類(lèi) Executor、ParameterHandler、StatementHandler、ResultSetHandler當(dāng)中的一個(gè)
 */
 Class<?> type();

 /**
 * 在定義攔截類(lèi)的基礎(chǔ)之上,在定義攔截的方法
 */
 String method();

 /**
 * 在定義攔截方法的基礎(chǔ)之上在定義攔截的方法對(duì)應(yīng)的參數(shù),
 * JAVA里面方法可能重載,故注意參數(shù)的類(lèi)型和順序
 */
 Class<?>[] args();
}

標(biāo)識(shí)攔截注解@Intercepts規(guī)則使用,簡(jiǎn)單實(shí)例如下:

@Intercepts({//注意看這個(gè)大花括號(hào),也就這說(shuō)這里可以定義多個(gè)@Signature對(duì)多個(gè)地方攔截,都用這個(gè)攔截器
  @Signature(
    type = ResultSetHandler.class,
    method = "handleResultSets", 
    args = {Statement.class}),
  @Signature(type = Executor.class,
    method = "query",
    args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})

說(shuō)明:
@Intercepts:標(biāo)識(shí)該類(lèi)是一個(gè)攔截器;
@Signature:指明自定義攔截器需要攔截哪一個(gè)類(lèi)型,哪一個(gè)方法;
- type:上述四種類(lèi)型中的一種;
- method:對(duì)應(yīng)接口中的哪類(lèi)方法(因?yàn)榭赡艽嬖谥剌d方法);
- args:對(duì)應(yīng)哪一個(gè)方法的入?yún)ⅲ?/p>

method中對(duì)應(yīng)四種的類(lèi)型的方法:

攔截類(lèi)型 攔截方法
Executor update, query, flushStatements, commit, rollback,getTransaction, close, isClosed
ParameterHandler getParameterObject, setParameters
StatementHandler prepare, parameterize, batch, update, query
ResultSetHandler handleResultSets, handleOutputParameters

介紹

談到自定義攔截器實(shí)踐部分,主要按照以下三步:

實(shí)現(xiàn)org.apache.ibatis.plugin.Interceptor接口,重寫(xiě)以下方法:

public interface Interceptor {
 Object intercept(Invocation var1) throws Throwable;
 Object plugin(Object var1);
 void setProperties(Properties var1);
}

添加攔截器注解@Intercepts{...}。具體值遵循上述規(guī)則設(shè)置。

配置文件中添加攔截器。

 intercept(Invocation invocation)

從上面我們了解到interceptor能夠攔截的四種類(lèi)型對(duì)象,此處入?yún)?code>invocation便是指攔截到的對(duì)象。
舉例說(shuō)明:攔截**StatementHandler#query(Statement st,ResultHandler rh)**方法,那么Invocation就是該對(duì)象。

plugin(Object target)

這個(gè)方法的作用是就是讓mybatis判斷,是否要進(jìn)行攔截,然后做出決定是否生成一個(gè)代理。

@Override
 public Object plugin(Object target) {
 //判斷是否攔截這個(gè)類(lèi)型對(duì)象(根據(jù)@Intercepts注解決定),然后決定是返回一個(gè)代理對(duì)象還是返回原對(duì)象。
//故我們?cè)趯?shí)現(xiàn)plugin方法時(shí),要判斷一下目標(biāo)類(lèi)型,如果是插件要攔截的對(duì)象時(shí)才執(zhí)行Plugin.wrap方法,否則的話(huà),直接返回目標(biāo)本身。
  if (target instanceof StatementHandler) {
   return Plugin.wrap(target, this);
  }
  return target;
 }

注意:每經(jīng)過(guò)一個(gè)攔截器對(duì)象都會(huì)調(diào)用插件的plugin方法,也就是說(shuō),該方法會(huì)調(diào)用4次。根據(jù)@Intercepts注解來(lái)決定是否進(jìn)行攔截處理。

setProperties(Properties properties)

攔截器需要一些變量對(duì)象,而且這個(gè)對(duì)象是支持可配置的。

實(shí)戰(zhàn)

自定義攔截器

@Intercepts(value = {@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class MyInterceptor implements Interceptor {

 @Override
 public Object intercept(Invocation invocation) throws Throwable {
  StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
  BoundSql boundSql = statementHandler.getBoundSql();
  Object obj = boundSql.getParameterObject();
  String sql = boundSql.getSql();
  if (sql.trim().toUpperCase().startsWith("INSERT")) {
   ReflectUtil.setFieldValue(obj, "rev", 0);
   ReflectUtil.setFieldValue(obj, "createTime", new Date());
   ReflectUtil.setFieldValue(obj, "operateTime", new Date());
   ReflectUtil.setFieldValue(boundSql,"parameterObject", obj);

  } else if (sql.trim().toUpperCase().startsWith("UPDATE")) {
   sql = sql.replaceAll(" set ", " SET ")
     .replaceAll(" Set ", " SET ")
     .replaceAll(" SET ", " SET rev = rev+1, operate_time = NOW(), ");
   ReflectUtil.setFieldValue(boundSql,"sql", sql);
  }
  return invocation.proceed();
 }

 @Override
 public Object plugin(Object o) {
  return Plugin.wrap(o, this);
 }

 @Override
 public void setProperties(Properties properties) {

 }
}

主要看下核心代碼方法intercept():
這段代碼主要目的:攔截insert和update語(yǔ)句,利用反射機(jī)制,設(shè)置insert語(yǔ)句的參數(shù)rev(版本號(hào),利用樂(lè)觀鎖),第一次查詢(xún),故創(chuàng)建時(shí)間和操作時(shí)間相同;update是將版本號(hào)+1,統(tǒng)一修改其操作時(shí)間。

mybatis-config

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration> 
	<plugins>
  <plugin interceptor="com.qxy.mybatis.interceptor.MyInterceptor"/>
 </plugins>

</configuration>

application.yml
特別重要的一點(diǎn),一定將mybatis-config中的對(duì)象注入到Sprint容器中,否則不會(huì)生效。

...//省略其他配置
mybatis:
 config-location: classpath:/mybatis-config.xml

ReflectUtil

...//省略其他配置
mybatis:
 config-location: classpath:/mybatis-config.xml

debug

在這里插入圖片描述

上圖中能夠看到BoundSql對(duì)象中主要存儲(chǔ)的屬性值,所以我們自定義攔截器時(shí),主要針對(duì)BoundSql的屬性值進(jìn)行修改。
程序代碼沒(méi)有走到我們反射機(jī)制設(shè)置值的位置,測(cè)試createTime=null;

在這里插入圖片描述

返回之前,看下BoundSql對(duì)象的值,創(chuàng)建時(shí)間已被賦值。

在這里插入圖片描述

源代碼:https://github.com/stream-source

到此這篇關(guān)于mybatis 自定義實(shí)現(xiàn)攔截器插件Interceptor的文章就介紹到這了,更多相關(guān)mybatis 自定義實(shí)現(xiàn)攔截器插件Interceptor內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java實(shí)現(xiàn)雪花算法的原理

    Java實(shí)現(xiàn)雪花算法的原理

    這篇文章主要介紹了Java實(shí)現(xiàn)雪花算法的原理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • Java如何使用JSR303校驗(yàn)數(shù)據(jù)與自定義校驗(yàn)注解

    Java如何使用JSR303校驗(yàn)數(shù)據(jù)與自定義校驗(yàn)注解

    這篇文章主要介紹了Java如何使用JSR303校驗(yàn)數(shù)據(jù)與自定義校驗(yàn)注解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • java開(kāi)發(fā)之內(nèi)部類(lèi)的用法

    java開(kāi)發(fā)之內(nèi)部類(lèi)的用法

    本篇文章介紹了,java開(kāi)發(fā)之內(nèi)部類(lèi)的用法。需要的朋友參考下
    2013-05-05
  • 使用mockito編寫(xiě)測(cè)試用例教程

    使用mockito編寫(xiě)測(cè)試用例教程

    這篇文章主要為大家介紹了使用mockito編寫(xiě)測(cè)試用例教程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • spring的構(gòu)造函數(shù)注入屬性@ConstructorBinding用法

    spring的構(gòu)造函數(shù)注入屬性@ConstructorBinding用法

    這篇文章主要介紹了關(guān)于spring的構(gòu)造函數(shù)注入屬性@ConstructorBinding用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • springbean的八種加載方式匯總

    springbean的八種加載方式匯總

    這篇文章主要介紹了springbean的八種加載方式,一種是XML方式聲明bean,使用@Component及其衍生注解@Controller?、@Service、@Repository定義bean,還有其他方法,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-10-10
  • Kotlin基本類(lèi)型自動(dòng)裝箱出現(xiàn)問(wèn)題解決辦法

    Kotlin基本類(lèi)型自動(dòng)裝箱出現(xiàn)問(wèn)題解決辦法

    這篇文章主要介紹了Kotlin基本類(lèi)型自動(dòng)裝箱出現(xiàn)問(wèn)題解決辦法的相關(guān)資料,希望通過(guò)本文能幫助到大家,讓大家遇到這樣的問(wèn)題順利解決,需要的朋友可以參考下
    2017-10-10
  • HashMap底層原理全面詳解面試絕對(duì)不慌

    HashMap底層原理全面詳解面試絕對(duì)不慌

    這篇文章主要介紹了HashMap底層實(shí)現(xiàn)原理詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08
  • Maven中的dependencyManagement 實(shí)例詳解

    Maven中的dependencyManagement 實(shí)例詳解

    dependencyManagement的中文意思就是依賴(lài)關(guān)系管理,它就是為了能通更好統(tǒng)一管理項(xiàng)目的版本號(hào)和各種jar版本號(hào),可以更加方便升級(jí),解決包沖突問(wèn)題,這篇文章主要介紹了Maven中的dependencyManagement 實(shí)例詳解,需要的朋友可以參考下
    2024-02-02
  • Java?NIO?Channel?使用詳情

    Java?NIO?Channel?使用詳情

    這篇文章主要介紹了Java?NIO?Channel?使用詳情,文章圍繞主題展開(kāi)詳細(xì)內(nèi)容需要的小伙伴可以參考一下,希望對(duì)你的學(xué)習(xí)有所幫助
    2022-04-04

最新評(píng)論