Mybatis(7)- 源码解析(5)*Mapper.java接口生成代理对象

Mybatis(7)- 源码解析(5)*Mapper.java接口生成代理对象,第1张

Mybatis(7)- 源码解析(5)*Mapper.java接口生成代理对象

我们在使用mybatis时只定义了类似 ActorMapper 的接口,并没有编写实现这个接口的类,实际上mybatis在初始化时生成了这个接口的代理对象,这篇文章分析下mybatis在何时完成的这件事。

通过 org.apache.ibatis.session.SqlSession.getMapper 方法我们可以获得对象接口的代理类,下面分析下这段代码:

ActorMapper actorMapper = session.getMapper(ActorMapper.class);

org.apache.ibatis.session.defaults.DefaultSqlSession getMapper 方法,从以下代码可知,实际执行的是 configuration 的 getMapper 方法:

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

org.apache.ibatis.session.Configuration getMapper 方法,如下 configuration调用的是 configuration 属性 MapperRegistry mapperRegistry 的方法,mapperRegistry 是在 org.apache.ibatis.builder.xml.XMLConfigBuilder 构造方法中初始化 Configuration过程中初始化的

public  T getMapper(Class type, SqlSession sqlSession) {
    return this.mapperRegistry.getMapper(type, sqlSession);
}

org.apache.ibatis.binding.MapperRegistry

解析完 *Mapper.xml 后,MapperRegistry 中 knownMappers 属性已经填充好了对应 接口和 MapperProxyFactory 的键值对

public class MapperRegistry {
    private final Configuration config;
    private final Map, MapperProxyFactory> knownMappers = new HashMap();
    
    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 {
                // 生成 Mapper 的代理对象
                return mapperProxyFactory.newInstance(sqlSession);
            } catch (Exception var5) {
                throw new BindingException("Error getting mapper instance. Cause: " + var5, var5);
            }
        }
    }
}

org.apache.ibatis.binding.MapperProxyFactory

package org.apache.ibatis.binding;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.ibatis.binding.MapperProxy.MapperMethodInvoker;
import org.apache.ibatis.session.SqlSession;

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) {
        // 通过JDK动态代理的方式生成代理对象
        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);
    }
}

org.apache.ibatis.binding.MapperProxy
如下:MapperProxy 实现了 InvocationHandler 接口

public class MapperProxy implements InvocationHandler, Serializable {
    private static final long serialVersionUID = -4724728412955527868L;
    private static final int ALLOWED_MODES = 15;
    private static final Constructor lookupConstructor;
    private static final Method privateLookupInMethod;
    private final SqlSession sqlSession;
    private final Class mapperInterface;
    private final Map methodCache;

    public MapperProxy(SqlSession sqlSession, Class mapperInterface, Map methodCache) {
        this.sqlSession = sqlSession;
        this.mapperInterface = mapperInterface;
        this.methodCache = methodCache;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
            return Object.class.equals(method.getDeclaringClass()) ? method.invoke(this, args) : this.cachedInvoker(method).invoke(proxy, method, args, this.sqlSession);
        } catch (Throwable var5) {
            throw ExceptionUtil.unwrapThrowable(var5);
        }
    }
}

当执行 selectOneActor 方法时实际调用 MapperProxy invoke 方法,最终从 configuration 中获取 SQL 并替换参数执行

public  List selectList(String statement, Object parameter, RowBounds rowBounds) {
    List var5;
    try {
        MappedStatement ms = this.configuration.getMappedStatement(statement);
        var5 = this.executor.query(ms, this.wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
    } catch (Exception var9) {
        throw ExceptionFactory.wrapException("Error querying database.  Cause: " + var9, var9);
    } finally {
        ErrorContext.instance().reset();
    }

    return var5;
}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/798117.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-06
下一篇 2022-05-06

发表评论

登录后才能评论

评论列表(0条)

保存