Mybatis针对以下四大组件提供了拓展机制
- Executor:SQL执行器
- StatementHandler:SQL语法构建器
- ParameterHandler:参数处理器
-
01|插件使用
1、创建插件类实现Interceptor接口
//type='xxx'指定需要拦截的组件,method='xxxx'为StatementHandler中的方法名,args为参数列表
@Intercepts({@Signature(type = StatementHandler.class,
method = "query", args = {Statement.class, ResultHandler.class})})
public class StatementHandlerPlugin implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
System.out.println(" StatementHandler增强行为");
final StatementHandler target = (StatementHandler) invocation.getTarget();
System.out.println(target.getBoundSql().getSql());
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
System.out.println(" StatementHandler进行了增强初始化...");
return Plugin.wrap(target,this);
}
@Override
public void setProperties(Properties properties) {
}
}
2、配置文件中引入插件
<plugins>
<plugin interceptor="white.colde.plugin.StatementHandlerPlugin"></plugin>
</plugins>
02|插件实现机制
当mybatis启动时,会首先解析加载配置文件中的插件配置信息,并将解析出的插件信息类存储Configuration对象中。
public class XMLConfigBuilder extends BaseBuilder {
private void pluginElement(XNode parent) throws Exception {
if (parent != null) {
for (XNode child : parent.getChildren()) {
String interceptor = child.getStringAttribute("interceptor");
Properties properties = child.getChildrenAsProperties();
Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).getDeclaredConstructor().newInstance();
interceptorInstance.setProperties(properties);
// 将解析出的所有插件类信息存入Configuration类中
configuration.addInterceptor(interceptorInstance);
}
}
}
}
当创建四大组件时,会生成相应的插件代理对象 ```java public class Configuration {
public Executor newExecutor(Transaction transaction, ExecutorType executorType) { executorType = executorType == null ? defaultExecutorType : executorType; executorType = executorType == null ? ExecutorType.SIMPLE : executorType; Executor executor; if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
} if (cacheEnabled) {
executor = new CachingExecutor(executor);
} // 创建executor代理对象 executor = (Executor) interceptorChain.pluginAll(executor); return executor; }
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql); statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler); // 创建statementHandler代理对象 return statementHandler; }
public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) { ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql); parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler); // 创建parameterHandler代理对象 return parameterHandler; }
public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler,
ResultHandler resultHandler, BoundSql boundSql) {
ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds); resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler); // 创建resultSetHandler代理对象 return resultSetHandler; } }
public class InterceptorChain {
private final List
public Object pluginAll(Object target) { // 依次遍历装载的插件,如果是多个插件则生成代理链,执行时依次执行拦截器中的拦截逻辑 for (Interceptor interceptor : interceptors) { target = interceptor.plugin(target); } return target; }
public void addInterceptor(Interceptor interceptor) { interceptors.add(interceptor); }
public List
} //编写拦截器的时候,一个典型的plugin方法实现方式,如下: public class XXXXPlugin implements Interceptor { @Override public Object plugin(Object target) { System.out.println(“ StatementHandler进行了增强初始化…”); return Plugin.wrap(target,this); } }
public class Plugin{
public static Object wrap(Object target, Interceptor interceptor) {
Map
``` 至此,当组件在真正执行时,会调用对应的代理对象进而拦截器中的拦截逻辑