Mybatis---01Mybatis动态代理过程分析
1.通过调试,session调用的getMapper是其实现类DefaultSQLSession中的
//1.读取配置文件 InputStream in = Resources.getResourceAsStream("mybatis-config.xml"); //2.创建 SqlSessionFactory 的构建者对象 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); //3.使用构建者创建工厂对象 SqlSessionFactory SqlSessionFactory factory = builder.build(in); //4.使用 SqlSessionFactory 生产 SqlSession 对象 SqlSession session = factory.openSession(); //5.使用 SqlSession 创建 dao 接口的代理对象 IBookDao bookDao = session.getMapper(IBookDao.class); //6.使用代理对象执行查询所有方法 List<Book> books = bookDao.selectAll(); for (Book book : books) { System.out.println(book); } //7.释放资源 session.close(); in.close();
2.在DefaultSQLSession类中getMapper方法如下,里面调用Configuration类的泛型方法<T> T getMapper(Class<T> type)
@Override public <T> T getMapper(Class<T> type) { return configuration.<T>getMapper(type, this); }
3.在Configuration类中查看getMapper(type, sqlSession)方法,里面调用的是MapperRegistry类里面的getMapper(type, sqlSession)方法。
public <T> T getMapper(Class<T> type, SqlSession sqlSession) { return mapperRegistry.getMapper(type, sqlSession); }
4.进入MapperRegistry类里面查看getMapper(type, sqlSession)方法。里面通过属性knownMappers里面的方法get(Object key)获取MapperProxyFactory<T>泛型类,使用这个类里面的newInstance(SqlSession sqlSession)方法。
private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>(); public <T> T getMapper(Class<T> type, SqlSession sqlSession) { final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type); if (mapperProxyFactory == null) { throw new BindingException("Type " + type + " is not known to the MapperRegistry."); } try { return mapperProxyFactory.newInstance(sqlSession); } catch (Exception e) { throw new BindingException("Error getting mapper instance. Cause: " + e, e); } }
5.进入MapperProxyFactory<T>泛型类,查看newInstance(SqlSession sqlSession)方法如下;这里面生成一个MapperProxy<T>对象mapperProxy,然后使用T newInstance(MapperProxy<T> mapperProxy)实现动态代理。其中MapperProxy<T>类实现了接口InvocationHandler。重写了Object invoke(Object proxy, Method method, Object[] args)方法
protected T newInstance(MapperProxy<T> mapperProxy) { return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy); } public T newInstance(SqlSession sqlSession) { final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache); return newInstance(mapperProxy); }
6.查看MapperProxy<T>类里的invoke方法.
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { if (Object.class.equals(method.getDeclaringClass())) {//并不是每个方法都需要调用代理对象进行执行,如果这个方法是Object中通用的方法,则无需执行 return method.invoke(this, args); } else if (isDefaultMethod(method)) {//判断是不是接口默认方法,1.8之后接口就有默认方法了 return invokeDefaultMethod(proxy, method, args); } } catch (Throwable t) { throw ExceptionUtil.unwrapThrowable(t); } //从缓存中获取MapperMethod对象,如果缓存中没有,则创建一个,并添加到缓存中 final MapperMethod mapperMethod = cachedMapperMethod(method); // 执行方法对应的 SQL 语句 return mapperMethod.execute(sqlSession, args); }
7.查看MapperMethod 类的execute方法,这个方法是执行sql的主要方法,根据我写的程序这里是调用executeForMany方法,实际上这个方法DefaultSqlSession类里面的selectList方法。
public Object execute(SqlSession sqlSession, Object[] args) { Object result; switch (command.getType()) { //insert语句的处理逻辑 case INSERT: { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.insert(command.getName(), param)); break; } //update语句的处理逻辑 case UPDATE: { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.update(command.getName(), param)); break; } //delete语句的处理逻辑 case DELETE: { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.delete(command.getName(), param)); break; } //select语句的处理逻辑 case SELECT: if (method.returnsVoid() && method.hasResultHandler()) { executeWithResultHandler(sqlSession, args); result = null; } else if (method.returnsMany()) { result = executeForMany(sqlSession, args); } else if (method.returnsMap()) { result = executeForMap(sqlSession, args); } else if (method.returnsCursor()) { result = executeForCursor(sqlSession, args); } else { Object param = method.convertArgsToSqlCommandParam(args); result = sqlSession.selectOne(command.getName(), param); } break; case FLUSH: result = sqlSession.flushStatements(); break; default: throw new BindingException("Unknown execution method for: " + command.getName()); } if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) { throw new BindingException("Mapper method '" + command.getName() + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ")."); } return result; }
private <E> Object executeForMany(SqlSession sqlSession, Object[] args) { List<E> result; Object param = method.convertArgsToSqlCommandParam(args); if (method.hasRowBounds()) { RowBounds rowBounds = method.extractRowBounds(args); result = sqlSession.<E>selectList(command.getName(), param, rowBounds); } else { result = sqlSession.<E>selectList(command.getName(), param); } // issue #510 Collections & arrays support if (!method.getReturnType().isAssignableFrom(result.getClass())) { if (method.getReturnType().isArray()) { return convertToArray(result); } else { return convertToDeclaredCollection(sqlSession.getConfiguration(), result); } } return result; }
在这里,动态代理过程就完成了。大致执行过程是 sqlSession.getMapper()【这个sqlSession实际上是 DefaultSqlSession】-----调用---->Configuration.getMapper()-----调用--->MapperRegistry.getMapper() ------调用-->MapperProxyFactory.newInstance() -------调用----> Proxy.newProxyInstance()【其中的InvocationHandler接口由实现类MapperProxy代替】------invoke----->MapperMethod.execute()-----调用----->DefaultSqlSession.相应方法

浙公网安备 33010602011771号