• MyBatis-Plugins 的创建流程与执行顺序(源码)


    一、插件的解析,所有插件都会被添加到 InterceptorChain 类中,用于后续处理

    org.apache.ibatis.builder.xml.XMLConfigBuilder

    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).newInstance();
                interceptorInstance.setProperties(properties);
                configuration.addInterceptor(interceptorInstance);
            }
        }
    }

    org.apache.ibatis.session.Configuration

    public void addInterceptor(Interceptor interceptor) {
        interceptorChain.addInterceptor(interceptor);
    }

    二、四大对象的创建顺序,都会经过 interceptorChain.pluginAll() 进行处理

    1.Executor,SQL语句执行器

    org.apache.ibatis.session.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) interceptorChain.pluginAll(executor);
        return executor;
    }

    2.ParameterHandler,参数处理器

    org.apache.ibatis.executor.statement.BaseStatementHandler

    protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
        this.configuration = mappedStatement.getConfiguration();
        this.executor = executor;
        this.mappedStatement = mappedStatement;
        this.rowBounds = rowBounds;
    
        this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
        this.objectFactory = configuration.getObjectFactory();
    
        if (boundSql == null) { // issue #435, get the key before calculating the statement
            generateKeys(parameterObject);
            boundSql = mappedStatement.getBoundSql(parameterObject);
        }
    
        this.boundSql = boundSql;
    
        this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
        this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
    }

    org.apache.ibatis.session.Configuration

    public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
        ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);
        parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
        return parameterHandler;
    }

    3.ResultSetHandler,结果集处理器

    org.apache.ibatis.executor.statement.BaseStatementHandler

    protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
        this.configuration = mappedStatement.getConfiguration();
        this.executor = executor;
        this.mappedStatement = mappedStatement;
        this.rowBounds = rowBounds;
    
        this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
        this.objectFactory = configuration.getObjectFactory();
    
        if (boundSql == null) { // issue #435, get the key before calculating the statement
            generateKeys(parameterObject);
            boundSql = mappedStatement.getBoundSql(parameterObject);
        }
    
        this.boundSql = boundSql;
    
        this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
        this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
    }

    org.apache.ibatis.session.Configuration

    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);
        return resultSetHandler;
    }

    4.StatementHandler,SQL语句处理器

    org.apache.ibatis.executor.SimpleExecutor

    @Override
    public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        Statement stmt = null;
        try {
            Configuration configuration = ms.getConfiguration();
            StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
            stmt = prepareStatement(handler, ms.getStatementLog());
            return handler.query(stmt, resultHandler);
        } finally {
            closeStatement(stmt);
        }
    }

    org.apache.ibatis.session.Configuration

    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);
        return statementHandler;
    }

    三、多个不同类型插件的执行顺序

    org.apache.ibatis.executor.SimpleExecutor

    @Override
    public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        Statement stmt = null;
        try {
            Configuration configuration = ms.getConfiguration();
            StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
            stmt = prepareStatement(handler, ms.getStatementLog());
            // 3.执行 SQL 语句,封装结果集,ResultSetHandler 拦截插件执行
            return handler.query(stmt, resultHandler);
        } finally {
            closeStatement(stmt);
        }
    }
    
    private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
        Statement stmt;
        Connection connection = getConnection(statementLog);
        // 1.准备语句,StatementHandler 拦截插件执行
        stmt = handler.prepare(connection, transaction.getTimeout());
        // 2.SQL 语句参数处理,ParameterHandler 拦截插件执行
        handler.parameterize(stmt);
        return stmt;
    }

    四、多个相同类型插件的执行顺序,以  StatementHandler 为例

    1.创建顺序,按照配置顺序层层代理,最后配置的插件为最外层代理

    配置了两个插件

    <plugins>
        <plugin interceptor="com.plugins.ExamplePlugin"></plugin>
        <plugin interceptor="com.plugins.ExamplePlugin2"></plugin>
    </plugins>

    1.1.准备创建

    1.2.最开始要执行的对象

    1.3.开始创建

    1.4.创建完毕

    2.执行顺序,按照配置顺序倒序执行

    2.1.第一次执行,ExamplePlugin2

    2.2.第二次执行,ExamplePlugin

    2.3.最终执行

    3.示意图

  • 相关阅读:
    jQuery.API源码深入剖析以及应用实现(4) - 选择器篇(下)
    jquery表单应用
    随笔 没顾虑
    jquery基础技巧总结
    jQuery.API源码深入剖析以及应用实现(3) - 选择器篇(上)
    JQuery语法总结和注意事项
    5个jQuery问题和解答
    Jquery编辑数据
    jquery 对checkbox的操作
    有关jQuery动画的认识
  • 原文地址:https://www.cnblogs.com/jhxxb/p/10692496.html
Copyright © 2020-2023  润新知