一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - mybatis多個plugins的執行順序解析

mybatis多個plugins的執行順序解析

2022-01-12 12:13子衿_青青 Java教程

這篇文章主要介紹了mybatis多個plugins的執行順序解析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

 

一、前言

mybatis官網中,有插件一說 mybatis plugins 如果同時有多個插件,那么他們的執行順序是怎樣的?

mybatis多個plugins的執行順序解析

 

二、準備工作、代碼準備

1、 項目結構

mybatis多個plugins的執行順序解析

2、TestDAO

public interface TestDAO {
    Test selectById(Integer id);
 
    default void testDefaultMethod(){
        System.out.println("===調用接口中的默認方法,用來驗證MapperProxy中的isDefaultMethod方法===");
    }
}

3、Test

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Test {
    private Integer id;
 
    private String name;
}

4、ExamplePlugin

@Intercepts({@Signature(
        type= Executor.class, method = "query", args={MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}
        ),
        @Signature(
                type = ParameterHandler.class, method = "setParameters", args = {PreparedStatement.class}
        ),
        @Signature(
                type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class}
        ),
        @Signature(
                type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}
        )
})
public class ExamplePlugin implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("==== ExamplePlugin 開始搞事情:" + invocation.getMethod().getName() + "  ====");
        return invocation.proceed();
    }
 
    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }
 
    @Override
    public void setProperties(Properties properties) {
 
    }
}

5、SecondExamplePlugin

@Intercepts({@Signature(
        type= Executor.class, method = "query", args={MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}
        ),
        @Signature(
                type = ParameterHandler.class, method = "setParameters", args = {PreparedStatement.class}
        ),
        @Signature(
                type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class}
        ),
        @Signature(
                type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}
        )
})
public class SecondExamplePlugin implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("==== SecondExamplePlugin 開始搞事情:" + invocation.getMethod().getName() + "  ====");
        return invocation.proceed();
    }
 
    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }
 
    @Override
    public void setProperties(Properties properties) {
 
    }
}

6、Main

public class Main {
 
    public static SqlSession getSqlSession() throws IOException {
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        return sqlSessionFactory.openSession();
    }
 
    public static void main(String[] args) throws IOException {
        TestDAO testDAO = getSqlSession().getMapper(TestDAO.class);
        Test test = testDAO.selectById(1);
 
//        testDAO.testDefaultMethod();
 
        //類文件是緩存在java虛擬機中,我們將類文件打印到文件中,便于查看
//        generateProxyFile("F:/TestDAOProxy.class");
    }
 
    private static void generateProxyFile(String path){
        byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy0", new Class<?>[]{TestDAO.class});
 
        try(FileOutputStream fos = new FileOutputStream(path)) {
            fos.write(classFile);
            fos.flush();
            System.out.println("代理類class文件寫入成功");
        } catch (Exception e) {
            System.out.println("寫文件錯誤");
        }
    }
}

7、 TestMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 
<mapper namespace="com.me.mybatis.dao.TestDAO">
    <resultMap id="testMap" type="com.me.mybatis.domain.Test">
        <result property="id" column="id" />
        <result property="name" column="name" />
    </resultMap>
 
    <sql id="allColumn">
        id, name
    </sql>
 
    <select id="selectById" resultMap="testMap">
        SELECT <include refid="allColumn"/>
        FROM test
        WHERE id = #{id}
    </select>
 
</mapper>

8、mybatis-confi.xml

<?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.me.mybatis.plugin.ExamplePlugin">
            <property name="someProperty" value="200" />
        </plugin>
        <plugin interceptor="com.me.mybatis.plugin.SecondExamplePlugin">
            <property name="someProperty" value="200" />
        </plugin>
    </plugins>
 
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis_test?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false&amp;useJDBCCompliantTimezoneShift=true&amp;useLegacyDatetimeCode=false&amp;serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="NewPwd@123"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mappers/TestMapper.xml"/>
    </mappers>
</configuration>

9、POM

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>com.me</groupId>
    <artifactId>mybatis-test</artifactId>
    <version>1.0-SNAPSHOT</version>
 
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
 
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.14</version>
        </dependency>
 
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
 
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.12</version>
        </dependency>
    </dependencies>
 
</project>

 

三、開始探索

1、運行結果

==== SecondExamplePlugin 開始搞事情:query  ====
==== ExamplePlugin 開始搞事情:query  ====
==== SecondExamplePlugin 開始搞事情:prepare  ====
==== ExamplePlugin 開始搞事情:prepare  ====
==== SecondExamplePlugin 開始搞事情:setParameters  ====
==== ExamplePlugin 開始搞事情:setParameters  ====
==== SecondExamplePlugin 開始搞事情:handleResultSets  ====
==== ExamplePlugin 開始搞事情:handleResultSets  ====

2、疑問:為什么是這樣的順序?

和我們在mybatis-config.xml文件中的順序相反,為什么?

mybatis多個plugins的執行順序解析

3、注釋掉一個,我們從一個plugin開始debug,看看做了什么

mybatis多個plugins的執行順序解析

4、如圖,在Configuration的四個方法newParameterHandler、newResultSetHandler、newStatementHandler、newExecutor中打上斷點

mybatis多個plugins的執行順序解析

5、debug Main類的main方法

mybatis多個plugins的執行順序解析

6、我們發現在newExecutor中,被攔住了

mybatis多個plugins的執行順序解析

這里的interceptorChain是什么東西?我們往上找一找,發現它是在Configuration類中new出來的。它等價于mybatis-config中的<plugins></plugins>

mybatis多個plugins的執行順序解析

7、我們已經知道interceptorChain是什么了,那么進入它的pluginAll方法

mybatis多個plugins的執行順序解析

mybatis多個plugins的執行順序解析

我們可以看到它是遍歷interceptors的plugin方法。而interceptors是ArrayList,是有序的。那么在配置文件中,哪個plugin在前,這里它就在前面

8、進入interceptor的plugin方法,發現我們來到了我們自己寫的ExamplePlugin類的plugin方法

mybatis多個plugins的執行順序解析

9、它又繼續調用了Plugin的靜態方法wrap

mybatis多個plugins的執行順序解析

1) 第一步獲取@Signature注解中的type和method,也就是我們在ExamplePlugin中使用的注解。

mybatis多個plugins的執行順序解析

2)第二步,用動態代理,生成代理類。其中Plugin作為InvocationHandler

mybatis多個plugins的執行順序解析

10、UML圖

mybatis多個plugins的執行順序解析

最終Executor不再是原來的類,而是它的代理類。newStatementHandler方法和newResultSetHandler方法的流程,也差不多,最終也是生成代理類。

當Executor、StatementHandler、ParameterHandler、ResultSetHandler執行他們自己的方法時,實際上調用他們的代理類Plugin中的invoke方法。

mybatis多個plugins的執行順序解析

也就是在interceptor.intercept(new Invocation(target, method, args));這一句中,回到了我們ExamplePlugin的intercept方法

mybatis多個plugins的執行順序解析

整個流程中Executor的代理。(這里只拿Executor來舉例)

mybatis多個plugins的執行順序解析

 

四、結論

上面只是代理一次,還記得pluginAll嗎?

mybatis多個plugins的執行順序解析

多個interceptor呢?當然是代理類又被代理了

mybatis多個plugins的執行順序解析

所以,后面的將會代理前面的,這也就是為什么SecondExamplePlugin先執行的原因了――越外層的越先執行嘛

多個插件的執行順序已經明了了,那么插件里面方法的執行順序呢?

當然是看這些方法什么時候被調用咯

mybatis多個plugins的執行順序解析

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/qq_18433441/article/details/84036317

延伸 · 閱讀

精彩推薦
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7482021-02-04
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
主站蜘蛛池模板: 亚洲国产区中文在线观看 | 无套大战白嫩乌克兰美女 | 91国语精品自产拍在线观看一 | 男人午夜视频在线观看 | 四虎影院网址大全 | 亚洲老头与老太hd | 亚洲AV无码专区国产乱码网站 | 成人免费视频一区二区三区 | 国产白虎| 性奶乳妇 | 四虎地址 | 欧美精品一区二区三区免费播放 | 日本中年japanesebear | 欧美草逼视频 | 亚洲 色 欧美 爱 视频 日韩 | 久久这里只有精品视频9 | 深夜福利影院在线观看 | 四虎色影院 | 猛操女人| 国产成人亚洲精品乱码在线观看 | 免费在线看 | 学校捏奶揉下面污文h | 欧美va天堂va视频va在线 | 久久伊人精品青青草原2021 | 国产精品美女久久久久网站 | 99爱免费| 亚洲色图色 | 欧美成人tv在线观看免费 | 爽好舒服使劲添高h视频 | 欧美日韩亚洲区久久综合 | 日韩一品在线播放视频一品免费 | 久久99re2在线视频精品 | 13日本xxxxxxxxx18 1313午夜精品久久午夜片 | 久久日韩精品无码一区 | freesex1718处xx| 成在线人免费 | 精品国产综合 | www毛片| 滑进了柔佳火热紧夹的 | 国产高清在线播放刘婷91 | 齐天大性之七仙女欲春迅雷链接 |