设为首页 - 加入收藏 ASP站长网(Aspzz.Cn)- 科技、建站、经验、云计算、5G、大数据,站长网!
热搜: 创业者 数据 手机
当前位置: 首页 > 站长学院 > MySql教程 > 正文

Mybatis超详细插件机制解析,弄懂拦截器So easy(3)

发布时间:2019-12-25 22:25 所属栏目:115 来源:站长网
导读:publicResultSetHandlernewResultSetHandler(Executorexecutor,MappedStatementmappedStatement,RowBoundsrowBounds,ParameterHandlerparameterHandler,ResultHandlerresultHandler,BoundSqlboundSql){ ResultSetHa

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; 

查看源码可以发现, Mybatis框架在创建好这四大接口对象的实例后,都会调用InterceptorChain.pluginAll()方法。InterceptorChain对象是插件执行链对象,看源码就知道里面维护了Mybatis配置的所有插件(Interceptor)对象。

// target --> Executor/ParameterHandler/ResultSetHander/StatementHandler 

public Object pluginAll(Object target) { 

  for (Interceptor interceptor : interceptors) { 

   target = interceptor.plugin(target); 

  } 

  return target; 

其实就是按顺序执行我们插件的plugin方法,一层一层返回我们原对象(Executor/ParameterHandler/ResultSetHander/StatementHandler)的代理对象。当我们调用四大接口的方法的时候,实际上是调用代理对象的相应方法,代理对象又会调用四大接口的实例。

Plugin对象

我们知道,官方推荐插件实现plugin方法为:Plugin.wrap(target, this);

public static Object wrap(Object target, Interceptor interceptor) { 

  // 获取插件的Intercepts注解 

  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; 

这个方法其实是Mybatis简化我们插件实现的工具方法。其实就是根据当前拦截的对象创建了一个动态代理对象。代理对象的InvocationHandler处理器为新建的Plugin对象。

插件配置注解@Intercepts

Mybatis的插件都要有Intercepts注解来指定要拦截哪个对象的哪个方法。我们知道,Plugin.warp方法会返回四大接口对象的代理对象(通过new Plugin()创建的IvocationHandler处理器),会拦截所有的执行方法。在代理对象执行对应方法的时候,会调用InvocationHandler处理器的invoke方法。Mybatis中利用了注解的方式配置指定拦截哪些方法。具体如下:

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)) { 

     return interceptor.intercept(new Invocation(target, method, args)); 

   } 

   return method.invoke(target, args); 

  } catch (Exception e) { 

   throw ExceptionUtil.unwrapThrowable(e); 

  } 

可以看到,只有通过Intercepts注解指定的方法才会执行我们自定义插件的intercept方法。未通过Intercepts注解指定的将不会执行我们的intercept方法。

官方插件开发方式

@Intercepts({@Signature(type = Executor.class, method = "query", 

    args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})}) 

public class TestInterceptor implements Interceptor { 

  public Object intercept(Invocation invocation) throws Throwable { 

   Object target = invocation.getTarget(); //被代理对象 

   Method method = invocation.getMethod(); //代理方法 

   Object[] args = invocation.getArgs(); //方法参数 

   // do something ...... 方法拦截前执行代码块 

   Object result = invocation.proceed(); 

   // do something .......方法拦截后执行代码块 

   return result; 

  } 

  public Object plugin(Object target) { 

   return Plugin.wrap(target, this); 

  } 

以上就是Mybatis官方推荐的插件实现的方法,通过Plugin对象创建被代理对象的动态代理对象。可以发现,Mybatis的插件开发还是很简单的。

自定义开发方式

Mybatis的插件开发通过内部提供的Plugin对象可以很简单的开发。只有理解了插件实现原理,对应不采用Plugin对象我们一样可以自己实现插件的开发。下面是我个人理解之后的自己实现的一种方式。

public class TestInterceptor implements Interceptor { 

  public Object intercept(Invocation invocation) throws Throwable { 

    Object target = invocation.getTarget(); //被代理对象 

    Method method = invocation.getMethod(); //代理方法 

    Object[] args = invocation.getArgs(); //方法参数 

    // do something ...... 方法拦截前执行代码块 

    Object result = invocation.proceed(); 

    // do something .......方法拦截后执行代码块 

    return result; 

  } 

  public Object plugin(final Object target) { 

(编辑:ASP站长网)

网友评论
推荐文章
    热点阅读