Mybatis与Spring整合
和Spring整合目的是为了让Spring管理Mybatis的核心对象.
(一)启动时候需要做的事情
ü 注入SqlSessionFactoryBean 生成SqlSessionFactory对象到Spring容器里面
ü
Spring和Mybatis整合的时候需要将SqlSessionFactoryBean 放入到Spring容器里面,SqlSessionFactoryBean 实现了InitializingBean接口.在实例化SqlSessionFactoryBean的时候会先执行afterPropertiesSet方法,在afterPropertiesSet内部调用了org.mybatis.spring.SqlSessionFactoryBean#buildSqlSessionFactory,在buildSqlSessionFactory方法里面解析mybatis-config.xml和mapper.xml(XMLConfigBuild对象和XMLMapperBuild对象) ,生成Configuration对象等等,最终在这个方法内部调用sqlSessionFactoryBuilder的build方法生成SqlSessionFactory对象return给afterPropertiesSet方法
ü DefaultSqlSession不是线程安全问题,不能被Spring直接使用
需要注意的是DefaultSqlSession不是线程线程安全的,在Spring环境下不能直接使用的,所以在Spring环境下有一个专门用来替换DefaultSqlSession对象的类,这个类是SqlSessionTemplate.这个类是Spring管理的线程安全的类.
SqlSessionTemplate也是执行增删改查操作的类,内部是通过jdk代理模式创建DefaultSqlSession执行增删改查的操作
SqlSessionTemplate在获取DefaultSqlSession对象的时候先通过TransactionSynchronizationManager事务管理器的getResource方法,调用TransactionSynchronizationManager#doGetResource 从resources(ThreadLocal)容器获取.
(二)注册Mapper接口到Spring容器里面
ü 注入MapperScannerConfigurer对象
这个bean主要是用来扫描dao接口的
MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessor接口,这个接口的有一个抽象方法是postProcessBeanDefinitionRegistry.
我们在注册我们的Bean到BeanDefinition的时候我们可以去做一些事情,比如说去修改我们的BeanDefinition的定义我们就可以在postProcessBeanDefinitionRegistry里面进行操作
在MapperScannerConfigurer#postProcessBeanDefinitionRegistry生成ClassPathMapperScanner对象,进行一系列的属性初始化操作,最后调用了ClassPathBeanDefinitionScanner#scan
在scan方法内部调用到 ClassPathMapperScanner#doScan 在doScan方法调用到了processBeanDefinitions,在processBeanDefinition方法内部注入到Spring容器的是MapperFactoryBean对象,并不是Mapper接口本身.
MapperFactoryBean
MapperFactoryBean继承了SqlSessionDaoSupport是为了获取到SqlSessionTemplate对象,在这个对象里面有个getSqlSession方法.
(三)用@Autowired使用Mapper对象
在一个@Component类里面如果成员变量有@Autowired xxxMapper xxxmapper; 的话, 说明这个xxxmapper会被实例化.
创建xxxmapper会先创建MapperFactoryBean,因为MapperFactoryBean实现了FactoryBean的接口,调用getObject方法来返回我们这个Bean,
在MapperFactoryBean调用getObject方法的时候,会先获取.sqlSessionTemplate然后调用sqlSessionTemplate的getMapper方法从Configuration对象里面根据class类型返回对应的Mapper对象.注意这个Mapper对象还是一个代理对象..
(四)Mapper对象执行对应的查询语句
在用Mapper执行对应的sql语句的时候,因为Mapper是一个代理对象,所以是还会先执行invoke方法,去执行对应的sql语句…..这个流程和原生的Mybatis执行SQL语句一模一样了.