核心对象
MyBatis 插件的运行是基于 JDK 动态代理 + 拦截器链实现
-
Interceptor 是拦截器,可以拦截 Executor, StatementHandle, ResultSetHandler, ParameterHandler 四个接口
实际就是利用 JDK动态代理,生成对应的代理类实例,通过
InvocationHandler#invoke
实现拦截逻辑 -
InterceptorChain 是拦截器链,对象定义在 Configuration 类中, 实际是一个 List集合,元素就是 Interceptor接口的实现类
-
Invocation 是对方法、方法参数、执行对象和方法的执行的封装,就是对
InvocationHandler#invoke
方法参数的封装
加载解析拦截器
mybatis-config.xml
<configuration>
<plugins>
<plugin interceptor="io.github.tangmonkmeat.MyInterceptor1" />
<plugin interceptor="io.github.tangmonkmeat.MyInterceptor2"/>
</plugins>
</configuration>
拦截器的解析是在 XMLConfigBuilder
对象的 parseConfiguration
方法中,
如果是 Mybatis ,则从 SqlSessionFactoryBuilder#build
方法开始
如果是 springboot-mybatis-starter,则从 SqlSessionFactoryBean#buildSqlSessionFactory
开始
private void parseConfiguration(XNode root) {
try {
// issue #117 read properties first
propertiesElement(root.evalNode("properties"));
Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfs(settings);
loadCustomLogImpl(settings);
typeAliasesElement(root.evalNode("typeAliases"));
// 开始加载解析插件的标签,添加到 Configuration
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectorFactoryElement(root.evalNode("reflectorFactory"));
settingsElement(settings);
// read it after objectFactory and objectWrapperFactory issue #631
environmentsElement(root.evalNode("environments"));
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
typeHandlerElement(root.evalNode("typeHandlers"));
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
拦截器(Interceptor)
Interceptor 接口配置文件中类需要实现的接口,可以添加属性,在方法执行前后添加自定义逻辑代码
代理类,通过 InvocationHandler#invoke
调用 拦截器的 intercept
方法,实现拦截逻辑
@Intercepts({
// 被代理类的类型,和 需要代理的方法名及其参数类型
@Signature(
type = Executor.class,
method = "query",
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}
)
})
public class MyInterceptor1 implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 拦截器逻辑
// ...
// 反射调用 被代理类的方法
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
// default impl
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}
将拦截器配置添加 Configuration
创建拦截器、设置属性、添加到 Configuration 的拦截器链 InterceptorChain
InterceptorChain 实际是一个 List集合 private final List<Interceptor> interceptors = new ArrayList<>();
private void pluginElement(XNode parent) throws Exception {
if (parent != null) {
for (XNode child : parent.getChildren()) {
// 拦截器全类名 io.github.tangmonkmeat.MyInterceptor1
String interceptor = child.getStringAttribute("interceptor");
// 获取配置属性, 如果interceptor标签没有其他属性,则为 null
Properties properties = child.getChildrenAsProperties();
// 根据全类名,创建拦截器实例
Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).getDeclaredConstructor().newInstance();
// 设置拦截器的属性
interceptorInstance.setProperties(properties);
// 添加拦截器到 configuration 的拦截器链 InterceptorChain 中
configuration.addInterceptor(interceptorInstance);
}
}
}
拦截器逻辑插入到四大核心接口
实际就是 利用 JDK的动态代理, 生成 核心接口实现类的代理类,
比如 SimpleExecutor,使用 Plugin 类 作为 InvocationHandler的实现类,
Plugin 持有 SimpleExcutor的引用,和 拦截器的引用,可以在 invoke方法中添加 拦截处理逻辑
Plugin (InvocationHandler的实现类)
public class Plugin implements InvocationHandler {
// 被代理类
private final Object target;
// 拦截器
private final Interceptor interceptor;
private final Map<Class<?>, Set<Method>> signatureMap;
// ...
// Configuration 会调用此方法,生成 代理类
// 如果拦截器有多个,可以循环调用此方法,生成代理类的代理类。。。
// 返回最外层的代理类,最内部的就是 被代理类
public static Object wrap(Object target, Interceptor interceptor) {
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,
// InvocationHandler
new Plugin(target, interceptor, signatureMap));
}
return target;
}
@Override
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);
}
}
}
添加拦截器
public class Configuration {
// 拦截器链,实际就是一个 List集合
protected final InterceptorChain interceptorChain = new InterceptorChain();
// 参数处理
public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
//创建参数处理对象
ParameterHandler parameterHandler = mappedStatement.getLang().
createParameterHandler(mappedStatement, parameterObject, boundSql);
//将拦截器链中的拦截器拦截动态代理中的参数处理方法执行,加入插件逻辑
parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
return parameterHandler;
}
// 结果集处理
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;
}
// 数据库操作处理
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);
//将拦截器链中的拦截器拦截动态代理中的数据库操作方法执行,加入插件逻辑
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
// 执行器处理
// SimpleExecutor 就是在这里生成的
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;
}
}
附录
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/69688.html