一、mybatis使用动态代理要实现的功能。
mybatis 的底层实际上运行的还是ibatis,即需要把接口和xml映射翻译成 ibatis 需要的这种格式。
二、mapper接口的动态代理
- 当使用 sqlSession.getMapper 获取一个Mapper 的时候一般是使用
sqlSession
的DefaultSqlSession
这个实现类去调用的。 - 先去调用 configuration.getMapper。然后会从
mapperRegistry
的knownMappers
中拿到接口对应的MapperProxyFactory
- MapperProxyFactory会创建出来mapper接口的代理实现类(严格的讲,这生成的只是一个接口的代理,算不上一个真正的实现),并把他交给 MapperProxy 管理。
- 然后把代理的实现类返回。
三、mapper接口调用方法
- 上文讲到通过sqlsession拿到的是一个经过动态代理的mapper。所以在mapper调用方法的时候,会进入代理对象
MapperProxy
的invoke方法。 - 在
MapperProxy.invoke
,方法中会创建一个MapperMethod
对象。这个对象封装了Mapper接口中对应方 法的信息,以及对应的sql语句的信息。 - 接下来就会调用
MapperMethod
的 execute方法。在这里就会真正执行ibatis的部分。
四、问题:mybatis 的mapper接口没有实现类,那么他是如何工作的
- 有些文章中说,mybatis是通过动态代理的方式,生成了mapper接口的实现类,其实这种表达是很不准确的。动态代理并没有替mapper接口生成实现类,而是利用动态代理的方式使接口每次执行方法的时候,都会经过代理类的invoke 方法来做一些操作。
- mybatis 的运行,最终都会进入到ibatis 的运行方式来,看ibatis 的运行方式,是并没有mapper接口参与的。所以mybatis 的mapper接口类更像是一个工具人。
- mapper接口工具人论述。
- 接口被动态的代理了,所以他执行的所有方法都会进入到代理类的invoke方法中。所以使用接口调用方法的目的,只是为了执行代理类的invoke方法而已,
工具人
mapper 接口只是为代理类跑腿而已 - mapper接口的每个方法会定义 入参类型、出参类型,在调用接口方法时候还会往里面传入具体参数。所以mapper接口只是为了让ibatis调用selectOne、selectList等方法时运送 这些关键信息的而已。
- 接口被动态的代理了,所以他执行的所有方法都会进入到代理类的invoke方法中。所以使用接口调用方法的目的,只是为了执行代理类的invoke方法而已,