Mybatis超具体插件机制理会,弄懂拦截器So easy
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) { (编辑:湖南网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |