面试-mybatis重要的类

一、mybatis流程

这里是Mybatis自己的流程,不包含spring

1、重要标签

mybatis-config.xml有3个重要标签transactionManager、mappers、dataSource标签

  1. dataSource存的是数据库的连接信息
  2. transactionManager存的是事务管理模式。事务回滚就是通过这个来选择事务类型的。
  3. mappers标签,主要是把配置DAO.xml关联进来,DAO.xml有个namespace标签表示这个DAO.xml所对应的DAO.java类型。

2、解析mybatis-config.xml配置文件

把mybatis-config.xml配置文件转成Java对象Configuration,DAO.xml的namespace和Mapper类绑定,在把这个Mapper类转成MapperProxyFactory对象,并存到Configuration的属性Map里面去。因为后面会通过getMapper(Type)来拿到这个MapperProxyFactory。下面看下MapperProxyFactory里面有啥

//MapperProxyFactory结构
public class MapperProxyFactory<T> {
	//接口类型,也就是Mapper对应的class类
	private final Class<T> mapperInterface;
	
	//通过sqlSession,得到Mapper的代理对象
	public T newInstance(SqlSession sqlSession) {
		//创建一个Mapperxy对象,这个方法实现了JDK动态代理中的InvocationHandler接口
		final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
		return newInstance(mapperProxy);
	}

	//产生Mapper对应的代理对象
	protected T newInstance(MapperProxy<T> mapperProxy) {
		//mapperInterface,说明Mapper接口被代理了,这样返回的对象就是Mapper接口的子类,
		//Mapper接口里面方法被调用时,会被mapperProxy里面的invoke()方法拦截。
		return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
	}
}

3、创建SqlSessionFactory

通过Configuration创建DefaultSqlSessionFactory对象(DefaultSqlSessionFactory是SqlSessionFactory实现类),DefaultSqlSessionFactory对象里面有个属性Configuration,所以DefaultSqlSessionFactory没什么就一个Configuration属性,其他的不是很重要。SqlSessionFactory内部会做一系列的事情。

1、创建JdbcTransactionFactory:通过Configuration得到标签transactionManager,把transactionManager转成TransactionFactory,TransactionFactory的实现类是JdbcTransactionFactory。

2、创建JdbcTransaction:从Configuration得到标签dataSource的属性存到JdbcTransactionFactory里面。在通过JdbcTransactionFactory创建JdbcTransaction对象,用到的条件就是标签dataSource里面的属性。

3、创建执行器CachingExecutor:通过上一步得到的JdbcTransaction对象,转成执行器,也就是CachingExecutor

4、创建SqlSession

通过Configuration + 执行器CachingExecutor来得到SqlSession,这里SqlSession的实现类用的是DefaultSqlSession。

5、通过MapperProxyFactory生成Mapper类的代理对象

通过DefaultSqlSession+Mapper.class得到该Mapper对应的MapperProxyFactory,内部是从Configuration里面的map来得到MapperProxyFactory,在通过MapperProxyFactory的newInstance方法来动态代理生成代理对象。也就是Mapper代理对象。MapperProxyFactory的newInstance方法里面会生成一个MapperProxy对象,这个很重要,Mappe接口方法执行拦截都是通过他来实现的。

6、生成MapperMethod类

拿到Mapper生成的代理类,执行目标方法,此时会被invoke方法拦截,invoke里面会生成MapperMethod对象

public class MapperMethod {
	//里面存的是Mapper.xml方法和sql类型,比如getById,select类型
	private final SqlCommand command;
	//这个是用来生成sql的参数
	private final MethodSignature method;
	。。。。。
}

二、Spring整合mybatis流程

1、SqlSessionFactoryBean->SqlSessionFactory(实现类:DefaultSqlSessionFactory)

@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
    SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
    sqlSessionFactoryBean.setDataSource(..);
    return sqlSessionFactoryBean.getObject();
}
//至此SqlSessionFactory就是这样产生了

2、Mapper->MapperFactoryBean->反射生成MapperFactoryBean实例->初始化属性->sqlSession(实现类:SqlSessionTemplate)

注意:初始化属性包含处理@AutoWrite注解、@Value注解,像setSqlSessionTemplate方法就带了@AutoWrite注解,就会创建上面说的sqlSession

SqlSession sqlSession = new SqlSessionTemplate(sqlSessionFactory);
//SqlSessionTemplate是Mybatis-spring jar包里面的

SqlSessionTemplate属性:

1、sqlSessionFactory = sqlSessionFactory;
2、executorType = executorType
3、SqlSession sqlSessionProxy //创建SqlSession代理对象,注意这里和上面都是sqlSession但是实现类不一样,上面的SqlSession的实现类是SqlSessionTemplate。这里的SqlSession对象是代理出来的

sqlSessionProxy = (SqlSession) newProxyInstance(
      SqlSessionFactory.class.getClassLoader(), 
      new Class[] { SqlSession.class }, 
      new SqlSessionInterceptor());
//SqlSessionInterceptor实现了了invoke方法
//当执行SqlSession的任何方法,都会走到回调方法invoke里面,这就是SqlSessionInterceptor的作用

代理对象1:被代理对象SqlSession,回调方法在SqlSessionInterceptor类里面

问题1、那么上面的SqlSession对象何时被使用?
问题2、为什么还需要SqlSessionTemplate?

重点
1、完善了MapperFactoryBean,填充好了属性,通过实例调用MapperFactoryBean.getObject()方法得到Mapper实例。
Spring把Mapper转成了MapperFactoryBean,通过MapperFactoryBean来生产Mapper的实例,就是通过getObject方法来得到Mapper的实例。下面看下getObject方法怎么做的

问题3、Mapper的真正实例是什么?

this.getSqlSession().getMapper(this.mapperInterface);
//getSqlSession就得到上面我们创建的SqlSessionTemplate对象

看下SqlSessionTemplate的getMapper方法

public <T> T getMapper(Class<T> type) {
    return this.getConfiguration().getMapper(type, this);
}
public Configuration getConfiguration() {
	return this.sqlSessionFactory.getConfiguration();//拿到Mybatis的Configuration
}

最终还是通过Mybatis的Configuration调用getMapper方法

注意有个细节:在调用getMapper方法的时候传参数,第二个参数是this也就是SqlSessionTemplate对象
在这里插入图片描述

看下getMapper方法是怎么执行的

在这里插入图片描述

追踪mapperRegistry的getMapper方法

在这里插入图片描述

看下newInstance方法执行流程

在这里插入图片描述

看下MapperProxy
在这里插入图片描述

上面通过创建MapperProxy对象,然后再将MapperProxy对象作为参数调用下面方法创建mapperInterface代理对象

return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);

也就是UserInfoMapper的代理对象返回,走了这么长的流程,就是为了得到Mapper的代理对象,原来是在这里产生的。

代理对象2:被代理对象 “自定义Mapper” ,回调方法在MapperProxy类里面

回到上面的问题3,Mapper真正的实例对象,是动态代理生成的对象,被代理对象就是我们自定义的Mapper

最后把Maper的实例存到Spring容器中下面看下,当我们执行查询的时候,流程是什么?

查询:因为Mapper的实例是代理对象,当我我们调用就会进到MapperProxy的invoke方法里面
在这里插入图片描述

进入execute

在这里插入图片描述

selectOne方法

在这里插入图片描述
当执行sqlSessionProxy的任何方法,都会进入到SqlSessionInterceptor的invoke里面去,看下invoke里面怎么做的

在这里插入图片描述
包括method.invoke执行的是selectOne里面的逻辑,这些都是mybatis自己实现的

整个流程涉及的2个代理对象
1、第一个是sqlSessionTemplate里面创建的一个SqlSessionProxy
2、第二个是Mapper的代理对象

第一个代理对象为了在执行sqlSession的selectOne的方法时,为了能走到SqlSessionInterceptor的invoke方法,然后在Invoke方法里面通过调用mybatis的sqlSession去执行selectOne
第二个代理对象是为注入Spring容器中,当我们service调用Mapper里面的方法的时候,能进到代理对象的invoke方法,而这个invoke方法里面会调用sqlSessionTemplate的逻辑方法,来触发进到第一个代理对象的Invoke方法

下面介绍关于Spring为什么要加sqlSessionTemplate,最主要的是实现事务
当我们在Service方法加了@Transactional注解的时候

这个时候sqlSessionTemplate的作用就提现出来了

在这里插入图片描述
关于上面的代码执行了分两步,第一个是目标方法,第二个是invoke方法

先进入代理类的invoke方法
在这里插入图片描述
在执行目标方法
在这里插入图片描述

当没哟开启事务时,Spring是默认不提交,如果未开启是会自动提交的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

信仰_273993243

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值