目的:

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的关系

posted on 2022-11-27 10:56  我是坏男孩  阅读(23)  评论(0编辑  收藏  举报