1. 问题背景
使用mybatis + mapper配置的方式,在业务代码中
1.1 定义,自动导入Dao类
@Resource
private ViewpointPkgDao viewpointPkgDao;
1.2 使用,直接使用ViewpointPkgdao.listViewpointPkg()
// 单独在粉丝端过滤出没有关联组合code的观点包
List<ViewpointPkgFullInfo> noRelated = viewpointPkgDao.listViewpointPkg(qryForm).stream().
filter(vp -> StringUtil.isEmpty(vp.getCombiCode())).collect(Collectors.toList());
viewpointPkgList = CommonTool.genCopyBeanList(noRelated,
该listViewpointPkg
方法在ViewpointPkgdaoMapper.xml
中有定义,即sql实现了该方法,指定了出参和入参,
<select id="listViewpointPkg"
parameterType="xxxx.ViewpointPkgDataBaseQryForm"
resultType="xxxxx.ViewpointPkgFullInfo">
SELECT
a.viewpoint_pkg_id AS viewpointPkgId,
a.name,
a.broker_id AS brokerId,
a.broker_manager_id AS brokerManagerId,
a.status,
...
FROM
<include refid="filterViewpointPkgFullInfoSql"/>
<if test="orderBySql != null">
ORDER BY ${orderBySql}
</if>
<if test="limitSql != null">
LIMIT ${limitSql}
</if>
</select>
为啥,通过MyBatis对ViewpointPkgDaomapper.xml
自动生成工具代码后,本质MyBatis和我们都没有实现ViewpointPkgDao
接口,业务代码中能直接调用ViewpointPkgDao
接口的相关方法?
答案是: spring容器bean注入+动态代理
从调试结果也证明了这一动态代理猜想,org.apache.ibatis.binding.MapperProxy@6304a864
2. spring 注入mapperBean
https://zhuanlan.zhihu.com/p/196744982
3. 动态代理
3.1 定义
org.apache.ibatis.binding.MapperProxy
// 实现了 InvocationHandler接口??有何用
public class MapperProxy<T> implements InvocationHandler, Serializable {
private final SqlSession sqlSession;
private final Class<T> mapperInterface;
private final Map<Method, MapperMethod> methodCache;
// 构造,传入了 SqlSession,说明每个session中的代理对象的不同的!
public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {
this.sqlSession = sqlSession;
this.mapperInterface = mapperInterface;
this.methodCache = methodCache;
}
3.2 被创建
org.apache.ibatis.binding.MapperProxyFactory#newInstance
通过mapper代理工厂创建mapper代理
// jdk动态代理
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] {
mapperInterface },