Explanation of MyBatis interceptor Inteceptor in java

Source: Internet
Author: User
Tags prepare throwable

This article mainly analyzes the plug-in mechanism of MyBatis, which is actually the implementation of the responsibility chain mode implemented by Java dynamic proxy.

According to the official documentation. Mybatis can only intercept the following methods. This decides to write the signature parameter of the interceptor annotation.

The code is as follows: Copy code
Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
ParameterHandler (getParameterObject, setParameters)
ResultSetHandler (handleResultSets, handleOutputParameters)
StatementHandler (prepare, parameterize, batch, update, query)

The source code for interceptorChain. pluginAll (...) is the custom interceptor:

The code is as follows: Copy code

/* Org. apache. ibatis. session. Configuration method */
Public ParameterHandler newParameterHandler (MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql ){
ParameterHandler parameterHandler = mappedStatement. getLang (). createParameterHandler (mappedStatement, parameterObject, boundSql );
/* Intercept ParameterHandler */
ParameterHandler = (ParameterHandler) interceptorChain. pluginAll (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 );
/* Intercept ResultSetHandler */
ResultSetHandler = (ResultSetHandler) interceptorChain. pluginAll (resultSetHandler );
Return resultSetHandler;
}

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 );
/* Intercept StatementHandler */
StatementHandler = (StatementHandler) interceptorChain. pluginAll (statementHandler );
Return statementHandler;
}

Public Executor newExecutor (Transaction transaction, ExecutorType executorType ){
ExecutorType = null? DefaultExecutorType: 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 );
  }
/* Intercept Executor */
Executor = (Executor) interceptorChain. pluginAll (executor );
Return executor;
}

To implement a custom Interceptor, you only need to implement the Interceptor interface. The code is as follows:

The code is as follows: Copy code

/* Indicates the method of the interface to intercept and its parameters */
@ Intercepts ({@ Signature (type = StatementHandler. class, method = "prepare", args = {Connection. class })})
Public class YourInterceptor implements Interceptor {

Public Object intercept (Invocation invocation) throws Throwable {
DoSomeThing ();
/* Note: Invocation is actually used here. the proceed () method completes the traversal call of the interceptorChain chain (that is, the intercept method of all registered Interceptor is executed), and is finally called by the original method of the proxy object */
Return invocation. proceed ();
  }

/* Generate a proxy for the target, and the @ Intercepts annotation is used in Plugin. wrap */
@ Override
Public Object plugin (Object target ){
/* When the target class is of the StatementHandler type, the target class is encapsulated without any meaningless proxy */
Return (target instanceof StatementHandler )? Plugin. wrap (target, this): target;
  }

/* Used to set custom interceptor configuration parameters */
@ Override
Public void setProperties (Properties properties ){
  }
}

The code for blocking calls is in Plugin. wrap:

The code is as follows: Copy code

/* Org. apache. ibatis. plugin. Plugin class */
Public class Plugin implements InvocationHandler {

/* Omitting the code ...*/

Public static Object wrap (Object target, Interceptor interceptor ){
/* Obtain the annotation signature of Interceptor */
Map <Class <?>, Set <Method> signatureMap = getSignatureMap (interceptor );
Class <?> Type = target. getClass ();
/* Obtain the interface that matches the interception target class */
Class <?> [] Interfaces = getAllInterfaces (type, signatureMap );
If (interfaces. length> 0 ){
/* Use jdk dynamic proxy */
Return Proxy. newProxyInstance (type. getClassLoader (), interfaces, new Plugin (target, interceptor, signatureMap ));
    }
Return target;
  }

/* All methods of the interception target class will be executed here */
@ Override
Public Object invoke (Object proxy, Method method, Object [] args) throws Throwable {
Try {
Set <Method> methods = signatureMap. get (method. getDeclaringClass ());
If (methods! = Null & methods. contains (method )){
/* Method for executing the interceptor */
Return interceptor. intercept (new Invocation (target, method, args ));
      }
Return method. invoke (target, args );
} Catch (Exception e ){
Throw ExceptionUtil. unwrapThrowable (e );
    }
  }

/* Omitting the code ...*/

}

We can see that the core code of the interceptor design of MyBatis is relatively simple, but flexible enough. In actual use, do not use meaningless proxy (Plugin. wrap ).

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.