这篇主要看下mybatis的Mapper,Mapper可以说是mybatis的入口。这里仅讨论注解的方式。
回顾下第一篇中mybatis是如何使用的。sqlSession = SqlSessionFactoryUtil.getSqlSession();productMapper = sqlSession.getMapper(ProductMapper.class);Product product = productMapper.detail(1);
可以看到获取Session后(第二篇讲到了,本质就是获取到一个数据库连接),获取productMapper,ProductMapper是我们定义的一个接口,detail是我们定义的一个抽象方法。 接口并没有实现方法,因此可以猜想到mybatis帮我们生成了一个实现了ProductMapper接口的类。
思路
那可以试想下,让我们自己实现这个类,是怎样的流程呢?
首先,getMapper有个入参是ProductMapper.class。也就是我们有ProductMapper这个接口,接口上每个方法中的注解上都定义了该如何执行sql。通过反射能够拿到这些sql信息。生成类则可以使用动态代理,因为ProductMapper是接口,我们可以用jdk动态代理。mybatis生成productMapper流程
mybatis生成productMapper是分两步的,第一步是在初始化的时候addMapper,第二步则是在使用的时候getMapper。为什么要这样做呢,因为解析注解、生成工厂类等都是重复的工作。可以在初始化前计算好。使用的时候拿来用就行了。
getMapper流程
publicT getMapper(Class type, SqlSession sqlSession) { final MapperProxyFactory mapperProxyFactory = (MapperProxyFactory ) 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); } }
getMapper的流程比较简单,就是通过Mapper在knownMappers(addMapper中会讲)中取到对应的Mapper代理工厂。然后通过工厂构建Mapper代理。