要想一针见血地理解MyBatis插件机制,只需要明白一点:原身和变身。也就是说,一旦配置上插件,ParameterHandler,ResultSetHandler,StatementHandler,Executor这四大核心对象,将会生成变身,是一种代理对象,而不再是原身。
MyBatis框架的配置文件,即mybatis-config.xml文件中,包括了插件的设置。
根据功能,可以将插件分为两大类:
第一类:插件是对系统的一种补充,例如在分布式系统中,可以使用插件的方式,实现内存插件、磁盘插件、线性网络插件、Paxos插件等。此类插件等同于组件。
第二类:插件是对系统默认功能的自定义修改,例如mybatis里面自定义插件,它实现的拦截器的功能。此类插件等同于拦截器。
mybatis里面自定义插件属于拦截器插件,大凡拦截器都需要关注两个要点:
(1)拦截的对象是谁,用代码行话来说,target目标是谁? (2)拦截的技术方案是什么?
下面,针对这两个问题进行详细的阐述一下。
我们知道,MyBatis有四大核心对象:
(1)ParameterHandler:处理SQL的参数对象 (2)ResultSetHandler:处理SQL的返回结果集 (3)StatementHandler:数据库的处理对象,用于执行SQL语句 (4)Executor:MyBatis的执行器,用于执行增删改查操作
那么,MyBatis拦截器针对的对象就是上面“四大金刚”。
在Java里面,我们想拦截某个对象,只需要把这个对象包装一下,用代码行话来说,就是重新生成一个代理对象。
这样在每次调用Executor类的方法的时候,总是要经过Interceptor接口的拦截。
一旦我们在mybatis-config.xml里面配置了插件:
ParameterHandler,ResultSetHandler,StatementHandler,Executor这“四大金刚”就发生变身,而不再是原身。这个变身的过程是这样的,以ParameterHandler为例:
第一步:根据插件配置,利用反射技术,创建interceptor拦截器
Interceptor interceptor = (Interceptor) MyInterceptor.class.newInstance();
第一步:创建原身 ParameterHandler parameterHandler = createParameterHandler();
第二步:原身+拦截器---->变身 parameterHandler = (ParameterHandler) Plugin.wrap(parameterHandler, interceptor); 在这一步,将parameterHandler和interceptor包装到一起,生成了变身,并重新赋值给parameterHandler变量
代码备注:也许上面的代码,你没有看懂,但是没有关系,其中的细节你可以不去探究,你只要明白代码的字面意思,createParameterHandler(),这是创建ParameterHandler对象,Plugin.wrap就是包装,把两个类包装一下,重新生成一个新的类。你只要能理清“原身->变身”这个过程,这就足够了,就能把MyBatis插件机制的精髓已经掌握了。
大凡提到“MyBatis插件”,很多人感觉这是一个高大上的玩意,深入MyBatis源码内核,威力巨大,也破坏巨大,让人万分小心,惴惴不安。其实不然,添加插件,就是给mybatis核心对象生成了变身而已。也就是说,一旦配置上插件,ParameterHandler,ResultSetHandler,StatementHandler,Executor这四大核心对象,将会生成变身,是一种代理对象,而不再是原身,仅此而已。通过本文的一针见血,希望大家能够放开手脚,大胆尝试,开发MyBatis插件不是困难的事情。