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

解决办法:

  1. 通过mybatis-configuration.xml进行配置
  2. 通过SpringBootVFS进行自动扫描配置(推荐)

Springboot Mybatis 打包jar扫描bean与mapper问题研究与解决的更多相关文章

  1. SpringBoot 项目打包后获取不到resource下资源的解决

    SpringBoot 项目打包后获取不到resource下资源的解决 在项目中有几个文件需要下载,然后不想暴露真实路径,又没有CDN,便决定使用接口的方式来获取文件.最初的时候使用了传统的方法来获取文 ...

  2. (二十二)SpringBoot之使用mybatis generator自动生成bean、mapper、mapper xml

    一.下载mybatis generator插件 二.生成generatorConfig.xml new一个generatorConfig.xml 三.修改generatorConfig.xml 里面的 ...

  3. SpringBoot Maven多模块整合MyBatis 打包jar

    最近公司开始新的项目,框架选定为SpringBoot+Mybatis,本篇主要记录了在IDEA中搭建SpringBoot多模块项目的过程. 源码:https://github.com/12641561 ...

  4. SpringBoot引入第三方jar的Bean的三种方式

    在SpringBoot的大环境下,基本上很少使用之前的xml配置Bean,主要是因为这种方式不好维护而且也不够方便. 因此本篇博文也不再介绍Spring中通过xml来声明bean的使用方式. 一.注解 ...

  5. 关于用maven创建的springboot工程打包jar后找不到配置文件的问题

    你的resources文件夹的名称写错了!!! 如果不在pom中配置build的资源路径,那么你的资源文件名必须默认是“resources”! 解决办法有两个: 1.修改文件夹名称 2.添加pom的b ...

  6. SpringBoot环境下使用测试类注入Mapper接口报错解决

    当我们在进行开发中难免会要用到测试类,而且测试类要注入Mapper接口,如果测试运行的时候包空指针异常,看看测试类上面的注解是否用对! 正常测试我们需要用到的注解有这些: @SpringBootTes ...

  7. springboot linux打包后访问不到resources 下面的模板文件

    在本地是可以直接获取模板文件并下载,但是服务器上就不行 本地代码: @Overridepublic void downArchRelayTemplate(HttpServletRequest requ ...

  8. DB数据源之SpringBoot+MyBatis踏坑过程(二)手工配置数据源与加载Mapper.xml扫描

    DB数据源之SpringBoot+MyBatis踏坑过程(二)手工配置数据源与加载Mapper.xml扫描 liuyuhang原创,未经允许进制转载  吐槽之后应该有所改了,该方式可以作为一种过渡方式 ...

  9. DB数据源之SpringBoot+MyBatis踏坑过程(三)手工+半自动注解配置数据源与加载Mapper.xml扫描

    DB数据源之SpringBoot+MyBatis踏坑过程(三)手工+半自动注解配置数据源与加载Mapper.xml扫描 liuyuhang原创,未经允许禁止转载    系列目录连接 DB数据源之Spr ...

随机推荐

  1. beanshell 常用的内置变量与函数

    官方详细文档:https://github.com/beanshell/beanshell/wiki log:用来记录日志文件 log.info("jmeter"); vars - ...

  2. jQuery的attr和prop属性

    <div id="div1"></div> attr: 首先是一个参数的attr. $("#div").attr("id&qu ...

  3. go获取当前项目下所有依赖包

    在设置好GOPATH,GOROOT的环境变量的情况下. 在项目配置好pkg.bin.src等这几个目录的情况,进入src目录. 在终端,输入:go get ./... 即可获得所有依赖包.

  4. 关于Google下插件SwitchyOmega用法

    开启代理后,尽管访问很自由了,但是我的搬瓦工,是有流量限制的.所以,在之前,我开启一会自由访问模式(戏称),然后关一会,用来方便打开国内网站. 是的,我这么坚持了半个月,之后,就崩溃了,太尼玛繁琐了! ...

  5. 关于join on 和单表查询的实时效果

    当数据量大(10W单位级)的时候,join的优势,会被单表查询超过. 以下是两张表单查和两张表联查的时间对比,同时,这样的记录有局限性的. 一.数据量少时: 单表查: 表一:显示行 0 - 2 ( 3 ...

  6. mac、window版编辑器 webstorm 2016... 永久破解方法。

    第一步:从官网下载最新版本的webstorm编辑器(建议在官网下载,防止第三方插件恶意攻击!): 下载链接  http://www.jetbrains.com/webstorm/  , 点击 DOWN ...

  7. sql注入notebook

    内容来自: https://ca0y1h.top/ 联合查询注入 使用场景 页面上有显示位 什么是显示位:在一个在一个网站的正常页面,服务端执行SQL语句查询数据库中的数据,客户端将数据展示在页面中, ...

  8. /sbin/mount.vboxsf: mounting failed with the error: Protocol error

    公司换了新电脑,需要把之前的虚拟机的配置全部备份下来,在移动的过程中挂载共享文件夹时候出现了 /sbin/mount.vboxsf: mounting failed with the error: P ...

  9. 2019-2020-1 20199303《Linux内核原理与分析》第七周作业

    进程的描述 1.进程概念 进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位.进程由程序段.数据段.PCB组成 2.PCB中的信息 ①进程标识符 ②处理机状态 ③进程调度信息 ④进程控制 ...

  10. Linux系统进入救援模式

    由于现在很多的服务器都是用的RedHat,CentOS也比较多,这里就介绍CentOS6.6的救援模式. 有很多人的linux在用的时候不小心修改了某个权限,导致系统启动不起来,下面我就来为大家解决一 ...