mybatis会为每个mapper接口生成动态代理。每个动态代理对象都会持有sqlSession的引用。那么mybatis如何将自己生成的代理对象交给spring管理呢?
spring和mybatis整合的时候,主要有两点:
1.@MapperScan
@MapperScan 我们看到使用@Import注解,该注解直接往spring容器注入ImportBeanDefinitionRegistear的实现类MapperScannerRegistrar.class。执行了里面的registerBeanDefinitions的方法,将扫描指定包下面的全部接口(mybatis已经为这些接口生成代理对象了),动态将这些的接口的代理实现类放入MapperFactoryBean这个类中。
其中MapperFactoryBean是实现了FactoryBean接口。getObejct里面调用getSqlSession().getMapper(this.mapperInterface)生成mapper对象。那么所有接口都变成了MapperFactoryBean对象后,又是如何区分的呢? definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName())(getBeanClassName()返回的是String,但是为什么MapperFactoryBean构造函数类型是Class,原因是spring不允许给构造方法传入class对象,只能传入该类的全路径名)
在生成MapperFactoryBean对象的时候,立即在一参构造中设置了一个值,这样就有名称了。
2.@Bean ——>SqlSessionFactoryBean
可以看到SqlSessionFactoryBean有实现了InitializingBean和FactoryBean(两个接口,就这两个懂先讲)重写了InitializingBean的afterPropertiesSet的方法,此方法将配置文件中的各种属性列如 mapperlocation 、typealias、plugins等等放入configuration中。并生成sqlSessionFactory对象。重写了FactoryBean的getObject方法调用了afterPropertiesSet方法生成sqlSessionFactory对象(这边是将解析配置的sqlSessionFactory放入spring中)。
通常我们配置spring的xml中SqlSessionFactoryBean,其中可以指定dataSource、configLocation、mapperLocations等。dataSource是数据原配置,configLocation是xml全局配置文件,mapperLocations是指定mapper.xml的位置。