mybatis源码1.2:mapper接口代理对象的获取

由于我实在是感觉自己功力不够选择跳过  SqlSession sqlSession = sessionFactory.openSession();过段时间再看

接下来开始查看 

UserMapper mapper = sqlSession.getMapper(UserMapper.class);

调用Configuration对象得getMapper方法

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

Configuration得getMapper方法,返回得是Configuration对象中MapperRegistry的getMapper方法,MapperRegistry中使用一个Map(knowMappers)保存了扫描到的mapper接口信息,具体的话保存的就是mapper接口的Class对象

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

MapperRegistry中的getMapper方法

    public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
      /*
       *  根据我们调用session.getMapper中传递的Class对象,去map中查找是否存在,map的key就是扫描的的mapper接口的Class对象
       *  value就是MapperProxyFactory,里面有个mapperInterface成员,保存的也是mapper接口的Class对象
       */
MapperProxyFactory
<T> 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); } } }

接下来进入mapperProxyFactory.newInstance方法,MapperProxyFactory是帮我们创建MapperProxy对象,他实现了InvocationHandler接口,这是一个代理类

    protected T newInstance(MapperProxy<T> mapperProxy) {
    //2,通过Proxy对象来创建代理对象 ,最后拿到mapper接口的代理对象,并返回
return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy); }    public T newInstance(SqlSession sqlSession) {
    //1,创建代理类对象 MapperProxy
<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache); return this.newInstance(mapperProxy); }

MapperProxy实现了InvocationHandler接口,里面有个invoke方法,当通过Proxy.newProxyInstance生成的代理对象调用真实对象的方法时,会执行该invoke方法

比如:UserMapper mapper = sqlSession.getMapper(UserMapper.class)  调用mapper中的方法时:mapper.getUserById(1) 就会调用invoke,这是关于jdk动态代理的知识

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
        /*
          首先我们得mapper接口时没有实现类的,也就是没有具体的实现方法,里面的方法是不能反射调用的
          但是如果是Object中的方法就可以调用
          method.getDeclaringClass用来判断当前这个方法是属于哪个类的方法。
          动态代理对象是可以调用toString,hashCode等这些从Object对象中继承的方法
          如果是调用这类方法的话直接反射调用,
         */
if (Object.class.equals(method.getDeclaringClass())) { return method.invoke(this, args); } if (method.isDefault()) { return this.invokeDefaultMethod(proxy, method, args); } } catch (Throwable var5) { throw ExceptionUtil.unwrapThrowable(var5); }        MapperMethod mapperMethod = this.cachedMapperMethod(method);
      //这里大概就是执行db操作的方法了
return mapperMethod.execute(this.sqlSession, args); }

 通过sqlSession获取的mapper对象其实时通过jdk的动态代理生成的一个代理对象,mapper接口就是被代理的一方

通过Proxy生成的代理对象调用方法时会调用代理类(MapperProxy)中的invoke方法,

 

posted @ 2020-04-15 11:44  不爱笑青年  阅读(466)  评论(0编辑  收藏  举报