自定义插件要实现mybatis的插件接口 Interceptor
public interface Interceptor { // 执行拦截逻辑的方法 Object intercept(Invocation invocation) throws Throwable; // 决定是否触发 intercept()方法,如果该插件是拦截对应方法,则返回该类的代理对象 default Object plugin(Object target) { return Plugin.wrap(target, this); } // 根据配置 初始化 Intercept 对象 default void setProperties(Properties properties) { // NOP }}
自定义拦截器
@Intercepts({
@Signature(
type = Executor.class // 需要拦截的类型
, method = “query” // 需要拦截的方法
// args 中指定 被拦截方法的 参数列表
, args = {MappedStatement.class, Object.class, RowBounds.class,
ResultHandler.class}
),
@Signature(
type = Executor.class
, method = “close”
, args = {boolean.class}
)
})
public class MyInterceptor implements Interceptor {
public Object intercept(Invocation invocation) throws Throwable {
System.out.println(“被拦截方法执行前打印。。。”);
Object object = invocation.proceed();
System.out.println(“被拦截方法执行后打印。。。”);
return object;
}public Object plugin(Object target) { return Plugin.wrap(target, this);}public void setProperties(Properties properties) {}
}
插件配置初始化插件拦截的4个类:Excutor ParameterHandler StatementHandler ResultSetHandler
初始化
SqlSessionFactoryBuilder
public SqlSessionFactory build(Reader reader, String environment, Properties properties) { try { // 读取配置文件 XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties); // 解析配置文件得到Configuration对象 创建DefaultSqlSessionFactory对象 return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { reader.close(); } catch (IOException e) { // Intentionally ignore、Prefer previous error. } } }
XMLConfigBuilder
插件解析:pluginElement(root.evalNode(“plugins”));,最终得到
InterceptorsChain 对象,里面对插件进行管理
private void parseConfiguration(XNode root) { try { //issue #117 read properties first // 对于全局配置文件各种标签的解析 propertiesElement(root.evalNode("properties")); // 解析 settings 标签 Properties settings = settingsAsProperties(root.evalNode("settings")); // 读取文件 loadCustomVfs(settings); // 日志设置 loadCustomLogImpl(settings); // 类型别名 typeAliasesElement(root.evalNode("typeAliases")); // 插件 pluginElement(root.evalNode("plugins")); // 用于创建对象 objectFactoryElement(root.evalNode("objectFactory")); // 用于对对象进行加工 objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); // 反射工具箱 reflectorFactoryElement(root.evalNode("reflectorFactory")); // settings 子标签赋值,默认值就是在这里提供的 >> settingsElement(settings); // read it after objectFactory and objectWrapperFactory issue #631 // 创建了数据源 >> environmentsElement(root.evalNode("environments")); databaseIdProviderElement(root.evalNode("databaseIdProvider")); typeHandlerElement(root.evalNode("typeHandlers")); // 解析引用的Mapper映射器 mapperElement(root.evalNode("mappers")); } catch (Exception e) { throw new BuilderException("Error parsing SQL Mapper Configuration、Cause: " + e, e); } }
InterceptorsChain
public class InterceptorChain { // 保存所有的 Interceptor 也就我所有的插件是保存在 Interceptors 这个List集合中的 private final List
代理方法的执行 plugin
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { // 获取当前方法所在类或接口中,可被当前Interceptor拦截的方法 Set
Interceptor :插件接口,用户自定义插件需要实现该接口
InterceptroChain :插件链管理:应用中所有的插件在初始化节点都会解析放到该对象中进行管理
Plugin :插件触发管理类,负责对插件对象进行代理包装,同时实现invoke调用逻辑,实现多个插件的层层调用
Invocation:调用方法的包装对象,封装调用方法的信息
@Interceptors 拦截的配置注解
@Signature :拦截方法签名注解