代码如下:

public class TestUtils {
private static UserDao logDao = SpringContextHolder.getBean(UserDao.class); public static String getLog(String type){
return "!23";
}
}

在controller中使用这Utils的时候出现如下错误:

奇怪的是在容器中又能得到UserDao,为何初始化这个TestUtils的时候就失败了呢。

经过一番排查,发现项目启动的时候有这么一段日志

2019-10-29 15:36:22.839  WARN 21948 --- [           main] o.mybatis.spring.SqlSessionFactoryBean   : Cannot load the 'file [D:\*\utils\TestUtils.class]'. Cause by java.lang.NoClassDefFoundError: Could not initialize class com.*.utils.TestUtils

所以觉得是mybatis的问题,mybaits在扫描所有entity的时候逻辑(mybatis-spring-boot-starter是2.1.1对应的mybatis-spring的版本2.0.3)

    if (hasLength(this.typeAliasesPackage)) {
scanClasses(this.typeAliasesPackage, this.typeAliasesSuperType).stream()
.filter(clazz -> !clazz.isAnonymousClass()).filter(clazz -> !clazz.isInterface())
.filter(clazz -> !clazz.isMemberClass()).forEach(targetConfiguration.getTypeAliasRegistry()::registerAlias);
} private Set<Class<?>> scanClasses(String packagePatterns, Class<?> assignableType) throws IOException {
Set<Class<?>> classes = new HashSet<>();
String[] packagePatternArray = tokenizeToStringArray(packagePatterns,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
for (String packagePattern : packagePatternArray) {
//会先扫描出所有typeAliasesPackage下面所有的类
Resource[] resources = RESOURCE_PATTERN_RESOLVER.getResources(ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
+ ClassUtils.convertClassNameToResourcePath(packagePattern) + "/**/*.class");
for (Resource resource : resources) {
try {
ClassMetadata classMetadata = METADATA_READER_FACTORY.getMetadataReader(resource).getClassMetadata();
//此时会先加载这个类,加载类的时候里面的静态属性会初始化,但是此时容器中还有UserDao的Bean实例,所以导致初始化失败,触发异常
Class<?> clazz = Resources.classForName(classMetadata.getClassName());
//此时才判断superType
if (assignableType == null || assignableType.isAssignableFrom(clazz)) {
classes.add(clazz);
}
} catch (Throwable e) {
LOGGER.warn(() -> "Cannot load the '" + resource + "'. Cause by " + e.toString());
}
}
}
return classes;
}

上面就是导致出现问题的原因。

看了一下之前的项目,逻辑一样,但为啥没出现问题呢,发现之前项目引用的mybatis-spring-boot-starter是1.3.2版本,对应的mybatis-spring的版本的1.3.2。

那么里面的实现是怎么样呢?为何没出现类似的错误呢?

if (hasLength(this.typeAliasesPackage)) {
String[] typeAliasPackageArray = tokenizeToStringArray(this.typeAliasesPackage,ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
for (String packageToScan : typeAliasPackageArray) {
configuration.getTypeAliasRegistry().registerAliases(packageToScan,
typeAliasesSuperType == null ? Object.class : typeAliasesSuperType);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Scanned package: '" + packageToScan + "' for aliases");
}
}
} public void registerAliases(String packageName, Class<?> superType){
ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
//会先过滤superType
resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
Set<Class<? extends Class<?>>> typeSet = resolverUtil.getClasses();
for(Class<?> type : typeSet){
// Ignore inner classes and interfaces (including package-info.java)
// Skip also inner classes. See issue #6
if (!type.isAnonymousClass() && !type.isInterface() && !type.isMemberClass()) {
registerAlias(type);
}
}
}

两个解决办法:

1.降低mybatis-spring-boot-starter 的版本到(经测试mybatis-spring.jar的2.0.0及以下版本都可以,其他版本没看源码)

2.精确指定到entity的目录(建议此,减少扫描和遍历的次数)

记一次SpringContextHolder.getBean出现异常NoClassDefFoundError: Could not initialize class的更多相关文章

  1. 异常:Caused by: java.lang.NoClassDefFoundError: Could not initialize class net.sf.log4jdbc.Properties

    参考文章: 使用Log4jdbc-log4j2监听MyBatis中运行的SQL和Connection 使用 log4jdbc格式化输出SQL,maven配置如下: <dependency> ...

  2. Java 上传文件到 SFTP 抛异常 java.lang.NoClassDefFoundError: Could not initialize class sun.security.ec.SunEC 的解决办法

    最近从 Op 那里报来一个问题,说是SFTP上传文件不成功.拿到的 Exception 如下: Caused by: java.lang.NoClassDefFoundError: Could not ...

  3. 异常-----java.lang.NoClassDefFoundError: Could not initialize class net.sf.cglib.core.KeyFactory

    SSH 类库问题 java.lang.NoClassDefFoundError: Could not initialize class net.sf.cglib.proxy.Enhancer2009- ...

  4. 日志异常:java.lang.NoClassDefFoundError: Could not initialize class org.slf4j.impl.StaticLoggerBinder

    今天启动开发的项目,碰到了一个日志上的bug:java.lang.NoClassDefFoundError: Could not initialize class org.slf4j.impl.Sta ...

  5. 验证码无法显示,服务器端出现异常:Could not initialize class sun.awt.X11GraphicsEnvironment

    异常信息: Caused by: java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11GraphicsEnvir ...

  6. hibernate 解决 java.lang.NoClassDefFoundError: Could not initialize class org.hibernate.validator.internal.engine.xxx 这类的问题

    <!-- 解决 java.lang.NoClassDefFoundError: Could not initialize class org.hibernate.validator.intern ...

  7. @Autowired注解和静态方法 NoClassDefFoundError could not initialize class 静态类

    NoClassDefFoundError could not initialize class 静态类 spring boot 静态类 java.lang.ExceptionInInitializer ...

  8. java.lang.NoClassDefFoundError: Could not initialize class异常处理

    借鉴:http://blog.csdn.net/sleepdancer/article/details/9207425 static { InputStream in = XXX.class.getR ...

  9. weblogic .NoClassDefFoundError: Could not initialize class sun.awt.X11Graphi

    这个是常见问题,可以通过增加Weblogic的启动参数来解决: -Djava.awt.headless=true 你可以修改 startWebLogic.sh 文件. export JAVA_OPTI ...

随机推荐

  1. split()方法 splice()方法 slice()方法

    split()方法是对字符串的操作:splice()和slice()是对数组的操作.slice()也可用于字符串. 一.作用对象 1.split()方法是对字符串的操作:splice()和slice( ...

  2. FPM-OVP增强实例-银行账户

    本文是基于NWBC银行账户信息进行增强,相关过程如下: 1.定位需要增强的界面 首先登陆SAP-GUI(尽量EN登陆,ZH可能乱码),输入TCODE:NWBC跳转到浏览器界面,新建银行账户: 注意上图 ...

  3. [AIR] NativeExtension在IOS下的开发实例 --- 新建项目测试ANE(四)

    来源:http://bbs.9ria.com/thread-102043-1-1.html 通过前面的努力,好了,我们终于得到了一个ANE文件了.下面我们开始新建一个Flex Mobile项目做一下测 ...

  4. 获取项目中所有URL--获取swagger上展示的接口信息

    有时我们需要接口的一些基本信息,比如接口请求路径,接口请求方式等,我们用这些信息来做判断,或者入库. 我在开发接口权限的时候就遇到了这个问题,之前写的接口很多,现在需要将这些接口信息存到数据库中, 用 ...

  5. Anaconda-Jupyter notebook 如何安装 nbextensions

    系统环境:windows 安装过程中,再次遇到了一地鸡毛,经过不断查询方法,发现前辈大牛们好棒棒! Step1:确定是已经安装好anaconda Step2:要在anaconda prompt模式下运 ...

  6. tomcat7.x配置APR高并发模式

    Tomcat支持BIO/NIO/APR三种运行模式 ,性能各色春秋! Apr插件提高Tomcat性能 Tomcat可以使用APR来提供超强的可伸缩性和性能,更好地集成本地服务器技术. APR(Apac ...

  7. linux学习记录--比较基本的文件档案知识

    [档案类型权限,连接数,档案拥有者,档案所属群组,档案容量,修改日期,档名],对应了上面的每一列的参数属性. 档案类型权限那一部分总共有十个字母,第一个字母代表档案类型: 当为[ d ]则是目录,例如 ...

  8. SOAP知识点

    SOAP简介: SOAP 是基于 XML 的简易协议,可使应用程序在 HTTP 之上进行信息交换. 或者更简单地说:SOAP 是用于访问网络服务的协议. 1.什么是 SOAP? SOAP 指简易对象访 ...

  9. Java synchronized实现原理总结和偏量锁、轻量锁、重量锁、自旋锁

    synchronized实现同步的基础:Java中的每一个对象都可以作为锁.具体表现为以下3种形式. 对于普通同步方法,锁是当前实例对象(this). 对于静态同步方法,锁是当前类的Class对象. ...

  10. python 杂记20191102

    上下文管理器: def __exit__(self, exc_type, exc_val, exc_tb):若exc_tb不是空,则说明有异常返回值只能是true或false,若是false,则会把之 ...