一、整合步骤
mybatis-spring-1.3.2版本
- 使用@MapperScan注解,配置Mapper路径
- @MapperScan继承@Import注解。
- @Import引入MapperScannerRegistrar(是ImportBeanDefinitionRegistrar实现类)。(Spring会在解析配置类逻辑中,解析Import、MapperScan注解)
- 利用ImportBeanDefinitionRegistrar(Spring扩展机制)。完成Mapper接口的扫描(继承并重写Spring扫描器)、修改与注册Mapper的BeanDefinition。【2.0.6或更高版本中,MapperScannerRegistrar注册实现BeanDefinitionRegistryPostProcessor的MapperScannerConfigurer完成扫描、修改BeanDefinition的动作】
- Spring容器会调用ImportBeanDefinitionRegistrar#registerBeanDefinitions
- 获取MapperScan注解实例
- 实例化自定义的扫描器(ClassPathMapperScanner),并利用MapperScan注解实例,将配置参数【重点参数:Mapper包路径】设置到扫描器中
- 向自定义扫描器中,注册自定义扫描过滤器(总是返回true,即不进行过滤)。Spring默认过滤器,仅扫描被@Component注解标记的类
- 执行扫描方法(doScan),(扫描@MapperScan注解配置的路径下的Mapper接口),得到Mapper接口的BeanDefinitionHolder集合。
- 循环BeanDefinitionHolder集合,修改BeanDefinition实例属性。
- 设置ConstructorArgumentValues属性值:原始的BeanClass。即:xxMapper的Class对象。(构造函数入参)
- 修改BeanClass属性为:MapperFactoryBean的Class对象,
- 设置AutowireMode属性为:2(byType方式注入)。
- 经过上一步,所有Mapper接口的BeanDefinition,都变成FactoryBean类型的
- 利用FactoryBean将Mapper接口的代理对象,注册为Spring容器的实例对象。
- 每个mapper接口,都对应一个MapperFactory类型的Bean的BeanDefinition
- MapperFactoryBean的getObject方法,首先获得sqlSession对象,然后根据步骤2.f.i中构造函数传递的Class参数,获取对应Mapper 的代理对象。并将代理对象缓存到Spring容器中。
- 利用Spring的依赖注入功能。完成Mybatis代理对象的依赖注入
- 因为MapperFactoryBean的AutowireMode是byType,所以Spring会调用set方法(setSqlSessionFactory(SqlSessionFactory sqlSessionFactory)、setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate))
- SqlSessionFactory需要开发者自行实例化,提供给Spring,Spring才能顺利调用上面set方法
- SqlSessionFactory会被包装成SqlSessionTemplate(SqlSessionTemplate实现了SqlSession接口)