Mybatis如何使用代理

2021-07-16  本文已影响0人  念䋛

Mybatis如何使用代理,操作数据库
分析过三个执行器,SimpleExecutor ReuseExecutor BatchExecutor,在实际应用中是不会直接使用这三个执行器的,都是使用代理,包括与spring整合的时候,都是将代理之后的bean放到容器中,那mybtis是如何代理的。
我们使用的是MapperProxy代理dao层,也就是spring中经常使用的@Mapper注解标注的接口,看实际代码

public static void main(String[] args) throws IOException, SQLException {
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream (resource);
    //SqlSessionFactoryBuilder(构造器):它会根据配置或者代码来生成SqlSessionFactory,采用的是分步构建的Builder模式。
    //SqlSessionFactory(工厂接口):依靠它来生成SqlSession,使用的是工厂模式。
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder ().build (inputStream);
    //SqlSession(会话):一个既可以发送SQL执行返回结果,也可以获取Mapper的接口。
    //  SqlSession openSession(ExecutorType execType);可以规定使用哪个Executor,默认为 ExecutorType.SIMPLE
    SqlSession sqlSession = sqlSessionFactory.openSession (ExecutorType.REUSE);
    UserDao mapper = sqlSession.getMapper (UserDao.class);
    mapper.queryUser ("id", "1");
    mapper.queryUser ("id", "1");
}

代码中可以看到sqlSession.getMapper (UserDao.class);那是如何代理的
DefaultSqlSession#getMapper
->Configuration#getMapper
->MapperRegistry#getMapper
--return mapperProxyFactory.newInstance(sqlSession);
->MapperProxyFactory#newInstance
-- return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
看到了使用jdk动态代理,我们知道jdk的动态代理,一般都是关注InvocationHandler的实现的invoke方法

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  try {
    if (Object.class.equals(method.getDeclaringClass())) {
      return method.invoke(this, args);
    } else if (isDefaultMethod(method)) {
      return invokeDefaultMethod(proxy, method, args);
    }
  } catch (Throwable t) {
    throw ExceptionUtil.unwrapThrowable(t);
  }
  final MapperMethod mapperMethod = cachedMapperMethod(method);
  return mapperMethod.execute(sqlSession, args);
}

return mapperMethod.execute(sqlSession, args);查看execute方法,都是判断sql的类型,如果是SELECT类型,判断返回类型,这里returnsMany举例
执行result = executeForMany(sqlSession, args);
进入源码发现了
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);代码,到这里就到了我们熟悉的执行器阶段。

@Override
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
  try {
    MappedStatement ms = configuration.getMappedStatement(statement);
//我们熟悉的执行器
    return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
  } catch (Exception e) {
    throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
  } finally {
    ErrorContext.instance().reset();
  }
}
上一篇 下一篇

猜你喜欢

热点阅读