Mybatis插件(plugin)开发
Mybatis插件编写:
- 1、编写Interceptor的实现类
- 2、使用@Intercepts注解完成插件签名
- 3、将写好的插件注册到全局配置文件中
/**
* 完成插件签名:
* 告诉MyBatis当前插件用来拦截哪个对象的哪个方法
*/
@Intercepts(
{
@Signature(type=StatementHandler.class,method="parameterize",args=java.sql.Statement.class)
})
public class MyFirstPlugin implements Interceptor{
/**
*
* 拦截目标对象的目标方法的执行
*/
@Override
public Object intercept(Invocation invocation) throws Throwable {
// TODO Auto-generated method stub
System.out.println("MyFirstPlugin...intercept:"+invocation.getMethod());
//动态的改变一下sql运行的参数:以前1号员工,实际从数据库查询2号员工
Object target = invocation.getTarget();
System.out.println("当前拦截到的对象:"+target);
//拿到:StatementHandler==>ParameterHandler===>parameterObject
//拿到target的元数据
MetaObject metaObject = SystemMetaObject.forObject(target);
Object value = metaObject.getValue("parameterHandler.parameterObject");
System.out.println("sql语句用的参数是:"+value);
//修改完sql语句要用的参数
metaObject.setValue("parameterHandler.parameterObject", 2);
//执行目标方法
Object proceed = invocation.proceed();
//返回执行后的返回值
return proceed;
}
/**
*
*包装目标对象的:为目标对象创建一个代理对象
*/
@Override
public Object plugin(Object target) {
// TODO Auto-generated method stub
//我们可以借助Plugin的wrap方法来使用当前Interceptor包装我们目标对象
System.out.println("MyFirstPlugin...plugin:mybatis将要包装的对象"+target);
Object wrap = Plugin.wrap(target, this);
//返回为当前target创建的动态代理
return wrap;
}
/**
*
*将插件注册时 的property属性设置进来
*/
@Override
public void setProperties(Properties properties) {
// TODO Auto-generated method stub
System.out.println("插件配置的信息:"+properties);
}
}
在全局配置文件中注册:
<!-- mybatis-config.xml -->
<plugins>
<plugin interceptor="org.mybatis.example.MyFirstPlugin">
<property name="someProperty" value="100"/>
</plugin>
</plugins>
插件是用来包装四大对象,拦截指定的方法:
-
Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
-
ParameterHandler (getParameterObject, setParameters)
-
ResultSetHandler (handleResultSets, handleOutputParameters)
-
StatementHandler (prepare, parameterize, batch, update, query)
四大对象在执行增删改查方法的过程中的作用:
1)、Mappe代理对象调用DefaultSqlSession的增删改查方法,DefaultSqlSession实际上是调用Executor的update(增删改)、query;
2)、Executor会创建一个StatementHandler对象(同时也会创建出ParameterHandler和ResultSetHandler)
3)、Executor使用StatementHandler预编译sql,以及使用ParameterHandler来给sql设置参数
4)、Executor调用StatementHandler的增删改查方法;
5)、ResultSetHandler封装结果集
在四大对象创建的时候,并不是直接直接返回,都会调用interceptorChain.pluginAll(target):
public Object pluginAll(Object target) {
//使用每一个插件来创建一个代理对象
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}