`
风过无声
  • 浏览: 87313 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

mybatis 插件

 
阅读更多

1.简介

MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:

  • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  • ParameterHandler (getParameterObject, setParameters)
  • ResultSetHandler (handleResultSets, handleOutputParameters)
  • StatementHandler (prepare, parameterize, batch, update, query)

这些类中方法的细节可以通过查看每个方法的签名来发现,或者直接查看 MyBatis 的发行包中的源代码。 假设你想做的不仅仅是监控方法的调用,那么你应该很好的了解正在重写的方法的行为。 因为如果在试图修改或重写已有方法的行为的时候,你很可能在破坏 MyBatis 的核心模块。 这些都是更低层的类和方法,所以使用插件的时候要特别当心。

1.1实现

1)实现 Interceptor 接口,通过@Intercepts指定拦截位置

@Intercepts({@Signature(
  type= Executor.class,
  method = "update",
  args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
  public Object intercept(Invocation invocation) throws Throwable {
    return invocation.proceed();
  }
  public Object plugin(Object target) {
    return Plugin.wrap(target, this);
  }
  public void setProperties(Properties properties) {
  }
}

 2)配置mybatis-config.xml

<plugins>
  <plugin interceptor="org.mybatis.example.ExamplePlugin">
    <property name="someProperty" value="100"/>
  </plugin>
</plugins>

2.实例

StatementHandler.query方法进行拦截,记录慢SQL

 

package com.siyuan.dao.mybatis;

import java.sql.Statement;
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;
import org.apache.ibatis.session.ResultHandler;
import org.apache.log4j.Logger;

@Intercepts(@Signature(type = StatementHandler.class, 
		method = "query", 
		args = {Statement.class, ResultHandler.class }))
public class SqlStatisticInterceptor implements Interceptor {
	
	private static final Logger LOGGER = 
		Logger.getLogger(SqlStatisticInterceptor.class);
	
	// 慢SQL阀值
	private int slowSQLThreshold = 3000;
	
	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		long start = System.currentTimeMillis();
		Object result = invocation.proceed();
		long timeSpent = System.currentTimeMillis() - start;
		StatementHandler handler = (StatementHandler) invocation.getTarget();
		String sql = handler.getBoundSql().getSql().trim();
		LOGGER.debug("spent [" + timeSpent + "]ms for :\n" + sql);
		if (timeSpent >= slowSQLThreshold) {
			LOGGER.warn("slow sql which costs [" + timeSpent 
					+ "]ms has been found:\n" + sql);
		}
		return result;
	}

	@Override
	public Object plugin(Object target) {
		return Plugin.wrap(target, this);
	}

	@Override
	public void setProperties(Properties properties) {
		if (properties.get("slowSQLThreshold") == null) {
			return;
		}
		this.slowSQLThreshold = 
			Integer.parseInt((String) properties.get("slowSQLThreshold"));
	}

}

2) mybatis-config.xml

 

<plugin interceptor="com.qfang.dao.mybatis.SqlStatisticInterceptor">
    <property name="slowSQLThreshold" value="1000"/>
</plugin>

3.原理

1)Interceptor.plugin方法将在创建Executor,ParameterHandler,ResultSetHandlerStatementHandler实例时被调用替代mybatis框架默认创建的实例


2)Plugin实现InvocationHandler,wrap方法通过Proxy创建Executor,ParameterHandler,ResultSetHandlerStatementHandler实例的代理类

  public static Object wrap(Object target, Interceptor interceptor) {
    Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
    Class<?> type = target.getClass();
    Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
    if (interfaces.length > 0) {
      return Proxy.newProxyInstance(
          type.getClassLoader(),
          interfaces,
          new Plugin(target, interceptor, signatureMap));
    }
    return target;
  }

4.参考资料

http://www.mybatis.org/mybatis-3/zh/configuration.html#plugins

 

  • 大小: 19.9 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics