时间:2021-07-01 10:21:17 帮助过:16人阅读
1 public static Object wrap(Object target, Interceptor interceptor) { 2 Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor); 3 Class<?> type = target.getClass(); 4 Class<?>[] interfaces = getAllInterfaces(type, signatureMap); 5 if (interfaces.length > 0) { 6 return Proxy.newProxyInstance( 7 type.getClassLoader(), 8 interfaces, 9 new Plugin(target, interceptor, signatureMap)); 10 } 11 return target; 12 }
因为这里的target一定是一个接口,因此可以放心使用JDK本身提供的Proxy类,这里相当于就是如果该接口满足方法签名那么就为之生成一个代理。
最后就是intercept方法了,这里就是拦截器的核心代码了,方法的逻辑我就不解释了,可以自己看一下,唯一要注意的一点就是无论如何最终一定要返回invocation.proceed(),保证拦截器的层层调用。
xml文件配置即效果演示
写完了插件,只需要在config.xml文件中进行一次配置即可,非常简单:
1 <plugins> 2 <plugin interceptor="org.xrq.mybatis.plugin.SqlCostInterceptor" /> 3 </plugins>
这里每个<plugin>子标签代表一个插件,interceptor表示拦截器的完整路径,每个人的不同。
有了类和这段配置,就可以使用SqlCostInterceptor了,SqlCostInterceptor是通用的,但是每个人的CRUD是不同的,我打印一下我这里CRUD执行的结果:
SQL:[insert into mail(id, create_time, modify_time, web_id, mail, use_for) values(null, now(), now(), "1", "123@sina.com", "个人使用");]执行耗时[1ms] SQL:[insert into mail(id, create_time, modify_time, web_id, mail, use_for) values(null, now(), now(), "2", "123@qq.com", "企业使用");]执行耗时[1ms] SQL:[insert into mail(id, create_time, modify_time, web_id, mail, use_for) values(null, now(), now(), "3", "123@sohu.com", "注册账号使用");]执行耗时[0ms]
看到打印了完整的SQl语句以及SQL语句执行时间。
不过要说明一点,这个插件只是一个简单的Demo,我并没有完整测试过,应该是无法覆盖所有场景的,所以如果想用这段代码片段打印真正的SQL及其执行时间的朋友,还需要在这个基础上做修改,不过即使不改代码,这个插件起到美化SQL的作用,去除一些换行符还是没问题的。
至于MyBatis插件的实现原理,会在我【MyBatis源码分析】系列文章中详细解读,文章地址为【MyBatis源码分析】插件实现原理。
后记
MyBatis插件机制非常有用,用得好可以解决很多问题,不只是这里的打印SQL语句以及记录SQL语句执行时间,分页、分表都可以通过插件来实现。用好插件的关键是我开头就列举的,这里再列一次:
只有理解这四个接口及相关方法是干什么的,才能写出好的拦截器,开发出符合预期的功能。