mybatis 无法初始化类_springboot 整合mybatis原理

84aa237cfacf443ba0fd48d3cd6e2d8b

现在企业级web开发最流行的框架组合是springboot+mybatis+mysql。springboot集成了spring强大齐全的组件化开发模式,并且几乎零配置。mybatis作为优秀的持久层框架,和hibernate一样利用ORM思想,但是mybatis使用更加灵活,学习成本更低。前几篇介绍了mybatis框架的原理,以及平时开发中常用的配置。上一篇主要讲mybatis和springboot整合的方式,这一篇介绍整合的原理。知其然,也要知其所以然,这样才能灵活变通,日积月累,你就是大牛!

前边有介绍mybatis的初始化过程及原理,总共份以下几步

public static void main(String[] args) throws Exception {String resource = "sqlMapConfig.xml";// 通过流将核心配置文件读取进来InputStream inputStream = Resources.getResourceAsStream(resource);// 通过核心配置文件创建会话工厂SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);// 通过会话工厂创建会话SqlSession session = factory.openSession();UserDao userDao = session.getMapper(UserDao.class);List list=userDao.findAllUser();System.out.println("-----------------");System.out.println("所有用户:");System.out.println("昵称"+""+"生日"+""+"性别"+""+"地址");for(User u:list){System.out.println(u.getUser_name()+""+u.getBirthday()+""+u.getSex()+" "+u.getAddress());}}

1、根据初始化配置文件创建Configuration对象

2、根据Configuration对象新建SqlSession的工厂类SqlSessionFactory对象

3、用SqlSessionFactory对象创建SqlSession对象

4、用SqlSession对象创建mapper接口类,这里运用了java的动态代理

5、调用接口方法查询数据库返回数据

但是从上一篇文章我们发现,程序里只是调用一个方法

List list=userDao.findAllUser();

就把数据取出来了,前边那些获取sqlSession等操作都省略了,大概这些都是springboot在初始化的时候已经帮我们做了。具体怎么整合的呢?

从上一篇文章介绍springboot和mybais整合的方式上我们发现关于整合的我们只做了两个步:一个是pom里增加了依赖

org.mybatis.spring.boot mybatis-spring-boot-starter 2.0.1

另一个是在springboot的运行类Application中增加了一个MapperScan注解

@MapperScan("com.ding.demo.model")

下面我们就从这两步来入手:

12380dd0d8244d8c894d8af2ec4385f1

找到依赖的mybatis-spring-boot-starter包,打开jar包之后,发现没有个java文件是一个,那这项目肯定是依赖了其他包,打开POM文件,可以看到,主要就是引入mybatis-spring-boot-autoconfigure,我们来看下这个jar包的结构

0b820dbe96f048879843e464241d0220

发现这个jar包里有三个类,和一些配置文件。打开熟悉的spring.factories

# Auto Configureorg.springframework.boot.autoconfigure.EnableAutoConfiguration=org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

说明springboot在启动的时候MybatisAutoConfiguration会被注入到容器中。

package org.mybatis.spring.boot.autoconfigure;import java.util.Iterator;@Configuration@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})@ConditionalOnSingleCandidate(DataSource.class)@EnableConfigurationProperties({MybatisProperties.class})@AutoConfigureAfter({DataSourceAutoConfiguration.class})public class MybatisAutoConfiguration implements InitializingBean {  @Bean @ConditionalOnMissingBean public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); factory.setDataSource(dataSource); factory.setVfs(SpringBootVFS.class); if (StringUtils.hasText(this.properties.getConfigLocation())) { factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation())); } this.applyConfiguration(factory); if (this.properties.getConfigurationProperties() != null) { factory.setConfigurationProperties(this.properties.getConfigurationProperties()); } if (!ObjectUtils.isEmpty(this.interceptors)) { factory.setPlugins(this.interceptors); } if (this.databaseIdProvider != null) { factory.setDatabaseIdProvider(this.databaseIdProvider); } if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) { factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage()); } if (this.properties.getTypeAliasesSuperType() != null) { factory.setTypeAliasesSuperType(this.properties.getTypeAliasesSuperType()); } if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) { factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage()); } if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) { factory.setMapperLocations(this.properties.resolveMapperLocations()); } return factory.getObject(); } ......}

发现我们熟悉的SqlSessionFactory工厂类出现了,还是有@bean注解,说明SqlSessionFactory在这里被注入到springboot的。我们注意到这里需要一个DataSource ,这说明在此之前,数据源已经被注入到项目中。那是在哪注入的呢?

经过一番查找,发现是在这,事实也是如此。

3efcfb930ece4e9aa76c1cf9db59a284

注:springboot自动配置的类一般在org.springframework.boot.autoconfigure包里,大部分的配置都可以找到。

现在数据源找到了,SqlSessionFactory工厂类也找到了,下一步就是根据SqlSessionFactory创建SqlSession 并且获取mapper接口了。

我们从@MapperScan找突破口。

2bc03b8ec9ad42b8bed5d2e98e1b5e09
214f27116c954459b52ef5452728f25d

进入MapperScannerRegistrar 发现这个类就是注册bean的。将MapperScan注解传递的包下得所有的类注册成MapperFactoryBean对象,MapperFactoryBean里有这个方法。

public T getObject() throws Exception { return this.getSqlSession().getMapper(this.mapperInterface);}

在真正使用到的时候通过这个方法创建对应接口的实例,而通过对Spring-Mybatis的分析可知,MapperFactoryBean真正返回的是接口的代理类MapperProxy,通过代理类实现对数据库的操作。

所以在用springboot的时候我们仅仅是写一个 类似userDao.findAllUser();就可以实现对数据库的操作,大量的工作比如读配置文件形成configration对象 管理SqlSessionFactory等都被springboot初始化的时候被定义好了,最后用一个动态代理,让代理对象去真正干活。是不是很高明?

如果有不实之处,欢迎不吝指正。有需要测试源码的私信我,免费给。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值