Mybatis针对以下四大组件提供了拓展机制

  • Executor:SQL执行器
  • StatementHandler:SQL语法构建器
  • ParameterHandler:参数处理器
  • ResultSetHandler:结果集处理器

    01|插件使用

  • 1、创建插件类实现Interceptor接口

    1. //type='xxx'指定需要拦截的组件,method='xxxx'为StatementHandler中的方法名,args为参数列表
    2. @Intercepts({@Signature(type = StatementHandler.class,
    3. method = "query", args = {Statement.class, ResultHandler.class})})
    4. public class StatementHandlerPlugin implements Interceptor {
    5. @Override
    6. public Object intercept(Invocation invocation) throws Throwable {
    7. System.out.println(" StatementHandler增强行为");
    8. final StatementHandler target = (StatementHandler) invocation.getTarget();
    9. System.out.println(target.getBoundSql().getSql());
    10. return invocation.proceed();
    11. }
    12. @Override
    13. public Object plugin(Object target) {
    14. System.out.println(" StatementHandler进行了增强初始化...");
    15. return Plugin.wrap(target,this);
    16. }
    17. @Override
    18. public void setProperties(Properties properties) {
    19. }
    20. }
  • 2、配置文件中引入插件

    1. <plugins>
    2. <plugin interceptor="white.colde.plugin.StatementHandlerPlugin"></plugin>
    3. </plugins>

    02|插件实现机制

    当mybatis启动时,会首先解析加载配置文件中的插件配置信息,并将解析出的插件信息类存储Configuration对象中。

    1. public class XMLConfigBuilder extends BaseBuilder {
    2. private void pluginElement(XNode parent) throws Exception {
    3. if (parent != null) {
    4. for (XNode child : parent.getChildren()) {
    5. String interceptor = child.getStringAttribute("interceptor");
    6. Properties properties = child.getChildrenAsProperties();
    7. Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).getDeclaredConstructor().newInstance();
    8. interceptorInstance.setProperties(properties);
    9. // 将解析出的所有插件类信息存入Configuration类中
    10. configuration.addInterceptor(interceptorInstance);
    11. }
    12. }
    13. }
    14. }

    当创建四大组件时,会生成相应的插件代理对象 ```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) {

    1. executor = new BatchExecutor(this, transaction);

    } else if (ExecutorType.REUSE == executorType) {

    1. executor = new ReuseExecutor(this, transaction);

    } else {

    1. executor = new SimpleExecutor(this, transaction);

    } if (cacheEnabled) {

    1. 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,

    1. 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 interceptors = new ArrayList<>();

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 getInterceptors() { return Collections.unmodifiableList(interceptors); }

} //编写拦截器的时候,一个典型的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, Set> 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; } }

``` 至此,当组件在真正执行时,会调用对应的代理对象进而拦截器中的拦截逻辑