工厂模式(四)泛型工厂之 MyBatis Mapper 代理
在MyBatis框架中,为了能操作数据库,执行sql语句,需要定义Mapper接口文件和对应的xml文件,比如UserMapper.java和UserMapper.xml。然后就可以在Service层直接注入UserMapper实例。其实UserMapper对象是代理对象。代理对象要实现的功能就是执行xml文件中定义的sql语句。
其实这里也涉及到动态代理模式
如果我们要自己创建的话大概是这样的:
通过SqlSession.getMapper()
方法获取到的就是UserMapper接口的一个代理对象,这里便用到了动态代理,内部实现大概是这样的(仍然使用了最无意义的代码):
以上就是动态代理的基本使用方法,其实这个例子少了一个要代理的真实对象,但是此处不需要真实对象,因为我们代理的是Mapper接口,在MyBatis中是不需要定义具体的Mapper接口实现的。
SqlSession.getMapper()
内部实现就犹如在示例代码main()
方法所展示的那样:创建代理对象。只不过在MyBatis中并不会直接创建代理对象,而是通过工厂去创建,这个工厂便是我要讲的 泛型工厂
该工厂直接作为类来使用,不像前面讲的那样:一个工厂接口和多个工厂实现类。因为这个地方只需一个工厂类就可以搞定。该类可以接收任何不同类型的对象,因为使用了类型参数。
这个泛型工厂创建的对象就是我们Mapper接口的动态代理对象,因为有了类型参数,所以它可以创建任意类型的对象。
具体的代理是 MapperProxy
。 所有Mapper接口的代理对象都是该类的实例。调用任何的Mapper接口中定义的方法都会被代理到MapperProxy
类的invoke()
方法,然后在invoke()
中执行具体的SQL语句。
同时MyBatis提供了工厂注册中心(具体类:MapperRegistry),MyBatis在初始化过程中会读取映射配置文件以及Mapper接口中的注解信息,然后去填充注册工厂,该注册工厂维护了一个映射关系表:
就是把工厂和Class的信息填充到此Map中,这样我们在使用时就可以通过注册中心的getMapper()方法去获取具体类型的代理对象:
刚开始提到的sqlSession.getMapper(UserMapper.class)
内部调用的就是这里的getMapper
方法。
工厂注册中心免得我们手动去创建维护此关系表。
以上是泛型工厂和工厂注册中心搭配使用的例子
版权声明: 本文为 InfoQ 作者【LSJ】的原创文章。
原文链接:【http://xie.infoq.cn/article/fcfd07d6e91e51d924a5ea432】。文章转载请联系作者。
评论