spring整合mybatis源码
2022-06-29 08:25:52 2 举报
spring整合mybatis源码流程图
作者其他创作
大纲/内容
没有
执行scan
resources这个ThreadLocal中有没有SqlSession
遍历扫描到的beandefinion
getObject()拿到UserMapper代理对象
SqlSessionFactoryBean注解@Bean方式注入 -> getObject() -> afterPropertySet() -> XMLConfigBuilder.parse()解析xml构建Configuration对象 (解析完每个mapper.xml后 -> addMapper(type) )注意: 这里如果sqlSessionFactoryBean没有setConfigLocation(mybatis.xml),那么是不会去解析配置文件的 -> 但是在初始化方法checkConfigDao中会执行configuration.addMapper(this.mapperInterface)方法创建代理对象塞进MapperRegistry并且会解析注解方式
执行方法
MapperFactoryBean extends DaoSupport还实现了InitializingBean接口,所以getBean的时候会执行checkDaoConfig方法,在这里configuration.addMapper(this.mapperInterface);
如果开启了spring事务,那么在执行sql时就能共用同一个SqlSession对象,mybatis以及缓存也就有用了,如果没有开启事务,那么在执行sql的时候每次都会新建一个sqlsession对象,一级缓存也就失效了
getSqlSession()拿到的是DefaultSqlSession对象
postProcessBeanDefinitionRegistry
addaddIncludeFilter(true)这样就不需要给UserMapper上使用@Component注解
基于数据库连接执行sql
base -> simple -> doqurey ->prepareStatement -> getConnection()
开启了事务就会bindResource把sqlSession存入resources这个ThreadLocal中
判断synchronizations是否为空, 也就是判断当前是否开启了事务
userMapper调用dao方法selectById
SqlSessionFactoryBean的初始化逻辑中会向Environment中添加一个SpringManagedTransactionFactory对象,拿连接前先newTranscation()方法得到一个SpringManagedTransaction,再调用它的getConnection()方法得到一个数据库连接,会利用DataSourceUtils来获取由事务管理器所创建号的数据库连接
registerSessionHolder
后续会用来判断当前是否开启了spring事务
创建SqlSessionTemplate并给MapperFactoryBean的sqlSessionTemplate属性赋值
这个子类重写了几个方法-doScan方法:-isCandidateComponent方法:扫描isInterface() && isIndependent()
这是一个BeanFactoryPostProcessor,spring启动过程中会去执行方法
实际就是导入一个ImportBeanDefinitionRegistrar@Import(MapperScannerRegistrar.class)或者在AppConfig中直接@Bean MapperScannerConfigurer并setBasePackage
registerBeanDefinitions注册一个MapperScannerConfigurer的beandifinition
MapperFactoryBean的setSqlSessionFactor方法注入bean
SqlSessionTemplate extends SqlSessiontemplate的sqlSessionProxy属性是一个jdk动态代理对象(很重要)
利用事务管理器创建一个数据库连接
开启事务(@Bean、@Enable..)
注册SessionFactory这个Bean
sqlSessionProxy.selectOne进入SqlSessionInterceptor拦截器中
SqlSessionFactory方式注册SessionFactory
创建ClassPathBeanDefinitionScanner扫描器的子类
执行方法DefalultSqlSession.selectOne()
进到MapperProxy拦截器中
有
非空
UserMapper中的方法子要不是default就会进入PlainMethodInvoker的invoke方法去执行,最后进入MethodMapper,最后是执行sqlsessiontemplate.selectOne() -> sqlSessionProxy.selectOne -> .. -> DefaultSqlSession.selectOne()
spring启动时MapperScannerRegistrar
开启了spring事务的话,同一事务下执行第二次sql时直接就能拿resources这个ThreadLocal中的SqlSession了
sqlsessiontemplate.selectOne()
MapperFactoryBean extends SqlSessionDaoSupport 父类有个setSqlSessionFactory,就能通过set方法注入SessionFactory,这个set方法是为了创建SqlSessionTemplate
直接返回该sqlSession
最终扫描到的beandifinition实际都是MapperFactoryBean
MapperScannerConfigurer
创建SpringManagedTransactionFactory
sessionFactory.openSession()创建一个sqlSession
拿到数据库连接
@MapperScan(basepakeages)
AppConfig
先到父类scan方法 -> 子类doscan() -> 修改扫描到的beandefiniton的beanclass及添加构造方法参数值及设置autowiremode为bytype(不需要@Autowired注解,直接set方法注入)
synchronizations.set(new LinkedHashSet<>());
DataSourceTransactionManager的doBegin()方法中会把对应的DataSource对象作为key,数据库连接对象作为value,存入resources这个ThreadLocal中
0 条评论
下一页