插件原理
四大对象在创建时
- 每一个创建出来的对象不是直接返回的,而是调用了interceptorChain.pluginAll()方法
- 调用方法获取到所有的Interceptor(拦截器),(插件需要实现的接口)
- 插件机制,可以使用插件为目标对象创建一个代理对象,面向切面的编程方式(AOP)
插件编写
1.编写Interceptor的实现类
MyFirstPlugin 类:
package cn.it.mybatis.dao; import java.util.Properties; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.plugin.Intercepts; import org.apache.ibatis.plugin.Invocation; import org.apache.ibatis.plugin.Plugin; import org.apache.ibatis.plugin.Signature; /** * 完成插件签名 告诉MyBatis当前插件用来拦截那个对象的那个方法 * * @author Administrator * */ @Intercepts({ @Signature(type = StatementHandler.class, method = "parameterize", args = java.sql.Statement.class) }) public class MyFirstPlugin implements Interceptor { /** * intercept:拦截目标对象的目标方法的执行 */ @Override public Object intercept(Invocation invocation) throws Throwable { System.out.println("MyFirstPlugin..Invocation" + invocation.getMethod()); // 执行目标方法 Object proceed = invocation.proceed(); // 返回执行后的对象 return proceed; } /** * plugin:包装目标对象,为目标对象创建一个代理对象 */ @Override public Object plugin(Object target) { System.out.println("MyFirstPlugin..plugin:将要包装的对象" + target); // 借助Plugin类的wrap方法来使用当前拦截器来包装目标对象 Object wrap = Plugin.wrap(target, this); // 返回为当前target创建动态代理对象 return wrap; } /** * setProperties:将插件注册时的property属性设置进来 */ @Override public void setProperties(Properties properties) { System.out.println("插件配置信息:" + properties); } }
2.使用@Intercepts注解完成插件签名
@Intercepts({ @Signature(type = StatementHandler.class, method = "parameterize", args = java.sql.Statement.class) })
3.将写好的插件注册到全局配置文件中
使用<plugins>标签注册插件
<!--plugins:注册插件 --> <plugins> <plugin interceptor="cn.it.mybatis.dao.MyFirstPlugin"> <property name="username" value="root"/> <property name="password" value="123456"/> </plugin> </plugins>
运行:
拦截到了StatementHandler的parameterize方法
多个插件的运行顺序
多个插件就会产生多层代理
创建动态代理的时候,是按照插件配置顺序创建层层代理对象。执行目标方法的之后,按照逆向顺序执行