Springboot Mybatis 打包jar扫描bean与mapper问题研究与解决
SpringBootLean 是对springboot学习与研究项目,是根据实际项目的形式对进行配置与处理,欢迎star与fork。
[oschina 地址]
http://git.oschina.net/cmlbeliever/SpringBootLearning
[github 地址]
https://github.com/cmlbeliever/SpringBootLearning
最近在项目中集成以全注解的方式Mybatis,配置了自动bean包与mapper所在包
db.mybatis.mapperLocations=classpath*:com/cml/springboot/sample/db/resource/*
db.mybatis.typeAliasesPackage=com.cml.springboot.sample.bean
db.mybatis.typeHandlerPackage=com.cml.springboot.framework.mybatis.typehandler
这些配置直接在ide上运行都是ok的,但是经过打包成jar包后,就一直报错提示找打不到对应的bean或者对应的mapper。主要错误如下:
Error resolving class. Cause: org.apache.ibatis.type.TypeException: Could not resolve type alias 'logbean'. Cause: java.lang.ClassNotFoundException: Cannot find class: logbean
***************************
APPLICATION FAILED TO START
***************************
Description:
Field logMapper in com.cml.springboot.sample.service.impl.LogServiceImpl required a bean of type 'com.cml.springboot.sample.db.LogMapper' that could not be found.
Action:
Consider defining a bean of type 'com.cml.springboot.sample.db.LogMapper' in your configuration.
针对以上问题,在新开的分支deploy_jar_bugfind上进行研究,找到了一个临时解决办法,就是配置mybat-configuration.xml将对应的bean都配置到xml上。
<configuration>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true" />
</settings>
<typeAliases>
<typeAlias type="com.cml.springboot.sample.bean.LogBean" alias="logbean"/>
<typeAlias type="com.cml.springboot.sample.bean.User" alias="user"/>
</typeAliases>
<typeHandlers>
<typeHandler javaType="org.joda.time.DateTime"
handler="com.cml.springboot.framework.mybatis.typehandler.JodaDateTimeTypeHandler" />
<typeHandler javaType="org.joda.time.LocalTime"
handler="com.cml.springboot.framework.mybatis.typehandler.JodaLocalTimeTypeHandler" />
</typeHandlers>
</configuration>
但是这个仅仅适合小项目并且bean少的情况,假如在打项目上,可能有几十上百的bean,都要一一配置岂不是累死人了,而且容易出bug。
于是继续研究,首先自定义DefaultSqlSessionFactoryBean取代默认的SqlSessionFactoryBean,并且在buildSqlSessionFactory()方法上对bean扫描的配置进行一步步log拆分,主要代码如下:
if (hasLength(this.typeAliasesPackage)) {
String[] typeAliasPackageArray = tokenizeToStringArray(this.typeAliasesPackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
for (String packageToScan : typeAliasPackageArray) {
logger.debug("##################################################################################");
List<String> children = VFS.getInstance().list(packageToScan.replace(".", "/"));
logger.debug("findclass:" + children);
logger.debug("##################################################################################");
logger.debug("DefaultSqlSessionFactoryBean.buildSqlSessionFactory.registerAliases:" + packageToScan);
ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
resolverUtil.find(new ResolverUtil.IsA(Object.class), packageToScan);
Set<Class<? extends Class<?>>> typeSet = resolverUtil.getClasses();
logger.debug(
"DefaultSqlSessionFactoryBean.buildSqlSessionFactory.typeAliasesPackage.scanClass:" + typeSet);
for (Class<?> type : typeSet) {
if (!type.isAnonymousClass() && !type.isInterface() && !type.isMemberClass()) {
String alias = type.getSimpleName();
String key = alias.toLowerCase(Locale.ENGLISH);
logger.debug(
"DefaultSqlSessionFactoryBean.buildSqlSessionFactory.typeAliasesPackage.scan:" + key);
}
}
configuration.getTypeAliasRegistry().registerAliases(packageToScan,
typeAliasesSuperType == null ? Object.class : typeAliasesSuperType);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Scanned package: '" + packageToScan + "' for aliases");
}
}
}
发现在ide上运行的时候是可以扫描到指定的bean,但是在jar上就扫描不到了。主要问题找到了,就是对代码的扫描问题,原本想自定义configuration的,但是发现好多类都是依赖configuration这个类,于是便放弃这个想法,转而研究扫描不到bean的问题。
继续研究源码,得知bean的扫描是通过ResolverUtil这个类进行的,并且ResolverUtil扫描是通过VFS进行扫描的,主要代码:
public ResolverUtil<T> find(Test test, String packageName) {
String path = getPackagePath(packageName);
try {
List<String> children = VFS.getInstance().list(path);
for (String child : children) {
if (child.endsWith(".class"))
addIfMatching(test, child);
}
} catch (IOException ioe) {
log.error("Could not read package: " + packageName, ioe);
}
return this;
}
结合log上的信息,工程上默认使用的是Mybatis的DefaultVFS进行扫描。查看这个类代码后也没发现什么问题,转而求救于百度与谷歌,经过多方搜索,找到了Mybatis官网issue (地址:https://github.com/mybatis/mybatis-3/issues/325)这里有对这些问题进行说明。根据issue的描述与各大神的回答,定位到了问题是DefaultVFS在获取jar上的class问题。
在mybat/spring-boot-starter工程上找到了SpringBootVFS,这个类重写了class扫描功能,通过spring进行扫描。
于是将SpringBootVFS拷贝到工程上,并且添加到VFS实现上去,代码如下:
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(DataSource datasource, MybatisConfigurationProperties properties)
throws Exception {
log.info("*************************sqlSessionFactory:begin***********************" + properties);
VFS.addImplClass(SpringBootVFS.class);
DefaultSqlSessionFactoryBean sessionFactory = new DefaultSqlSessionFactoryBean();
sessionFactory.setDataSource(datasource);
sessionFactory.setTypeAliasesPackage(properties.typeAliasesPackage);
sessionFactory.setTypeHandlersPackage(properties.typeHandlerPackage);
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sessionFactory.setMapperLocations(resolver.getResources(properties.mapperLocations));
// sessionFactory
// .setConfigLocation(new PathMatchingResourcePatternResolver().getResource(properties.configLocation));
SqlSessionFactory resultSessionFactory = sessionFactory.getObject();
log.info("===typealias==>" + resultSessionFactory.getConfiguration().getTypeAliasRegistry().getTypeAliases());
log.info("*************************sqlSessionFactory:successs:" + resultSessionFactory
+ "***********************" + properties);
return resultSessionFactory;
}
这样mybaits打包jar后扫描问题完美解决。
综上,解决SpringBoot Mybatis打包jar后问题处理完毕,已提交到git项目master分支和deploy_jar_bugfind
http://git.oschina.net/cmlbeliever/SpringBootLearning
解决办法:
- 通过mybatis-configuration.xml进行配置
- 通过SpringBootVFS进行自动扫描配置(推荐)
Springboot Mybatis 打包jar扫描bean与mapper问题研究与解决的更多相关文章
- SpringBoot 项目打包后获取不到resource下资源的解决
SpringBoot 项目打包后获取不到resource下资源的解决 在项目中有几个文件需要下载,然后不想暴露真实路径,又没有CDN,便决定使用接口的方式来获取文件.最初的时候使用了传统的方法来获取文 ...
- (二十二)SpringBoot之使用mybatis generator自动生成bean、mapper、mapper xml
一.下载mybatis generator插件 二.生成generatorConfig.xml new一个generatorConfig.xml 三.修改generatorConfig.xml 里面的 ...
- SpringBoot Maven多模块整合MyBatis 打包jar
最近公司开始新的项目,框架选定为SpringBoot+Mybatis,本篇主要记录了在IDEA中搭建SpringBoot多模块项目的过程. 源码:https://github.com/12641561 ...
- SpringBoot引入第三方jar的Bean的三种方式
在SpringBoot的大环境下,基本上很少使用之前的xml配置Bean,主要是因为这种方式不好维护而且也不够方便. 因此本篇博文也不再介绍Spring中通过xml来声明bean的使用方式. 一.注解 ...
- 关于用maven创建的springboot工程打包jar后找不到配置文件的问题
你的resources文件夹的名称写错了!!! 如果不在pom中配置build的资源路径,那么你的资源文件名必须默认是“resources”! 解决办法有两个: 1.修改文件夹名称 2.添加pom的b ...
- SpringBoot环境下使用测试类注入Mapper接口报错解决
当我们在进行开发中难免会要用到测试类,而且测试类要注入Mapper接口,如果测试运行的时候包空指针异常,看看测试类上面的注解是否用对! 正常测试我们需要用到的注解有这些: @SpringBootTes ...
- springboot linux打包后访问不到resources 下面的模板文件
在本地是可以直接获取模板文件并下载,但是服务器上就不行 本地代码: @Overridepublic void downArchRelayTemplate(HttpServletRequest requ ...
- DB数据源之SpringBoot+MyBatis踏坑过程(二)手工配置数据源与加载Mapper.xml扫描
DB数据源之SpringBoot+MyBatis踏坑过程(二)手工配置数据源与加载Mapper.xml扫描 liuyuhang原创,未经允许进制转载 吐槽之后应该有所改了,该方式可以作为一种过渡方式 ...
- DB数据源之SpringBoot+MyBatis踏坑过程(三)手工+半自动注解配置数据源与加载Mapper.xml扫描
DB数据源之SpringBoot+MyBatis踏坑过程(三)手工+半自动注解配置数据源与加载Mapper.xml扫描 liuyuhang原创,未经允许禁止转载 系列目录连接 DB数据源之Spr ...
随机推荐
- beanshell 常用的内置变量与函数
官方详细文档:https://github.com/beanshell/beanshell/wiki log:用来记录日志文件 log.info("jmeter"); vars - ...
- jQuery的attr和prop属性
<div id="div1"></div> attr: 首先是一个参数的attr. $("#div").attr("id&qu ...
- go获取当前项目下所有依赖包
在设置好GOPATH,GOROOT的环境变量的情况下. 在项目配置好pkg.bin.src等这几个目录的情况,进入src目录. 在终端,输入:go get ./... 即可获得所有依赖包.
- 关于Google下插件SwitchyOmega用法
开启代理后,尽管访问很自由了,但是我的搬瓦工,是有流量限制的.所以,在之前,我开启一会自由访问模式(戏称),然后关一会,用来方便打开国内网站. 是的,我这么坚持了半个月,之后,就崩溃了,太尼玛繁琐了! ...
- 关于join on 和单表查询的实时效果
当数据量大(10W单位级)的时候,join的优势,会被单表查询超过. 以下是两张表单查和两张表联查的时间对比,同时,这样的记录有局限性的. 一.数据量少时: 单表查: 表一:显示行 0 - 2 ( 3 ...
- mac、window版编辑器 webstorm 2016... 永久破解方法。
第一步:从官网下载最新版本的webstorm编辑器(建议在官网下载,防止第三方插件恶意攻击!): 下载链接 http://www.jetbrains.com/webstorm/ , 点击 DOWN ...
- sql注入notebook
内容来自: https://ca0y1h.top/ 联合查询注入 使用场景 页面上有显示位 什么是显示位:在一个在一个网站的正常页面,服务端执行SQL语句查询数据库中的数据,客户端将数据展示在页面中, ...
- /sbin/mount.vboxsf: mounting failed with the error: Protocol error
公司换了新电脑,需要把之前的虚拟机的配置全部备份下来,在移动的过程中挂载共享文件夹时候出现了 /sbin/mount.vboxsf: mounting failed with the error: P ...
- 2019-2020-1 20199303《Linux内核原理与分析》第七周作业
进程的描述 1.进程概念 进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位.进程由程序段.数据段.PCB组成 2.PCB中的信息 ①进程标识符 ②处理机状态 ③进程调度信息 ④进程控制 ...
- Linux系统进入救援模式
由于现在很多的服务器都是用的RedHat,CentOS也比较多,这里就介绍CentOS6.6的救援模式. 有很多人的linux在用的时候不小心修改了某个权限,导致系统启动不起来,下面我就来为大家解决一 ...