先看一下spring整合mybatis需要的配置Bean
@Configuration
@MapperScan(basePackages = {
"com.bijian.mapper"})
@ComponentScan(basePackages = {
"com.bijian"})
@Repository
public class MyBatisConfig {
// =====> spring.xml
/**
* <bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource"> </bean>
*
* <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
* datasource
* mapper文件的路径
* 别名
*
* </bean>
*
* <mapper-scan basePackage=""/>
* SqlSessionFactoryBean 创建的过程会初始化 sqlsession 数据源 事务 mapperProxyFactory
* @return
* @throws IOException
*/
@Bean // ===== > <bean class="org.mybatis.spring.SqlSessionFactoryBean">
public SqlSessionFactoryBean sqlSessionFactory( ) throws IOException {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource());
// 设置 MyBatis 配置文件路径
//factoryBean.setConfigLocation(new ClassPathResource("mybatis/mybatis-config.xml"));
// 设置 SQL 映射文件路径
//factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/*.xml"));
factoryBean.setTypeAliases(User.class);
return factoryBean;
}
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUsername("root");
dataSource.setPassword("123456");
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mydb1");
return dataSource;
}
}
大体介绍:
原理概述:
- 如何生成sqlSessionFactory对象不细说:就是以吧SqlSessionFactoryBean注入到容器中,它实现了FactoryBean,所以通过getObject方法来解析配置,生成包含所有mybatis所有信息的Configration对象,再构建一个完整的SqlSessionFactory对象;
- 如何通过mapper接口生成代理类注入容器中:扫描指定的mapper接口包,为每个接口生成一个BeanDefinition对象,再遍历这些BeanDefinition对象,修改其内容,把其class都设置成MapperFactoryBean,为其注入SqlSessionTamplate对象,因为其实现了BeanFactory对象,会调用其getObject方法返回mybatis生成的代理对象,这个代理对象的生成是mybatis自己做的,也就是为每个接口生成一个JDK动态代理,其动态代理对象中又有SqlSession对象,这样就可以执行了,就不细说了
我们先来解析SqlSessionFactoryBean对象所作的事,其实现了 FactoryBean,所以主要看起getObject方法所做的事,就是构建一个mybatis的SqlSessionFactory对象;
public SqlSessionFactory getObject() throws Exception {
if (this.sqlSessionFactory == null) {
afterPropertiesSet();
}
/**
* 返回我们的sqlSessionFactory对象
*/
return this.sqlSessionFactory;
}
public void afterPropertiesSet() throws Exception {
notNull(dataSource, "Property 'dataSource' is required");
notNull(sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");
state((configuration == null && configLocation == null) || !(configuration != null && configLocation != null),
"Property 'configuration' and 'configLocation' can not specified with together");
/**
* 通过sqlSessionFactoryBuilder来构建我们的sqlSessionFactory
*/
this.sqlSessionFactory = buildSqlSessionFactory();
}
构建我们的sqlSessionFactory的实例
protected SqlSessionFactory buildSqlSessionFactory() throws Exception {
// 声明一个Configuration对象用于保存mybatis的所有的配置信息
final Configuration targetConfiguration;
XMLConfigBuilder xmlConfigBuilder = null;
// 初始化 configuration 对象,和设置其 `configuration.variables` 属性
/**
* 判断当前的SqlSessionFactoryBean是否在配置@Bean的时候 factoryBean.setConfiguration();
*
*/
if (this.configuration != null) {
/**
* 把配置的SqlSessionFactoryBean配置的configuration 赋值给targetConfiguration
*/
targetConfiguration = this.configuration;
if (targetConfiguration.getVariables() == null) {
targetConfiguration.setVariables(this.configurationProperties);
} else if (this.configurationProperties != null) {
targetConfiguration.getVariables().putAll(this.configurationProperties);
}
}
/**
* 对configLocation进行非空判断,由于我们配置了SqlSessionFactoryBean的configLocation属性设置
*
* @Bean public SqlSessionFactoryBean sqlSessionFactory( ) throws IOException { SqlSessionFactoryBean factoryBean
* =new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSource()); factoryBean.setConfigLocation(new
* ClassPathResource("mybatis/mybatis-config.xml")); factoryBean.setMapperLocations(new
* PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/*.xml")); return factoryBean;
* }
*/
else if (this.configLocation != null) {
/**
* 创建我们xml配置构建器对象,对mybatis/mybatis-config.xml配置文件进行解析 在这里以及把我们的mybaits-config.xml解析出要给document对象
*/
xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);
/**
* 因为我们在创建XMLConfigBuilder的时候已经把我们的Configuration对象创建出来了
*/
targetConfiguration = xmlConfigBuilder.getConfiguration();
} else {
LOGGER.debug(
() -> "Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration");
targetConfiguration = new Configuration();
/**
* 判断configurationProperties不为空,那么就调用targetConfiguration.set方法 把configurationProperties注入到Configuration对象中
*/
Optional.ofNullable(this.configurationProperties).ifPresent(targetConfiguration::setVariables);
}
/**
* objectFactory不为空,那么就调用targetConfiguration.set方法 把objectFactory注入到Configuration对象中
*/
Optional.ofNullable(this.objectFactory).ifPresent(targetConfiguration::setObjectFactory);
/**
* objectWrapperFactory不为空,那么就调用targetConfiguration.set方法把 ObjectWrapperFactory注入到Configuration对象中
*/
Optional.ofNullable(this.objectWrapperFactory).ifPresent(targetConfiguration::setObjectWrapperFactory);
/**
* vfs不为空,那么就调用targetConfiguration.set方法把 vfs注入到Configuration对象中
*/
Optional.ofNullable(this.vfs)<