MyBatis插件实现日记

MyBatis提供了一个 interceptor

public interface Interceptor {
    Object intercept(Invocation var1) throws Throwable;

    Object plugin(Object var1); //注册插件

    void setProperties(Properties var1);
}

插件需要使用 Intercepts 注解, Signature 描述拦截的方法签名, 如:

@Intercepts({@Signature(
    type = Executor.class,
    method = "query",
    args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}
), @Signature(
    type = Executor.class,
    method = "query",
    args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}
)})

这里拦截 Executor的查询方法[四个参数和六个参数].

MyBatis Mapper接口使用jdk动态代理 具体类为 MapperProxyFactory:

public class MapperProxyFactory {
    private final Class mapperInterface;
    private final Map methodCache = new ConcurrentHashMap();

    public MapperProxyFactory(Class mapperInterface) {
        this.mapperInterface = mapperInterface;
    }

    public Class getMapperInterface() {
        return this.mapperInterface;
    }

    public Map getMethodCache() {
        return this.methodCache;
    }

    protected T newInstance(MapperProxy mapperProxy) {
        return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);
    }

    public T newInstance(SqlSession sqlSession) {
        MapperProxy mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache);
        return this.newInstance(mapperProxy);
    }
}

通过 MapperProxyFactory可以获取具体的Mapper然后调用接口方法.执行数据库操作

流程为:
SqlSessionFactory得到 SqlSession 然后获得 Configuration 然后 获取Mapper :

public  T getMapper(Class type) {
    return this.configuration.getMapper(type, this);
}

//Configuration
public  T getMapper(Class type, SqlSession sqlSession) {
    return this.mapperRegistry.getMapper(type, sqlSession);
}
//MapperRegistry
public  T getMapper(Class type, SqlSession sqlSession) {
    MapperProxyFactory mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
    if(mapperProxyFactory == null) {
        throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    } else {
        try {
            return mapperProxyFactory.newInstance(sqlSession);
        } catch (Exception var5) {
            throw new BindingException("Error getting mapper instance. Cause: " + var5, var5);
        }
    }
}

你可能感兴趣的:(MyBatis插件实现日记)