Spring整合MyBatis的原理剖析
整合包里提供了一个SqlSessionFactoryBean和一个扫描Mapper的配置对象,SqlSessionFactoryBean被实例化,就开始扫描Mapper并通过动态代理产生Mapper的实现类存储到Srping容器,有相关四个类
SqlSessionFactory:需要进行配置,用于提供SqlSessionFactoryBean
源码: SqlSessionFactory 实现了FactoryBean接口,也就有了getObject方法,最重要的作用就是产生SqlSessionFactory对象注入到spring容器
配置文件中实例化setDataSource
实现了InitializingBean接口
然后调用afterPropertiesSet方法
this.sqlSessionFactory = this.buildSqlSessionFactory()
buildSqlSessionFactory返回
sqlSessionFactoryBuilder.build(targetConfiguration)
targetConfiguration就是配置文件
然后调用SqlSessionFactory的getObject方法 返回sqlSessionFactory,于是当前spring容器中已经存在sqlSessionFactory的bean对象,谁用就去拿
谁用到了SqlSessionFactoryBean就去调用getObject,然后返回
MapperScannerConifigruer: 需要进行配置,用于扫描指定mapper注册BeanDefinition
代码继承体系
实现了BeanDefinitionRegistryPostProcessor接口,再存储到BeanDefinitionMap后,调用其工厂bean处理器,
BeanDefinitionMap的postProcessBeanDefinitionRegistry方法
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
这里的scanner.scan是ClassPathMapperScanner的父类的scan,其本身没有scan方法
scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ",; \t\n"));
调用ClassPathMapperScanner的父类的scan
scan方法里面再调用其儿子doscan方法,这里儿子没有重写父亲的scan方法,进入到scan的类型还行儿子的类型,调用的doScan还是儿子的doScan
儿子的doScan再调用父类的doScan
父类的doScan
这里的beanClass是UserMapper接口对象,如果是class类对象可以通过反射创建对象
这里把UserMapper等beanDefinition都注册到BeanDefinitionMap,然后返回给儿子的beanDefinitions
这里beanDefinitions已经有长度了,并且super.doScan扫描的是com.edu.mapper这个包
然后调用ClassPathMapperScanner的
processBeanDefinitions方法,这个方法在ClassPathMapperScanner
这个方法主要看setBeanClass,把原来的beanClass换成mapperFactoryBeanClass
mapperFactoryBeanClass调用object方法
MapperFactoryBean继承了FactoryBean
MapperFactoryBean调用object方法,返回的Mapper对象,不是spring干的,是mybatis底层干的
再往后~~~~~~~~~~~~~
setAutowireMode(2)自动注入,这里会发现beanClass改变,变成了MapperFactoryBean