目的:
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的關系
浙公網安備 33010602011771號