MyBatis的Configuration配置中有一个Plugin配置,根据其名可以解释为“插件”,这个插件实质可以理解为“拦截器”。“拦截器”这个名词不陌生,在众多框架中均有“拦截器”。这个Plugin有什么用呢?活着说拦截器有什么用呢?可以想想拦截器是怎么实现的。Plugin用到了Java中很重要的一个特性——动态代理。所以这个Plugin可以理解为,在调用一个方法时,我“拦截”其方法做一些我想让它做的事。它可以拦截以下方法:
创新互联主要从事做网站、网站制作、网页设计、企业做网站、公司建网站等业务。立足成都服务辛集,十载网站建设经验,价格优惠、服务专业,欢迎来电咨询建站服务:028-86922220
在官方文档中有这么一句话: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 turbo15 *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 @Override30 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 @Override39 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 @Override47 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 2 5 67 8 44 459 14 2210 11 12 13 23 2724 2625 28 3829 3730 31 3632 33 34 35 39 42 4340 41
客户端测试代码:
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 turbo15 *16 * 2016年10月25日17 */18 public class Main {19 20 /**21 * @param args22 * @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)构造SqlSession27 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 }
动态代理很重要,反射很重要。一定要反复理解领会动态代理以及反射,这对我们读懂很多框架源代码有很大帮助。这篇仅仅简单了解,不做过多的深入。