Mybatis插件分析

本文探讨Mybatis插件的拦截器机制,解析执行器的拦截原理。每个执行对象通过Plugin实现InvocationHandler动态代理,形成责任链模式,Plugin内部维护signatureMap存储拦截方法信息,interceptor存储拦截器。当调用代理执行器时,Plugin的invoke方法判断并执行拦截操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

拦截器

@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);
        }
    }

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值