文章图片
【Java|详解Mybatis 拦截器实现原理】拦截器概述
- 像springmvc一样,mybatis也提供了拦截器实现,只是他们拦截的对象不同。
- mybatis给Executor、StatementHandler、ResultSetHandler、ParameterHandler提供了拦截器功能,
- Executor提供了增删改查的接口.
- StatementHandler负责处理Mybatis与JDBC之间Statement的交互.
- ResultSetHandler负责处理Statement执行后产生的结果集,生成结果列表.
- ParameterHandler是Mybatis实现Sql入参设置的对象。
- 拦截器采用了责任链模式,把请求发送者和请求处理者分开,各司其职。
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class StatementInterceptor implements Interceptor {public Object intercept(Invocation invocation) throws Throwable {
System.out.println(" hello Statement interceptor !");
return invocation.proceed();
}public Object plugin(Object target) {
Object wrap = Plugin.wrap(target, this);
return wrap;
}public void setProperties(Properties properties) {}
}
开始一个Statement拦截器,在mybatis-config.xml加入plugin配置,编写一个StatementInterceptor类。这样就已经完成了一个拦截器的编写,该类会链接StatementHandler的prepare方法。
给大家免费分享一套资料,这套资料包含面试题,视频,简历模板,成长路径,核心总结文档,需要这份资料的小伙伴,点击这里即可免费领取,备注暗号 CSDN
![]()
文章图片
MyBatis 加载intercetor过程

文章图片
pluginElement() 是Confiration中,解析XML并把interceptorInstance加入到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);
}
}
}
到这里Confiration对象已经持有了一个InterceptorChain属性, InterceptorChain中只有一个intercetor的list集合。
sqlSessionFactory.openSession(),会创建Executor、StatementHandler、ResultSetHandler、ParameterHandler对象。
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;
}
executor = (Executor) interceptorChain.pluginAll(executor); 注意这一行代码,executor在这里已经被修改成一个代理对象。
推荐阅读
- Mybatis|基于Mybatis拦截器实现数据库切换
- Mybatis|Mybatis事务管理深入理解
- xml|MyBatis03:连接池及事务控制、xml动态SQL语句、多表操作
- mybatis|MyBatis事务
- 程序员|Java进阶(mysql的事务隔离级别面试题)
- 关于mybatis的 insert into select 命令未结束问题
- springboot配置druid数据源及druid的日志监控
- JAVA|SpringBoot配置druid连接池
- SSM|SpringMVC拦截器 & SpringMVC异常处理