mybatis源码分析
说明:以下分析基于spring-framework-5.0.x,mybatis-spring-1.3.2,mybatis-3.4.6相关源码可自行去github下载或者maven依赖然后利用类似ideal工具自动关联源码功能。
我们知道spring对bean的管理,我们可以通过多种方式将bean添加进spring中进行管理其中包括:
- 一般注解@Conponent、@Controller、@Service
- @Import形式有三种:第一种用法:@Import({ 要导入的容器中的组件 } ):容器会自动注册这个组件,id默认是全类,第二种用法:ImportSelector:返回需要导入的组件的全类名数组,springboot底层用的特别多第三种用法:ImportBeanDefinitionRegistrar(如Mybatis和springboot整合时):手动注册bean到容器。
- 当然也可以通过BeanDefinitionRegistryPostProcessor(BeanFactoryPostProcessor子类)进行bean注册。通过它的重写方法参数可以拿到register进而进行bean的注册或者
- 使用beanRegister或者bean工厂
一:bean交由spring管理
mybatis通过@MapperScan标签完成对接口mapper的注入,我们依次点击@MapperScan->@Import(MapperScannerRegistrar.class)->MapperScannerRegistrar implements ImportBeanDefinitionRegistrar通过重写registerBeanDefinitions这个方法完成bean的注入。部分相关代码如下:
@Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { ...for (String pkg : annoAttrs.getStringArray("basePackages")) { if (StringUtils.hasText(pkg)) { basePackages.add(pkg); ...scanner.doScan(StringUtils.toStringArray(basePackages)); } @Override public Set<BeanDefinitionHolder> doScan(String... basePackages) { Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages); if (beanDefinitions.isEmpty()) { logger.warn("No MyBatis mapper was found in ‘" + Arrays.toString(basePackages) + "‘ package. Please check your configuration."); } else { processBeanDefinitions(beanDefinitions); } return beanDefinitions; } private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) { for (BeanDefinitionHolder holder : beanDefinitions) { definition = (GenericBeanDefinition) holder.getBeanDefinition(); ... // the mapper interface is the original class of the bean but, the actual class of the bean is MapperFactoryBean definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName()); definition.setBeanClass(this.mapperFactoryBean.getClass()); }
二:MapperFactoryBean:MapperFactoryBean->SqlSessionDaoSupport->DaoSupport->InitializingBean(在bean实例化前执行checkDaoConfig方法)
public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> { public MapperFactoryBean(Class<T> mapperInterface) { this.mapperInterface = mapperInterface; }//把接口类型传入factoryBean便于代理对象的产生 @Override protected void checkDaoConfig() { ... configuration.addMapper(this.mapperInterface)->mapperRegistry.addMapper(type)->parser.parse()(完成一些注解解析及sql生成等) ... } } @Override public T getObject() throws Exception { //getSqlSession()->SqlSessionTemplate 在MapperFactoryBean实例化过程中,会首先根据mybatis-spring-boot-autoconfigure中META-INF/spring.factories中的内容获取到MybatisAutoConfiguration这个配置类类名。在后续的bean创建过 程中,MybatisAutoConfiguration类的对象会被创建成一个继承了FactoryBean的代理对象放到bean工厂中 MybatisAutoConfiguration中SqlSessionTemplate sqlSessionFactory两个类的的生成是@Bean注解来生成 return getSqlSession().getMapper(this.mapperInterface);->>> public T newInstance(SqlSession sqlSession) { final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache); return newInstance(mapperProxy); } } } public class MapperProxy<T> implements InvocationHandler, Serializable { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { ... return method.invoke(this, args); ... return mapperMethod.execute(sqlSession, args); } } public Object execute(SqlSession sqlSession, Object[] args) { Object result; switch (command.getType()) { case INSERT: { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.insert(command.getName(), param)); break; } ... case SELECT: if (method.returnsVoid() && method.hasResultHandler()) { executeWithResultHandler(sqlSession, args); result = null; } else if (method.returnsMany()) { result = executeForMany(sqlSession, args); ... } private <E> Object executeForMany(SqlSession sqlSession, Object[] args) { ... result = sqlSession.<E>selectList(command.getName(), param); ... } //sqlSession为SqlSessionTemplate @Override public <E> List<E> selectList(String statement, Object parameter) { return this.sqlSessionProxy.<E> selectList(statement, parameter);//执行invoke方法 } private class SqlSessionInterceptor implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { SqlSession sqlSession = getSqlSession( ... } finally { if (sqlSession != null) { closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);//mybatis结合spring时一级缓存失效原因 } } } }
相关推荐
Dullonjiang 2020-07-05
xiuyangsong 2020-11-16
Nishinoshou 2020-11-09
jimgreatly 2020-09-01
dongxurr 2020-08-18
Dullonjiang 2020-08-15
Dullonjiang 2020-08-11
Dullonjiang 2020-08-09
dongxurr 2020-08-08
yunzhonmghe 2020-08-07
jimgreatly 2020-08-03
Dullonjiang 2020-07-30
jimgreatly 2020-07-27
liqiancao 2020-07-26
xiuyangsong 2020-07-26
dongxurr 2020-07-26
mcvsyy 2020-07-26
helloxusir 2020-07-25