mybatis插件

mybatis可以对四大组件(executor、statementhandler、resultsethandler、parameterhandler)进行拦截

比如增强parameterhandler的时候

 
public ParameterHandler newParameterHandler(MappedStatement mappedStatement,Object object, BoundSql sql, InterceptorChain interceptorChain){
	ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement,object,sql);
	//在这里对parameterhandler进行增强,用拦截器链生成需要增强的类的代理对象
	parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
    return parameterHandler;
}
public Object pluginAll(Object target) {
    for (Interceptor interceptor : interceptors) {
		target = interceptor.plugin(target);
	}
    return target;
}

自定义一个插件 注意注释中的序号

@Intercepts({//花括号中可以定义多个
        @Signature(
                type= Executor.class,//拦截的接口
                method = "query",//拦截的方法
                args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}//方法参数
        )
    }
)
public class MyPlugin implements Interceptor {
	//4.代理类的方法被调用
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("intercept");//执行增强逻辑
        //原方法被调用,在这里即Executor的qurey方法被调用
        return invocation.proceed();
    }

	//1.在前面pluginAll()的时候会调用interceptor.plugin(target);
    @Override
    public Object plugin(Object target) {
        System.out.println("plugin");
        return Plugin.wrap(target,this);
    }

    @Override
    public void setProperties(Properties properties) {
        System.out.println("setProperties");
    }
}

查看org.apache.ibatis.plugin.Plugin

public class Plugin implements InvocationHandler {

  private final Object target;
  private final Interceptor interceptor;
  private final Map<Class<?>, Set<Method>> signatureMap;

  private Plugin(Object target, Interceptor interceptor, Map<Class<?>, Set<Method>> signatureMap) {
    this.target = target;
    this.interceptor = interceptor;
    this.signatureMap = signatureMap;
  }
	//2.在这个方法中会看target需不需要增强
  public static Object wrap(Object target, Interceptor interceptor) {
  	//这个方法中根据自定义类的注解@Signature来获得要被增强的方法
    Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
    Class<?> type = target.getClass();
    //从target的类中找到符合增强的方法
    Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
    //如果需要被增强则生成一个代理
    if (interfaces.length > 0) {
      return Proxy.newProxyInstance(
          type.getClassLoader(),
          interfaces,
          //生成代理后在interfaces的方法被调用的时候会调用Plugin的invoke方法
          new Plugin(target, interceptor, signatureMap));
    }
    return target;
  }

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
      //根据method的class去signatureMap去找这个类需要被增强的方法
      Set<Method> methods = signatureMap.get(method.getDeclaringClass());
      //如果这个类需要被增强
      if (methods != null && methods.contains(method)) {
      	//3.调用自定义Plugin的intercept方法
        return interceptor.intercept(new Invocation(target, method, args));
      }
      return method.invoke(target, args);
    } catch (Exception e) {
      throw ExceptionUtil.unwrapThrowable(e);
    }
  }
  //...省略其他方法

把自定义插件配置到xml中

<plugins>
	<plugin interceptor="com.plugin.MyPlugin">
	</plugin>
</plugins>
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐