• MyBatis之简单了解Plugin


    MyBatis的Configuration配置中有一个Plugin配置,根据其名可以解释为“插件”,这个插件实质可以理解为“拦截器”。“拦截器”这个名词不陌生,在众多框架中均有“拦截器”。这个Plugin有什么用呢?活着说拦截器有什么用呢?可以想想拦截器是怎么实现的。Plugin用到了Java中很重要的一个特性——动态代理。所以这个Plugin可以理解为,在调用一个方法时,我“拦截”其方法做一些我想让它做的事。它可以拦截以下方法:

    在官方文档中有这么一句话:If you attempt to modify or override the behaviour of a given method, you’re likely to break the core of MyBatis. 谨慎使用自定义Plugin拦截器,因为它可能修改Mybatis核心的东西。实现自定义Plugin我们需要实现 Interceptor接口。并未这个类注解@Intercepts。

     1 package day_8_mybatis.util;
     2 
     3 import java.util.Iterator;
     4 import java.util.Map;
     5 import java.util.Properties;
     6 
     7 import org.apache.ibatis.plugin.Interceptor;
     8 import org.apache.ibatis.plugin.Intercepts;
     9 import org.apache.ibatis.plugin.Invocation;
    10 import org.apache.ibatis.plugin.Plugin;
    11 import org.apache.ibatis.plugin.Signature;
    12 
    13 /**
    14  * @author turbo
    15  *
    16  * 2016年10月25日
    17  */
    18 @Intercepts({
    19     @Signature(
    20         type = Map.class,
    21         method = "get",
    22         args = {Object.class}
    23 )})
    24 public class ExamplePlugin implements Interceptor {
    25 
    26     /* 此方法用于实现拦截逻辑
    27      * @see org.apache.ibatis.plugin.Interceptor#intercept(org.apache.ibatis.plugin.Invocation)
    28      */
    29     @Override
    30     public Object intercept(Invocation invocation) throws Throwable {
    31         
    32         return "ExamplePlugin";
    33     }
    34 
    35     /* 使用当前的这个拦截器实现对目标对象的代理(内部实现时Java的动态代理)
    36      * @see org.apache.ibatis.plugin.Interceptor#plugin(java.lang.Object)
    37      */
    38     @Override
    39     public Object plugin(Object target) {
    40         return Plugin.wrap(target, this);
    41     }
    42 
    43     /* 此方法和上一节所讲的自定义对象工厂中的setProperties一样,初始化Configuration时通过配置文件配置property传递参数给此方法并调用。
    44      * @see org.apache.ibatis.plugin.Interceptor#setProperties(java.util.Properties)
    45      */
    46     @Override
    47     public void setProperties(Properties properties) {  
    48         Iterator iterator = properties.keySet().iterator();
    49         while (iterator.hasNext()){
    50             String keyValue = String.valueOf(iterator.next());
    51             System.out.println(properties.getProperty(keyValue));
    52         }
    53     }
    54 
    55 }

    别忘了在mybatis-config.xml的配置文件中注册自定义Plugin。(下面的配置中有一些遗留代码,是在上两节中的配置,可以选择性的忽略。)

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <!DOCTYPE configuration  
     3   PUBLIC "-//mybatis.org//DTD Config 3.0//EN"  
     4   "http://mybatis.org/dtd/mybatis-3-config.dtd">
     5   
     6 <configuration>
     7 <!-- 注意configuration中各个属性配置的顺序应为:properties,settings,typeAliases,typeHandlers,objectFactory,objectWrapperFactory,reflectorFactory,plugins,environments,databaseIdProvider,mappers)-->
     8     <properties>
     9         <property name="driver" value="com.mysql.jdbc.Driver"/>
    10         <property name="url" value="jdbc:mysql://localhost:3306/test"/>    
    11         <property name="username" value="root"/>
    12         <property name="password" value="0000"/>
    13     </properties>
    14     <!-- 
    15     <typeHandlers>
    16         <typeHandler handler="day_8_mybatis.util.ExampleTypeHandler" javaType="java.util.Date" jdbcType="VARCHAR"/>
    17     </typeHandlers>
    18     <objectFactory type="day_8_mybatis.util.ExampleObjectFactory">
    19         <property name="someProperty" value="100"/>
    20     </objectFactory>
    21      -->
    22     <plugins>
    23         <plugin interceptor="day_8_mybatis.util.ExamplePlugin">
    24             <property name="someProperty" value="100"/>
    25         </plugin>
    26     </plugins>
    27     <environments default="development">
    28         <environment id="development">
    29             <transactionManager type="JDBC" />
    30             <dataSource type="POOLED">
    31                 <property name="driver" value="${driver}"/>
    32                 <property name="url" value="${url}"/>
    33                 <property name="username" value="${username}"/>
    34                 <property name="password" value="${password}"/>
    35             </dataSource>            
    36         </environment>
    37     </environments> 
    38     <mappers>
    39         <mapper resource="day_8_mybatis/mapper/UserMapper.xml"/>
    40         <mapper resource="day_8_mybatis/mapper/NoteMapper.xml"/>
    41     </mappers>    
    42     
    43 </configuration>
    44 
    45  

    客户端测试代码:

     1 package day_8_mybatis;
     2 
     3 import java.io.IOException;
     4 import java.util.HashMap;
     5 import java.util.Map;
     6 
     7 import org.apache.ibatis.session.SqlSession;
     8 
     9 import day_8_mybatis.util.ExamplePlugin;
    10 import day_8_mybatis.util.SessionFactory;
    11 
    12 /**
    13  * 客户端
    14  * @author turbo
    15  *
    16  * 2016年10月25日
    17  */
    18 public class Main {
    19 
    20     /**
    21      * @param args
    22      * @throws IOException 
    23      */
    24     public static void main(String[] args) throws Exception {
    25         String resource = "day_8_mybatis/mybatis-config.xml";        //获取mybatis配置文件路径
    26         SqlSession sqlSession = SessionFactory.getSqlSession(resource);    //通过SessionFactory工具类(此工具类为自己构造即util包中的SessionFactory)构造SqlSession
    27         
    28         Map map = new HashMap();
    29         map = (Map)new ExamplePlugin().plugin(map);
    30         System.out.println(map.get(""));
    31 
    32     }
    33 
    34 }

    至此,我们就简单的了解了MyBatis中的Plugin。有兴趣的可以看看我们在客户端测试代码中的第29行所调用的plugin方法。即调用了Plugin类的静态方法wrap(Object target, Interceptor intercpetor),追踪该方法会发现,此方法即是Java的动态代理。

     1 public static Object wrap(Object target, Interceptor interceptor)
     2     {
     3         Map signatureMap = getSignatureMap(interceptor);
     4         Class type = target.getClass();
     5         Class interfaces[] = getAllInterfaces(type, signatureMap);
     6         if(interfaces.length > 0)
     7             return Proxy.newProxyInstance(type.getClassLoader(), interfaces, new Plugin(target, interceptor, signatureMap));  //返回代理类实例
     8         else
     9             return target;
    10     }

    动态代理很重要,反射很重要。一定要反复理解领会动态代理以及反射,这对我们读懂很多框架源代码有很大帮助。这篇仅仅简单了解,不做过多的深入。

  • 相关阅读:
    类 2020年8月19
    随便一写,明天改正
    os模块 2020年8月16
    time 模块 2020年8月16
    collections模块 2020年8月16
    正则跟re模块内容2020年8月16日
    【C++设计模式二】C++工厂模式
    【C++设计模式一】C++简单工厂模式
    【01-springmvc快速入门、组件解析】
    03-【Spring 的 AOP】
  • 原文地址:https://www.cnblogs.com/yulinfeng/p/5998774.html
Copyright © 2020-2023  润新知