目的:
1.ORM框架的发展历史与MyBatis的高级应用
2.MyBatis的体系结构与核心工作原理分析
3.MyBatis基础模块讲解与强化核心原理
4.探寻插件的原理与深究和Spring的集成
5.通过手写MyBatis带你掌握自己写框架的秘诀
1.ORM框架的发展历史与MyBatis的高级应用
作业:写一个typehandler list保存到verchar
2.MyBatis的体系结构与核心工作原理分析
1.掌握MyBatis源码环境搭建
2.掌握MyBatis的体系结构
3.掌握MyBatis核心工具类
4.掌握MyBatis的核心流程
作业:
用自己的语言描述下MyBatis工作的核心流程,包括
SqlSessionFactory,SqlSession,getMapper但不局限这些核心
对象方法的作用
3.MyBatis基础模块讲解与强化核心原理
自己布置作业:查看resulthandler的里面的延迟加载是怎么代理的,怎么实现的?
JavassistProxyFactory 其实用了代理的模式
别名 和别名处理,日志与jdbc,为什么代理的invoke里面还要再返回一个代理对象呢 还有binding模块
4.探寻插件的原理与深究和Spring的集成
作业: 自己实现一个第三方缓存,把数据缓存到mongdb上面,写一个插件 ------------ 已完成
作业:自己描述一下spring整合mybatis的过程
首先
SqlSessionFactoryBean 实现了InitializingBean接口,实力化的时候调用afterPropertiesSet,从而初始化sqlSessionFactory 其次定义MapperScannerConfigurer 实现了BeanDefinitionRegistryPostProcessor接口,会在实例化 前调用
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
scanner.setAddToConfig(this.addToConfig);
scanner.setAnnotationClass(this.annotationClass);
scanner.setMarkerInterface(this.markerInterface);
scanner.setSqlSessionFactory(this.sqlSessionFactory);
scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
scanner.setResourceLoader(this.applicationContext);
scanner.setBeanNameGenerator(this.nameGenerator);
scanner.setMapperFactoryBeanClass(this.mapperFactoryBeanClass);
if (StringUtils.hasText(this.lazyInitialization)) {
scanner.setLazyInitialization(Boolean.valueOf(this.lazyInitialization));
}
scanner.registerFilters();
//会在这里扫描,
scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ",; \t\n"));
->进入ClassPathMapperScanner的scan->doScan方法
public int scan(String... basePackages) {
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
this.doScan(basePackages);
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
return this.registry.getBeanDefinitionCount() - beanCountAtScanStart;
}
public Set<BeanDefinitionHolder> doScan(String... basePackages) {
//封装了beandefinition了
Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
if (beanDefinitions.isEmpty()) {
LOGGER.warn(() -> {
return "No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.";
});
} else {
//处理beanDefinitions
this.processBeanDefinitions(beanDefinitions);
}
return beanDefinitions;
}
->
private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
GenericBeanDefinition definition;
for(Iterator var3 = beanDefinitions.iterator(); var3.hasNext(); definition.setLazyInit(this.lazyInitialization)) {
BeanDefinitionHolder holder = (BeanDefinitionHolder)var3.next();
definition = (GenericBeanDefinition)holder.getBeanDefinition();
String beanClassName = definition.getBeanClassName();
LOGGER.debug(() -> {
return "Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + beanClassName + "' mapperInterface";
});
definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName);
//设置了 private Class<? extends MapperFactoryBean> mapperFactoryBeanClass = MapperFactoryBean.class;,我们看看 MapperFactoryBean
definition.setBeanClass(this.mapperFactoryBeanClass);
definition.getPropertyValues().add("addToConfig", this.addToConfig);
。。。
}
->进入MapperFactoryBean的getObject
方法
public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {
private Class<T> mapperInterface;
...
继承了SqlSessionDaoSupport
public T getObject() throws Exception {
return this.getSqlSession().getMapper(this.mapperInterface);
}
public abstract class SqlSessionDaoSupport extends DaoSupport {
//组合了形式拥有session
private SqlSessionTemplate sqlSessionTemplate;
public SqlSessionDaoSupport() {
}
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
if (this.sqlSessionTemplate == null || sqlSessionFactory != this.sqlSessionTemplate.getSqlSessionFactory()) {
this.sqlSessionTemplate = this.createSqlSessionTemplate(sqlSessionFactory);
}
}
protected SqlSessionTemplate createSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
public final SqlSessionFactory getSqlSessionFactory() {
return this.sqlSessionTemplate != null ? this.sqlSessionTemplate.getSqlSessionFactory() : null;
}
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSessionTemplate = sqlSessionTemplate;
}
public SqlSession getSqlSession() {
return this.sqlSessionTemplate;
}
public SqlSessionTemplate getSqlSessionTemplate() {
return this.sqlSessionTemplate;
}
protected void checkDaoConfig() {
Assert.notNull(this.sqlSessionTemplate, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required");
}
}
public class SqlSessionTemplate implements SqlSession, DisposableBean {
private final SqlSessionFactory sqlSessionFactory;
private final ExecutorType executorType;
private final SqlSession sqlSessionProxy;
private final PersistenceExceptionTranslator exceptionTranslator;
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType());
}
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType) {
this(sqlSessionFactory, executorType, new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true));
}
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {
Assert.notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
Assert.notNull(executorType, "Property 'executorType' is required");
this.sqlSessionFactory = sqlSessionFactory;
this.executorType = executorType;
this.exceptionTranslator = exceptionTranslator;
//
this.sqlSessionProxy = (SqlSession)Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(), new Class[]{SqlSession.class}, new SqlSessionInterceptor());
}
。。。
}
具体流程:
1、提供了SqlSession的替代品SqlSessionTemplate,里面有一个实现了实现了InvocationHandler的内
部SqlSessionInterceptor,本质是对SqlSession的代理。
2、提供了获取SqlSessionTemplate的抽象类SglSessionDaoSupport。
3、扫描Mapper接口,注册到容器中的是MapperFactoryBean,它继承了SqlSessionDaoSupport,可
以获得SqlSessionTemplate。
4、把Mapper注入使用的时候,调用的是getObject()方法,它实际上是调用了SqlSessionTemplate的
getMapper()方法,注入了一个JDK动态代理对象。
5、执行Mapper接口的任意方法,会走到触发管理类MapperProxy,进入SQL处理流程。
疑问: datasource和session的关系