Mybatis如何使用代理
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();
}
}