mybatis之MapperFactoryBean源码解读
来源:互联网 发布:廖雪峰的javascript 编辑:程序博客网 时间:2024/06/06 17:03
在我们使用mybatis开发dao层的时候,我们可以直接写好dao层接口,然后借助MapperFactoryBean直接代理,这样我们就不需要显示的实现dao接口,刚接触到这个技术点的时候就对这个MapperFactoryBean十分感兴趣,所以在了解了背后的实现机制时,就写下我的所见所得。
先来看看MapperFactoryBean的继承关系
从类的的继承图中可以看出来实现了FactoryBean,这是一个spring提供的工厂接口,其次继承了SqlSessionDaoSupport,SqlSessionSurpport最顶层实现了InitializingBean,InitializingBean接口定义了afterProper'tiesSet()方法,当一个类实现这个接口,spring容器在初始化一个Bean时,在初始化Bean并设置好相关的属性后就会调用这个方法,我们就可以利用这个接口来实现我们的一些初始化工作。
在DaoSupport中实现afterPropertiesSet()调用了CheckDaoConfig()
public final void afterPropertiesSet() throws IllegalArgumentException, BeanInitializationException { this.checkDaoConfig(); try { this.initDao(); } catch (Exception var2) { throw new BeanInitializationException("Initialization of DAO failed", var2); } }所以在MapperFactoryBean中重写了afterPropertiesSet()方法
protected void checkDaoConfig() { super.checkDaoConfig(); notNull(this.mapperInterface, "Property 'mapperInterface' is required"); Configuration configuration = getSqlSession().getConfiguration(); if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) { try { configuration.addMapper(this.mapperInterface); } catch (Exception e) { logger.error("Error while adding the mapper '" + this.mapperInterface + "' to configuration.", e); throw new IllegalArgumentException(e); } finally { ErrorContext.instance().reset(); } } }
在Configuration类中添加代理的接口,所以在初始化Bean时,spring通过getObject()获得代理的接口。
@Override public T getObject() throws Exception { return getSqlSession().getMapper(this.mapperInterface); }
通过SqlSession获得代理类,我们继续在DefaultSqlSession中查看
public <T> T getMapper(Class<T> type) { return configuration.<T>getMapper(type, this); }在代码中可以按到代理接口通过SqlSession所对应的Configuration获得,Configuration是一个保存XML文件相关信息的类,与SqlSession绑定。
public <T> T getMapper(Class<T> type, SqlSession sqlSession) { return mapperRegistry.getMapper(type, sqlSession); }Configuration是保存mybatis中XML的信息,要获得接口的代理需要通过MapperRegistry获得
@SuppressWarnings("unchecked") 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); } }
看到这里终于找到了代理的终点,通过MapperProxyFactory类,从类名中就可以看出来这是一个代理工厂,最终mapperProxyFactory.newInstance()获得接口的代理
@SuppressWarnings("unchecked") 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); }newInstance方法通过new 一个MapperProxy,然后通过JDK中Proxy获得接口的代理,我们知道常用的代理有两种,一种是JDK代理,一种是cglib代理,那么mybatis是使用哪种代理呢?我们可以查看MapperProxy类来看看到底是使用哪种代理
public class MapperProxy<T> implements InvocationHandler, Serializable从代码中可以明确看出来是使用JDK动态代理的,到这里我们就分析完了mybatis的接口自动代理了。
阅读全文
0 0
- mybatis之MapperFactoryBean源码解读
- Spring-MyBatis 之 MapperFactoryBean
- spring mybatis 之MapperFactoryBean
- spring-mybatis —— MapperFactoryBean之数据映射文件
- spring-mybatis——MapperFactoryBean 之映射接口
- Spring/mybatis整合之MapperScannerConfigurer和MapperFactoryBean区别
- spring整合mybatis(基于MapperFactoryBean)
- spring-mybatis整合一MapperFactoryBean
- Mybatis源码解读
- mybatis源码解读(1)
- mybatis源码解读(2)
- mybatis源码解读(3)
- mybatis源码解读(5)
- mybatis源码解读(6)
- mybatis源码解读(7)
- mybatis源码解读(8)
- MyBatis插件原理-源码解读
- spring整合mybatis(不基于MapperFactoryBean)
- web开发图表(ichartjs组件开发)
- 可自定义分页宽度的UIScrollView(Swift实现)
- 线性筛素数的欧拉筛法
- DBSCAN算法
- 谷歌电子市场开发流程(9)-线程,线程池
- mybatis之MapperFactoryBean源码解读
- 1008. 数组元素循环右移问题 --秒杀超简单方法
- 面向对象——异常RuntimeException
- Cloudera Manager 5和CDH5离线安装
- laravel
- webview 输入框无法调用键盘
- [LeetCode] String to Integer (atoi) Python
- 剑指offer-两个链表的第一个公共节点
- display:table-cell自适应布局下连续单词字符换行