zoukankan      html  css  js  c++  java
  • 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方法,

  • 相关阅读:
    Flask ~~“一见钟情之初体验”(Web表单)
    Flask ~~“一见钟情之初体验”(Flask~~过滤~包含~继承~宏)
    Flask ~~“一见钟情之初体验”(flask的网页模板介绍及使用①)
    Flask ~~“一见钟情之初体验”(flask的request模块的属性及上下文)
    Flask ~~“一见钟情之初体验”(cookie与session简单使用)
    Flask 入门(补充)~~~“一见钟情之初体验”
    表单中的单文件点击和拖拽上传
    HTML5存储之 indexedDB
    JavaScript中的 offset, client,scroll
    js 获取 url 里面的参数
  • 原文地址:https://www.cnblogs.com/a-small-lyf/p/12704217.html
Copyright © 2011-2022 走看看