在简析代理模式开发之前,先了解一下传统DAO模式开发:
在传统DAO模式下,定义接口和实现类,如interface EmpDao class EmpDaoImpl implements EmpDao. 在实现类中,用SqlSession对象调用select insert delete update 等方法实现。
目前极为少见,在传统模式下,我们需要知道SqlSession对象 实现CURD和 参数传递的处理
例如:SqlSession对象本身的API中就有三个查询方法,分别能够实现如下查询方式
1返回单个对象 selectOne
2返回对象List集合 selectList
3返回对象Map集合 selectMap
传统模式开发存在许多缺点:
1,不过是selectList(),selectOne(),selectMap(),都是通过SQLSession对象的API完成增删改查,都只能提供一个查询参数。如果要多个参数,需要封装到JavaBean或Map中,并不一定是一个好办法。
2,返回值类固定。
3,只提供了映射文件,没有提供数据库操作的接口,不利于后期的维护发展。
主题:
MyBatis中提供了一种成为Mapper代理的(或称接口绑定)的操作方式,在实际开发中也使用了该方法。
优点:
1有接口 模块之间有规范了
2参数的处理多样了,接口中的方法参数列表由我们自己决定
3通过代理模式由mybatis提供接口的实现类对象 我们不用写实现类了
当然代理模式下可以进行各种开发,例如多种参数的传递,模糊查询,主键自增,实现DML操作等等,这里就不再一一赘述。
看下面图
我们可以看到,getMapper正是基于接口的代理模式来做的一个开发,getMapper(EmpMapper.class)传入的是一个接口的字节码,在mybatis代理模式项目中没有写接口的实现类,但它一定会有一个接口的实现类,并由实现生成一个对象,再由这个对象去调用具体方法。
实际上,这个实现类是由Mybatis生成的,在生成的过程中,会做一个代理的处理,然后增强里面的一些方法。
如图所示,我们会有一个interface EmpMapper接口,其中定义了一个findAll(),这个接口并没有实现,同时准备了一个EmpMapper.xml的文件,这个文件写了一个<select>的标签。
当我们在getMapper(EmpMapper.class)传入了一个字节码时,通过一系列的处理手段,给我们生成了一个EmpMapper的实现类对象,但它不是一个真实的实现类,它是用底层的一个动态模式临时生成的,会对接口方法进行重写,如图在里面return了一个NULL。这个实现类方法相当于做了一个平庸的实现。
当然知道了这步,还压根不好使。在然后它通过代理对象进行一个增强,生成一个EmpMapper(Proxy)对象,称为代理对象。可以这样理解:Empmapper(Proxy)相当于律师,Empmapper(Impl)相当于被告,没有律师,被告啥都干了。
在这个代理模式中,会对这个findAll方法进行一个增强,那它是怎么进行增强的呢?它是读取EmpMapper映射文件里针对于这个方法的一些信息,读取参数类型,通过反射也可以读取方法本身的返回值类下和参数列表,知道是select,还是insert,还是update啊等等,去判断有什么实现方法,在里面定义一个具体的实现过程,本质上还是要调用sqlSession方法,然后把返回对象返回给程序。