代码如下:

  1. public class TestUtils {
  2. private static UserDao logDao = SpringContextHolder.getBean(UserDao.class);
  3.  
  4. public static String getLog(String type){
  5. return "!23";
  6. }
  7. }

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

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

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

  1. 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)

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

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

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

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

  1. if (hasLength(this.typeAliasesPackage)) {
  2. String[] typeAliasPackageArray = tokenizeToStringArray(this.typeAliasesPackage,ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
  3. for (String packageToScan : typeAliasPackageArray) {
  4. configuration.getTypeAliasRegistry().registerAliases(packageToScan,
  5. typeAliasesSuperType == null ? Object.class : typeAliasesSuperType);
  6. if (LOGGER.isDebugEnabled()) {
  7. LOGGER.debug("Scanned package: '" + packageToScan + "' for aliases");
  8. }
  9. }
  10. }
  11.  
  12. public void registerAliases(String packageName, Class<?> superType){
  13. ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
  14. //会先过滤superType
  15. resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
  16. Set<Class<? extends Class<?>>> typeSet = resolverUtil.getClasses();
  17. for(Class<?> type : typeSet){
  18. // Ignore inner classes and interfaces (including package-info.java)
  19. // Skip also inner classes. See issue #6
  20. if (!type.isAnonymousClass() && !type.isInterface() && !type.isMemberClass()) {
  21. registerAlias(type);
  22. }
  23. }
  24. }

两个解决办法:

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. linux 下 shell脚本报错:-bash: ./build.sh: /bin/sh^M: bad interpreter: No such file or directory

    主要原因是build.sh是在windows下编辑然后上传到linux系统里执行的..sh文件的格式为dos格式.而linux只能执行格式为unix格式的脚本. 我们可以通过vi编辑器来查看文件的fo ...

  2. unity 3D物体使用EventSystem响应事件

    在ugui中创建一个canvas 之后会自动创建一个EventSystem,用来处理UI上的时间响应.(可以通过UI>EventSystem创建EventSystem) EventSystem ...

  3. git提交代码并将develop分支合并到master分支上

    提交合并代码流程: git add .git commit -m ''git pushgit checkout mastergit merge develop //将develop 分支与master ...

  4. You may need to add '192.168.55.10' to ALLOWED_HOSTS.

    DisallowedHost at / Invalid HTTP_HOST header: '192.168.55.10:8000'. You may need to add '192.168.55. ...

  5. Linux正则表达式,grep总结,sed用法

    原文: 1.sed   流编辑器,实现对文字的增删改替换查(过滤.取行),能同时处理多个文件多行的内容,可以不对原文件改动,把整个文件 输入到屏幕,可以把只匹配到模式的内容输入到屏幕上.还可以对原文件 ...

  6. Altium designer 如何将2D PCB转换成3D

    点击键盘数字键的3,即可,2键可以切换回2D效果,但是如果要看元器件的3D效果,那么元器件封装必须带有3D模型才行! 先按3切换到三维界面,然后按住shift不放,按鼠标右键调整视图角度.

  7. jQuery + ashx 实现图片按比例预览、异步上传及显示

    目录(?)[-] 注ajax 方式异步读取数据库显示图片的方法同上传一致使用 ashx 返回base64字符串在客户端处理即可 记录一个让我纠结良久的问题 在Page_Load 函数中只有第一个用 S ...

  8. abp学习(四)——根据入门教程(aspnetMVC Web API进一步学习)

    Introduction With AspNet MVC Web API EntityFramework and AngularJS 地址:https://aspnetboilerplate.com/ ...

  9. Py---StringIO and BytesIO 读取str

    # StringIO和BytesIO (1)StringIO顾名思义就是在内存中读写str.(2)StringIO操作的只能是str,如果要操作二进制数据,就需要使用BytesIO. # string ...

  10. linux系统编程之信号(五)

    今天继续对信号进行学习,开始正入正题: sigaction函数: 安装信号之前我们已经学过一个函数:signal,它最早是在unix上出现的,它是对不可靠信号进行安装的,之后出现了可靠信号和实时信号, ...