在上一篇中Mybatis插件原理分析(一)中我们主要介绍了一下Mybatis插件相关的几个类的源码,并对源码进行了一些解释,接下来我们通过一个简单的插件实现来对Mybatis插件的运行流程进行分析。
一、简单的插件MyInterceptor,源码如下:
/**
* 实现Interceptor的类必须使用注解@Intercepts,Plugin类中的getSignatureMap函数就是来解析这个注解
* 获得注解中的相关信息,比如拦截的method,拦截的接口实现类,以及method的函数参数等
*/
@Intercepts( {
@Signature(method = "query", type = Executor.class, args = {
MappedStatement.class, Object.class, RowBounds.class,
ResultHandler.class })})
public class MyInterceptor implements Interceptor {
//这个函数的最终结果是调用invocation.proceed()方法,调用目标类的method.invoke方法
@Override
public Object intercept(Invocation invocation) throws Throwable {
return invocation.proceed();
}
//这个方法的目的就是将目标类通过代理类Plugin的wrap方法来生成目标类
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
// TODO Auto-generated method stub
}
}
二、mybatis的配文件中添加如下配置:
<plugins>
<plugin interceptor="com.tianjunwei.MyInterceptor"></plugin>
</plugins>
这样就完成了一个简单插件的实现工作。
三、运行流程
(1)在mybatis启动阶段,在Configuration类中的Executor、ParameterHandler、ResultSetHandler和StatementHandler的实现类初始化过程中会调用如下进行初始化:
resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
在InterceptorChain类中调用pluginAll函数,会调用所有已经实现的Interceptor,例如我们刚实现的MyInterceptor类的plugin方法
public Object pluginAll(Object target) {
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}
MyInterceptor类中的plugin方法其实调用的是Plugin的wrap函数,wrap函数是用来生代理类的目标类的
//这个方法的目的就是将目标类通过代理类Plugin的wrap方法来生成目标类
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
Plugin类中的wrap实现如下,其目的就是生成目标类,这样Executor、ParameterHandler、ResultSetHandler和StatementHandler的实现类都是目标类
//一个静态方法,对一个目标对象进行包装,生成目标类。
public static Object wrap(Object target, Interceptor interceptor) {
//首先根据interceptor上面定义的注解 获取需要拦截的信息
Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
Class<?> type = target.getClass();
Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
//如果长度为>0 则返回代理类 否则不做处理
if (interfaces.length > 0) {
//创建JDK动态代理对象
return Proxy.newProxyInstance(
type.getClassLoader(),
interfaces,
new Plugin(target, interceptor, signatureMap));
}
return target;
}
我们以Executor的实现类来说明,当调用Executor的query方法是,根据代理类机制会调用Plugin的invoke方法
在invoke方法中我们可以看,首先会判断目标类调用的方法是否是我们在实现的MyInterceptor的注解中进行了配置,如果配置了则会调用interceptor.intercept(new Invocation(target, method, args));,这样的话就是调用的MyInterceptor的intercept方法,否则则直接调用return method.invoke(target, args);,
//在执行Executor、ParameterHandler、ResultSetHandler和StatementHandler的实现类的方法时会调用这个方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
//通过method参数定义的类 去signatureMap当中查询需要拦截的方法集合
Set<Method> methods = signatureMap.get(method.getDeclaringClass());
//判断是否是需要拦截的方法,如果需要拦截的话就执行实现的Interceptor的intercept方法,执行完之后还是会执行method.invoke方法,不过是放到interceptor实现类中去实现了
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);
}
}
因为在MyInterceptor的plugin方法中已经把MyInterceptor作为参数赋值给Plugin了,代码如下
//这个方法的目的就是将目标类通过代理类Plugin的wrap方法来生成目标类
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
总结:Mybatis的插件的原理就是对Executor、ParameterHandler、ResultSetHandler和StatementHandler的实现类通过Plugin代理来生成目标类,并且关联生成的目标类与实现的Interceptor类,这样在调用Executor、ParameterHandler、ResultSetHandler和StatementHandler的实现类方法时会调用Plugin类中的invoke方法,在调用invoke方法时会进行判断这个实现类是否需要我们实现的MyInterceptor来处理,如果是会调用MyInterceptor的interceptor方法,进行一些处理之后调用Invocation的proceed方法,其实际处理方法也是调用method.invoke方法,如果不需要MyInterceptor处理时则直接调用method.invoke方法,Mybatis巧妙的利用的JDK的代理机制,实现了对目标类和方法在调用之前的一些处理,提高了整个框架的灵活性。
分享到:
相关推荐
而"Idea MyBatis插件"则是针对IntelliJ IDEA这个强大的Java集成开发环境设计的一款增强工具,它可以提供更高效、便捷的MyBatis开发体验。 该插件的直接可用性意味着用户无需复杂设置,只需按照指定路径将其放置在...
总的来说,理解 MyBatis 插件原理和自定义插件的编写,可以帮助我们更好地扩展 MyBatis 的功能,实现更灵活的数据库操作。同时,掌握 Spring 集成 MyBatis 的方法,可以确保事务管理和资源管理的正确性,提升系统的...
这个教程可能深入解析了Mybatis插件的原理、安装、配置以及如何利用它们优化数据库操作。 【描述】"Mybatis系列教程Mybatis插件共8页.pdf.zip" 描述了教程的形式和大致内容。它是以PDF文档的形式存在,且压缩包内...
9. **缓存机制**:分析Mybatis的一级缓存和二级缓存,如何配置和使用,以及缓存的刷新策略和一致性问题。 10. **插件机制**:探讨Mybatis的插件扩展,如PageHelper分页插件的实现原理,以及自定义插件的编写方法。 ...
此外,还将涉及MyBatis的插件机制,如PageHelper分页插件,以及如何使用MyBatis进行关联查询和一对一、一对多、多对多的关系映射。 在实际开发中,MyBatis不仅适用于传统的单表操作,还能处理复杂的业务场景,如...
本篇文章将通过解析“一图读懂mybatis插件plugin原理”来深入理解MyBatis Plugin的工作机制。 首先,我们需要了解MyBatis Plugin的基本概念。Plugin是MyBatis中用于拦截SqlSession方法的组件,它基于Java的动态代理...
为了实现这个功能,开发者可能需要创建一个 MyBatis 插件,该插件解析 MyBatis 的 XML 映射文件,提取出 SQL 语句和参数,然后将这些信息传递给 IDE,使其能够进行智能分析和提示。 对于标签中的 "mybatis 插件",...
本书还会讲解MyBatis的插件机制,开发者可以通过自定义插件拦截执行的SQL语句,进行日志记录、性能分析等操作。此外,MyBatis的缓存机制也是其高效性能的关键,分为一级缓存和二级缓存,可以有效减少对数据库的访问...
通过自定义插件,开发者可以实现诸如日志记录、性能分析等功能,提高开发效率和应用性能。 最后,书中还提供了大量实战案例,帮助读者将理论知识应用于实际项目中,例如多表联查、级联操作、缓存机制等。这些实战...
通过《深入浅出MyBatis技术原理与实战》这本书,读者可以系统学习MyBatis的各个方面,包括基础概念、核心组件、映射机制、事务管理、缓存策略,以及在实际项目中的应用技巧,从而成为一名熟练掌握MyBatis的开发者。
《深入浅出myBatis技术原理与实战》是由著名IT专家杨开振撰写的一本关于Mybatis技术的专著,这本书旨在帮助初中级开发者全面理解并掌握Mybatis框架的运用和核心原理。Mybatis作为一款广泛应用的Java持久层框架,以其...
本课程全面讲解了Mybatis-Plus框架的使用,从快速入门到原理分析再到插件的应用。每一个知识点都有案例进行演示学习,最终通过学习你将全面掌握MP的使用,从而使Mybatis的的开发更加的高效,达到事半功倍的效果。 ...
MyBatis插件系统允许开发者自定义拦截器,对MyBatis的执行流程进行拦截,实现如日志记录、性能分析、动态SQL等功能。在描述中提到的插件,可能是用于增强MyBatis开发体验的工具,例如代码生成器、SQL调试助手等。将...
通过自定义插件,开发者可以扩展MyBatis的功能,例如日志记录、性能分析等。书中会讲解如何编写和注册插件,以及插件工作原理。 实战部分,书中的实例涵盖了增删改查操作、复杂查询、关联查询、批量操作等多种常见...
6. **最佳实践**:使用MyBatis插件时,应遵循最佳实践,如保持Mapper接口和XML配置的一致性,合理利用缓存,避免复杂的嵌套查询,以及定期清理和更新插件,确保其兼容性和稳定性。 总之,"Free MyBatis Plugins" ...
二、Mybatis分库分表插件原理 Mybatis的插件机制基于拦截器(Interceptor)设计模式,允许在执行SQL之前或之后插入自定义逻辑。分库分表插件主要工作在SQL路由阶段,根据特定的规则(如哈希、范围等)对原始SQL进行...
3. **MyBatis分页插件原理** MyBatis分页插件的工作原理是动态插入SQL,它会在执行查询语句之前,根据数据库类型(如MySQL或Oracle)动态生成合适的分页SQL。例如,对于MySQL,它会将原SQL语句转换为带有LIMIT和...
分析MyBatis源码有助于开发者更深入地理解框架的工作原理,提升问题解决能力,优化性能,以及在遇到异常时能够快速定位问题所在。 3. **MyBatis核心组件** - **SqlSessionFactoryBuilder**:用于创建...
首先,了解 MyBatis 插件的工作原理。MyBatis 的插件基于 Java 的动态代理机制,插件是对 MyBatis 中某些接口(如 Executor、StatementHandler、ParameterHandler 和 ResultSetHandler)的方法进行拦截。当这些接口...