mapper接口怎么注入spring容器
文章目录
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
方法进行扫描basePackages
ClassPathMapperScanner
继承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
对象