Mybatis插件分析

版权声明:本文为博主原创文章,未经博主允许,请勿转载。 https://blog.csdn.net/qq_36404323/article/details/85005158

拦截器

@Intercepts({@Signature(
    type = StatementHandler.class,
    method = "prepare",
    args = {Connection.class, Integer.class}
)})
public class DataScopeInterceptor implements Interceptor {
    public DataScopeInterceptor() {
    }

    public Object intercept(Invocation invocation) throws Throwable {
        return invocation.proceed();
    }

    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    public void setProperties(Properties properties) {
    }
}

拦截执行器原理

每个执行的对象都需要调用pluginAll方法使其被各个拦截器层层包裹(责任链模式),

包裹方式是在生成执行器前会使用jdk的动态代理借(Plugin implements InvocationHandler)类生成代理执行器,

InterceptorChain类:
    public Object pluginAll(Object target) {
        Interceptor interceptor;
        for(Iterator var2 = this.interceptors.iterator(); var2.hasNext(); target = interceptor.plugin(target)) {
            interceptor = (Interceptor)var2.next();
        }
        return target;
    }

Plugin类:
    public static Object wrap(Object target, Interceptor interceptor) {
        Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
        Class<?> type = target.getClass();
        Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
        return interfaces.length > 0 ? Proxy.newProxyInstance(type.getClassLoader(), interfaces, new Plugin(target, interceptor, signatureMap)) : target;
    }

Plugin类中的signatureMap保存了要拦截方法信息(拦截器@Signature所配置的方法信息),interceptor保存这个拦截器。

在调用执行器代理也就是Plugin类方法是时,会调用Plugin类的invoke方法,

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
            Set<Method> methods = (Set)this.signatureMap.get(method.getDeclaringClass());
            return methods != null && methods.contains(method) ? this.interceptor.intercept(new Invocation(this.target, method, args)) : method.invoke(this.target, args);
        } catch (Exception var5) {
            throw ExceptionUtil.unwrapThrowable(var5);
        }
    }

首先判断方法是否应该被拦截,需要拦截的话拦截器进行拦截并处理。

猜你喜欢

转载自blog.csdn.net/qq_36404323/article/details/85005158