做软件赚钱的网站php中网站不同模板后台逻辑代码怎么管理
news/
2025/9/28 2:46:31/
文章来源:
做软件赚钱的网站,php中网站不同模板后台逻辑代码怎么管理,做php网站用什么软件好,免费做app的软件有哪些文章目录前言InterceptorChain保存所有的Interceptor创建四大对象都走ConfigurationInterceptorChain增强对象方法Plugin封装动态代理#xff0c;让你使用Mybatis拦截器更简单Invocation#xff0c;让我们能在拦截器中使用动态代理类中的invoke方法中的对象调用时序图小结前言…
文章目录前言InterceptorChain保存所有的Interceptor创建四大对象都走ConfigurationInterceptorChain增强对象方法Plugin封装动态代理让你使用Mybatis拦截器更简单Invocation让我们能在拦截器中使用动态代理类中的invoke方法中的对象调用时序图小结前言
mybatis拦截器是一个非常有用的功能当你想实现自动分页自动记录执行的sql等功能时若在service层每次调用时都写代码的话会非常麻烦而使用mybatis拦截器就可以非常轻松的实现了。
Executor , ResultSetHandler,StatementHandler,ParameterHandler,这是Mybatis中的四大对象也是拦截器的切入点。我们可以基于这四大对象的方法进行增强。解释一下因为这四个都是接口我们可以利用动态代理进行方法的增强。 动态代理这是底层的原理若只用了动态代理那么你肯定要自己写代理类在使用的时候实例化然后再替换Mybatis里面的原有对象对不但是实际你并不需要这么做那是因为mybatis一开始就为你设计好了让你如何简单快速的添加拦截器让你在添加拦截器的时候只用关注业务逻辑而不需要管类之间的关系。 那么Mybatis究竟是怎么做到这一点的呢接下来就让LZ带大家来看看Mybatis究竟是如何实现的吧。
我们实现mybatis拦截器的步骤首先创建Interceptor的实现类然后我们要在mybatis.xml中配置plugins这就是我们为Mybatis添加拦截器的步骤。
InterceptorChain保存所有的Interceptor
我们来到Configuration类中看到里面他有个属性叫InterceptorChain,里面是用来存放我们的所有拦截器针对四大对象的拦截器全部在里面。
//这里就是解析并把plugin加入到interceptorChain中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);}}}//加入到interceptorChainpublic void addInterceptor(Interceptor interceptor) {interceptorChain.addInterceptor(interceptor);}创建四大对象都走Configuration
然后Mybatis在创建四大对象的时候都是走的Configuration类中的方法
//创建ParameterHandler对象public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {ParameterHandler parameterHandler mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);//都有interceptorChain.pluginAll()parameterHandler (ParameterHandler) interceptorChain.pluginAll(parameterHandler);return parameterHandler;}
//创建ResultSetHandler对象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);//都有interceptorChain.pluginAll()resultSetHandler (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);return resultSetHandler;}
//创建StatementHandler对象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);//都有interceptorChain.pluginAll()statementHandler (StatementHandler) interceptorChain.pluginAll(statementHandler);return statementHandler;}
//创建Executor对象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);}//都有interceptorChain.pluginAll()executor (Executor) interceptorChain.pluginAll(executor);return executor;}观察上面的四个函数他们都有一个共有的点调用了interceptorChain.pluginAll()方法这也是Mybatis实现拦截器功能的中点这个pluginAll使拦截器有了一个特性那就是逻辑可以向下传递是责任链模式。
InterceptorChain增强对象方法
public class InterceptorChain {private final ListInterceptor interceptors new ArrayListInterceptor();public Object pluginAll(Object target) {//通过for循环遍历interceptors将所有的interceptor都加进去。//一层包一层直到所有的interceptor都包装好for (Interceptor interceptor : interceptors) {target interceptor.plugin(target);}return target;}public void addInterceptor(Interceptor interceptor) {interceptors.add(interceptor);}public ListInterceptor getInterceptors() {return Collections.unmodifiableList(interceptors);}}这里进去的对象和出来的对象已经不是同一个了。进去的基础四大对象出来的是增强版四大对象。 这里其实用到了责任链模式每个Interceptor 都有自己要服务的对象只有当请求的方法和Interceptor要服务的对象匹配时它才会执行你拦截器里的方法。 接下来LZ带大家来看看Mybatis是怎么比对两个对象是否匹配的。
Plugin封装动态代理让你使用Mybatis拦截器更简单
我们去Plugin类中
//看到这个类大家有没有觉得很熟悉没错实现了InvocationHandler 使用动态代理
//这个就是Mybatis实现拦截器功能的底层。
public class Plugin implements InvocationHandler {private Object target;private Interceptor interceptor;private MapClass?, SetMethod signatureMap;private Plugin(Object target, Interceptor interceptor, MapClass?, SetMethod signatureMap) {this.target target;this.interceptor interceptor;this.signatureMap signatureMap;}
//我们不需要手动的实例化动态代理对象是因为wrap为我们做了这件事public static Object wrap(Object target, Interceptor interceptor) {//这句也蛮重要的是将我们写的拦截器类的注解转换成了mapkey为我们的类对象value是方法//为了之后判断是否需要执行拦截器的方法//这句就不进去仔细分析了因为很简单就是解析注解而已MapClass?, SetMethod signatureMap getSignatureMap(interceptor);Class? type target.getClass();Class?[] interfaces getAllInterfaces(type, signatureMap);//这里实例了动态代理对象 return interfaces.length 0 ? Proxy.newProxyInstance(type.getClassLoader(), interfaces, new Plugin(target, interceptor, signatureMap)) : target;}
}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {try {//获得方法SetMethod methods (Set)this.signatureMap.get(method.getDeclaringClass());//如果方法不为空说明这个对象确实有拓展拦截器之后看method是不是有这个方法有的话才说明这个方法确实被拓展了之后执行interceptor.intercept()即调用拦截器的方法return methods ! null methods.contains(method) ? this.interceptor.intercept(new Invocation(this.target, method, args)) : method.invoke(this.target, args);} catch (Exception var5) {throw ExceptionUtil.unwrapThrowable(var5);}}Invocation让我们能在拦截器中使用动态代理类中的invoke方法中的对象
//通过这个对象把代理类中的invoke方法中的对象和我们拦截器类相连。
//我们在拦截器类中的intercept(Invocation invocation)中的invocation就是这个类型
//所以我们就能在拦截器类中获取到代理类中的各个对象啦
public class Invocation {private Object target;private Method method;private Object[] args;public Invocation(Object target, Method method, Object[] args) {this.target target;this.method method;this.args args;}public Object getTarget() {return target;}public Method getMethod() {return method;}public Object[] getArgs() {return args;}public Object proceed() throws InvocationTargetException, IllegalAccessException {return method.invoke(target, args);}}调用时序图 小结
总结一下其实底层用到的还是动态代理但是Mybatis通过封装让我们开发拦截器更加简单。通过InterceptorChain使得拦截器能将逻辑向下传递然后通过Invocation让拦截器类能使用到动态代理类invoke中的对象。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/920192.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!