zoukankan      html  css  js  c++  java
  • 记一次SpringContextHolder.getBean出现异常NoClassDefFoundError: Could not initialize class

    代码如下:

    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:*utilsTestUtils.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的目录(建议此,减少扫描和遍历的次数)

  • 相关阅读:
    Atitit 经济学常见的流派 古典主义与凯恩斯主义
    Atitit 学习方法 体系化学习方法 Excel 科目,分类,专业 三级分类。。 知识点。。 课程就是每一个知识点的详细化。。 比如经济学 类别 专业 xx概论知识点 3、金
    atiitt it学科体系化 体系树与知识点概念大总结.xlsx
    Atitit 减少财政支出普通人如何蹭政府补贴措施 attilax大总结.docx
    Atitit 信用管理概论 attilax学习心得
    Atitit.月度计划日程表 每月流程表v5
    Atitit 企业6大职能 attilax总结
    Atitit 常见每日流程日程日常工作.docx v8 ver ampm imp 签到 am y 天气情况检查 am y 晨会,每天或者隔天 am 每日计划(项目计划,日计划等。 am
    Atitit 财政赤字解决方案
    Atitit 建设自己的财政体系 attilax总结 1.1. 收入理论 2 1.2. 收入分类 2 1.3. 2 1.4. 非货币收入 2 1.5. 2 1.6. 降低期望 2 1.7.
  • 原文地址:https://www.cnblogs.com/gavinYang/p/11759448.html
Copyright © 2011-2022 走看看