文章目录
1 mapper接口
1.1 引出问题
经常用Spring和MyBatis也挺久的了,但是一直比较好奇mapper接口是怎么加载到spring容器中的,因为要想注入spring容器中,都必须有实例的,这就不得不提一下Spring和MyBatis的中间件MyBatis-Spring
1.2 MyBatis-Spring
1.2.1 MyBatis-Spring基础
当在使用MyBatis时,一般是编写一个Mapper接口和一个Mapper.xml文件,我们都知道接口是不能直接被实例化的,然而我们一般在service层中编写的注入属性都是Mapper接口,那么Spring是如何对该接口进行实例化的呢
一般而言,如果使用Spring和MyBatis作为开发框架时,在搭建开发环境的时候,都会做一个Spring与MyBatis的整合,使用到的就是MyBatis-Spring这个中间件,MyBatis-Spring中间件把mapper接口和mapper.xml文件对应的代理类注册到Spring中,因此,在service层中就能根据类型注入,将对应mapper接口的代理类注入到service层中,这样才能够调用到对应的方法
1.2.2 MyBatis-Spring原理
1.2.3 讲解
在Spring开发中,通常是在service层中通过依赖注入Dao层的实例,在MyBatis中,Mapper接口即对应着Dao实例,MyBatis-Spring中间件就是把MyBatis中的mapper.xml和mapper.java对应的Mapper接口注册到Spring容器中,使得service层可以直接通过以来注入获取到Mapper接口
1.2.3.1 注册
在Spring中所有的Mapper接口都会被注册为MapperFactoryBean,所有的MapperFactoryBean会共享一个SqlSessionFactory,该SqlSessionFactory由SqlSessionFactoryBean创建
在sqlSessionFactory的configuration属性中存的是一个Configuration对象,configuratiaon对象中的mapperRegistry属性中存储了一个MapperRegistry对象,MapperRegistry对象中的knownMappers属性是一个key为mapper.java文件对应接口的类型,value为MapperProxyFactory的对象。
1.2.3.2 获取
当从Spring中获取Mapper接口时,将会调用对应的MapperFactoryBean的getObjects方法,该方法返回值即为对应的MapperProxyFactory创建的MapperProxy动态代理
1.2.4 整体流程图
1.3 总结
1.3.1 定位
注解方式 根据MapperScan里的内容找到basePackages
1.3.2 加载
MapperScannerRegistrar里registerBeanDefinitions方法通过ClassPathMapperScanner的doScan方法进行扫描basePackagesClassPathMapperScanner继承spring中ClassPathBeanDefinitionScanner,通过调用ClassPathBeanDefinitionScanner中doScan获得BeanDefinitionHolder,获取BeanDefinitionHolder之后通过processBeanDefinitions方法来把BeanDefinition对应的beanClass修改为MapperFactoryBean的beanclass
1.3.3 注入
在注入mapper形成的bean中会根据MapperFactoryBean中的getObject获取对应的bean变量MapperFactoryBean.getObject会调用SqlSessionTemplate的getMapper方法获取mapper对象SqlSessionTemplate调用Configuration.getMapper获取对象Configuration调用MapperRegistry.getMapper方法MapperRegistry根据mapperProxyFactory来生成对mappper的代理对象,该代理对象内部拥有mapperInterface以及SqlSessionTemplate对象