文档章节

centos7导致的spring循环依赖

Mr_Qi
 Mr_Qi
发布于 05/21 22:43
字数 4874
阅读 498
收藏 7

背景

由于一些变化 公司jenkins发生了迁移 老的jenkins运行在centos6 而新的jenkins运行在centos7上

结果导致某一台服务完全起不来 出现了bean循环依赖

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'sqlSessionFactoryBean' defined in class path resource [com/f6car/report/config/MybatisConfigurer.class]: Unsatisfied de      pendency expressed through method 'sqlSessionFactoryBean' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceConfig1' defined in URL [jar:file:/hom      e/opt/f6-report-server-8079/report.jar!/BOOT-INF/classes!/com/f6car/report/config/DataSourceConfig1.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creat      ing bean with name 'dataSourceInitializer': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'primaryDataSource': Requested       bean is currently in creation: Is there an unresolvable circular reference?
24760     at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)
24761     at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467)
24762     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1173)
24763     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1067)
24764     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
24765     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
24766     at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
24767     at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
24768     at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
24769     at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
24770     at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
24771     at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
24772     at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
24773     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType(AbstractAutowireCapableBeanFactory.java:1342)
24774     ... 51 common frames omitted
24775 Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceConfig1' defined in URL [jar:file:/home/opt/f6-report-server-8079/report.jar!/BOOT-INF/classes!/com/f6car/report/confi      g/DataSourceConfig1.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceInitializer': Invocation of init method failed; ne      sted exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'primaryDataSource': Requested bean is currently in creation: Is there an unresolvable circular reference?
24776     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564)
24777     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
24778     at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
24779     at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
24780     at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
24781     at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
24782     at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:372)
24783     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1173)
24784     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1067)
24785     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
24786     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
24787     at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
24788     at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
24789     at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
24790     at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
24791     at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
24792     at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
24793     at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
24794     at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835)
24795     at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
24796     ... 64 common frames omitted
24797 Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceInitializer': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInC      reationException: Error creating bean with name 'primaryDataSource': Requested bean is currently in creation: Is there an unresolvable circular reference?
24798     at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:137)
24799     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:409)
24800     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1620)
24801     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
24802     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
24803     at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
24804     at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
24805     at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
24806     at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:220)
24807     at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1018)
24808     at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:345)
24809     at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:340)
24810     at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerPostProcessor.postProcessAfterInitialization(DataSourceInitializerPostProcessor.java:62)
24811     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:423)
24812     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1633)
24813     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
24814     ... 83 common frames omitted

问题

由于代码完全没有修改过 因此考虑是否由于环境发生了变化导致【目前锁定在jenkins变化】

该项目使用了多数据源 很明显这是由于循环依赖导致出现的 首先来看一下数据源配置

@Configuration
@ConfigurationProperties("spring.datasource")
public class DataSourceConfig1 extends AbstractDataSourceConfig {
    @Bean(PRIMARY_DATA_SOURCE_NAME)
    @Primary
    public DataSource dataSource1() {
        return this;
    }
}

 

@Configuration
@ConfigurationProperties("spring.datasource2")
@Lazy
@ConditionalOnProperty(name = "spring.datasource2.url", matchIfMissing = false)
 
public class DataSourceConfig2 extends AbstractDataSourceConfig {
    @Bean(SECOND_DATA_SOURCE_NAME)
    public DataSource dataSource2() {
        return this;
    }
}

当我们spring正常启动时候我们知道根据bean注入的顺序会依次初始化对应bean

首先分析一下出现错误的场景

  1. spring初始化controller 发觉依赖service
  2. spring初始化service发觉依赖dao
  3. spring初始化dao发觉依赖sqlSession
  4. spring初始化sqlSession发觉依赖dataSource
  5. spring初始化dataSource(见上方代码)
  6. 此时由于dataSource需要执行processor DataSourceInitializerPostProcessor
  7. 该processor会在dataSource初始化完成后调用init方法 实质上 就是

    this.beanFactory.getBean(DataSourceInitializer.class);

     

  8. 上述代码可以看到需要初始化DataSourceInitializer 而该类的作用是用于dataSource初始化执行一些脚本

  9. 该类的方法如下使用

    @PostConstruct
    public void init() {
       if (!this.properties.isInitialize()) {
          logger.debug("Initialization disabled (not running DDL scripts)");
          return;
       }
       if (this.applicationContext.getBeanNamesForType(DataSource.class, false,
             false).length > 0) {
          this.dataSource = this.applicationContext.getBean(DataSource.class);
       }
       if (this.dataSource == null) {
          logger.debug("No DataSource found so not initializing");
          return;
       }
       runSchemaScripts();
    }

     

  10. 此时applicationContext.getBean(DataSource.class) 实质上会调用某个dataSource【如果有多个怎么办???】当存在多个的时候会选择含有primary的bean 对于本篇文章就是PRIMARY_DATA_SOURCE_NAME

  11. 那么如果当PRIMARY_DATA_SOURCE_NAME还在创建过程中就会出现此问题【在此处表现在sqlSession依赖PRIMARY_DATA_SOURCE_NAME】

 

那么为何在centos6上编译出现的jar没有此问题呢???

分析

从上述描述中我们可以看到当sqlSession依赖的dataSource导致出现此问题

那么出现了两个问题

  1. 为何其他服务迁移到新环境【新的jenkins编译】没有问题
  2. 为何该服务在以前环境编译没问题在新的环境出现了问题

首先解释第二个问题

我们看了上述的分析其实很容易将依赖循环打破===》

很简单 只要我们在sqlSessionBean初始化完成之前就可以完成dataSource的初始化即可!确实很简单 但是也是个好办法

 

那么我们来看一下两边bean的初始化顺序是否发生了变化

centos7

centos6

果然出现了问题 可以正常运行【即centos6编译产生的dataSource1在前面而centos7编译产生的dataSource不在第一页 很显然controller出现在前边那么就会出现上文的结论】

从上述可以看到似乎和多数据源没有太多关系【或者说和我们理解的多数据源没有太多关系】

从过往的学习中我们知道这个bean出现的位置和在BeanFactory中注册的位置有关

而注册的位置又和扫描主键的顺序有关【但是在Springboot我们通常配置即Application所在的包】

因此我们来看一下究竟是如何注册的

@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
   String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
   basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
   String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
         ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
 
   // Actually scan for bean definitions and register them.
   ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
   Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
   registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
 
   return null;
}

我们看到了其实通过ClassPathBeanDefinitionScanner来注册的

/**
 * Perform a scan within the specified base packages.
 * @param basePackages the packages to check for annotated classes
 * @return number of beans registered
 */
public int scan(String... basePackages) {
   int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
 
   doScan(basePackages);
 
   // Register annotation config processors, if necessary.
   if (this.includeAnnotationConfig) {
      AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
   }
 
   return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}

 

/**
 * Perform a scan within the specified base packages,
 * returning the registered bean definitions.
 * <p>This method does <i>not</i> register an annotation config processor
 * but rather leaves this up to the caller.
 * @param basePackages the packages to check for annotated classes
 * @return set of beans registered if any for tooling registration purposes (never {@code null})
 */
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
   Assert.notEmpty(basePackages, "At least one base package must be specified");
   Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
   for (String basePackage : basePackages) {
      Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
      for (BeanDefinition candidate : candidates) {
         ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
         candidate.setScope(scopeMetadata.getScopeName());
         String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
         if (candidate instanceof AbstractBeanDefinition) {
            postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
         }
         if (candidate instanceof AnnotatedBeanDefinition) {
            AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
         }
         if (checkCandidate(beanName, candidate)) {
            BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
            definitionHolder =
                  AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
            beanDefinitions.add(definitionHolder);
            registerBeanDefinition(definitionHolder, this.registry);
         }
      }
   }
   return beanDefinitions;
}
/**
 * Scan the class path for candidate components.
 * @param basePackage the package to check for annotated classes
 * @return a corresponding Set of autodetected bean definitions
 */
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
   Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();
   try {
      String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
            resolveBasePackage(basePackage) + '/' + this.resourcePattern;
      Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
      boolean traceEnabled = logger.isTraceEnabled();
      boolean debugEnabled = logger.isDebugEnabled();
      for (Resource resource : resources) {
         if (traceEnabled) {
            logger.trace("Scanning " + resource);
         }
         if (resource.isReadable()) {
            try {
               MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
               if (isCandidateComponent(metadataReader)) {
                  ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                  sbd.setResource(resource);
                  sbd.setSource(resource);
                  if (isCandidateComponent(sbd)) {
                     if (debugEnabled) {
                        logger.debug("Identified candidate component class: " + resource);
                     }
                     candidates.add(sbd);
                  }
                  else {
                     if (debugEnabled) {
                        logger.debug("Ignored because not a concrete top-level class: " + resource);
                     }
                  }
               }
               else {
                  if (traceEnabled) {
                     logger.trace("Ignored because not matching any filter: " + resource);
                  }
               }
            }
            catch (Throwable ex) {
               throw new BeanDefinitionStoreException(
                     "Failed to read candidate component class: " + resource, ex);
            }
         }
         else {
            if (traceEnabled) {
               logger.trace("Ignored because not readable: " + resource);
            }
         }
      }
   }
   catch (IOException ex) {
      throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
   }
   return candidates;
}

 

其实整句的关键在于this.resourcePatternResolver.getResources(packageSearchPath); 这个返回的结果决定了顺序

@Override
public Resource[] getResources(String locationPattern) throws IOException {
   Assert.notNull(locationPattern, "Location pattern must not be null");
   if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
      // a class path resource (multiple resources for same name possible)
      if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
         // a class path resource pattern
         return findPathMatchingResources(locationPattern);
      }
      else {
         // all class path resources with the given name
         return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
      }
   }
   else {
      // Generally only look for a pattern after a prefix here,
      // and on Tomcat only after the "*/" separator for its "war:" protocol.
      int prefixEnd = (locationPattern.startsWith("war:") ? locationPattern.indexOf("*/") + 1 :
            locationPattern.indexOf(":") + 1);
      if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {
         // a file pattern
         return findPathMatchingResources(locationPattern);
      }
      else {
         // a single resource with the given name
         return new Resource[] {getResourceLoader().getResource(locationPattern)};
      }
   }
}
/**
 * Find all resources that match the given location pattern via the
 * Ant-style PathMatcher. Supports resources in jar files and zip files
 * and in the file system.
 * @param locationPattern the location pattern to match
 * @return the result as Resource array
 * @throws IOException in case of I/O errors
 * @see #doFindPathMatchingJarResources
 * @see #doFindPathMatchingFileResources
 * @see org.springframework.util.PathMatcher
 */
protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {
   String rootDirPath = determineRootDir(locationPattern);
   String subPattern = locationPattern.substring(rootDirPath.length());
   Resource[] rootDirResources = getResources(rootDirPath);
   Set<Resource> result = new LinkedHashSet<Resource>(16);
   for (Resource rootDirResource : rootDirResources) {
      rootDirResource = resolveRootDirResource(rootDirResource);
      URL rootDirURL = rootDirResource.getURL();
      if (equinoxResolveMethod != null) {
         if (rootDirURL.getProtocol().startsWith("bundle")) {
            rootDirURL = (URL) ReflectionUtils.invokeMethod(equinoxResolveMethod, null, rootDirURL);
            rootDirResource = new UrlResource(rootDirURL);
         }
      }
      if (rootDirURL.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
         result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirURL, subPattern, getPathMatcher()));
      }
      else if (ResourceUtils.isJarURL(rootDirURL) || isJarResource(rootDirResource)) {
         result.addAll(doFindPathMatchingJarResources(rootDirResource, rootDirURL, subPattern));
      }
      else {
         result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));
      }
   }
   if (logger.isDebugEnabled()) {
      logger.debug("Resolved location pattern [" + locationPattern + "] to resources " + result);
   }
   return result.toArray(new Resource[result.size()]);
}

 

可以看到由于我们是jar运行那么最终都走到了

result.addAll(doFindPathMatchingJarResources(rootDirResource, rootDirURL, subPattern));

我们知道jar本质上都是zip 只不过是不同的拓展名

for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements();) {
   JarEntry entry = entries.nextElement();
   String entryPath = entry.getName();
   if (entryPath.startsWith(rootEntryPath)) {
      String relativePath = entryPath.substring(rootEntryPath.length());
      if (getPathMatcher().match(subPattern, relativePath)) {
         result.add(rootDirResource.createRelative(relativePath));
      }
   }
}

因此可以看到最终的顺序其实就是jar中的顺序 而jar的顺序其实是在写入的时候就已经固定了!

我们可以使用unzip命令查看

Archive:  /data/jenkins/workspace/f6-local-test-report-server/report-web/target/report.jar.original
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  05-03-2018 13:46   META-INF/
      376  05-03-2018 13:46   META-INF/MANIFEST.MF
        0  05-03-2018 13:46   j2cache/
        0  05-03-2018 13:46   com/
        0  05-03-2018 13:46   com/f6car/
        0  05-03-2018 13:46   com/f6car/report/
        0  05-03-2018 13:46   com/f6car/report/controller/
        0  05-03-2018 13:46   com/f6car/report/controller/base/
        0  05-03-2018 13:46   com/f6car/report/controller/part/
        0  05-03-2018 13:46   com/f6car/report/controller/maintain/
        0  05-03-2018 13:46   com/f6car/report/controller/finance/
        0  05-03-2018 13:46   com/f6car/report/controller/custom/
        0  05-03-2018 13:46   com/f6car/report/controller/item/
        0  05-03-2018 13:46   com/f6car/report/controller/saPerformance/
        0  05-03-2018 13:46   com/f6car/report/config/
        0  05-03-2018 13:46   com/f6car/report/jwt/
        0  05-03-2018 13:46   com/f6car/report/web/
        0  05-03-2018 13:46   com/f6car/report/web/converter/
        0  05-03-2018 13:46   com/f6car/report/web/interceptor/
        0  05-03-2018 13:46   com/f6car/report/web/json/
        0  05-03-2018 13:46   com/f6car/report/web/shiro/
        0  05-03-2018 13:46   com/f6car/report/callback/
     1749  05-03-2018 13:46   j2cache/application-unit-test.properties
     1765  05-03-2018 13:46   j2cache/j2cache-local-test.properties
     1796  05-03-2018 13:46   j2cache/j2cache-prod-trial.properties
     1977  05-03-2018 13:46   j2cache/j2cache-dev.properties
     1784  05-03-2018 13:46   j2cache/j2cache-prod.properties
     1748  05-03-2018 13:46   j2cache/j2cache-re.properties
     1506  05-03-2018 13:46   application-prod.properties
     1196  05-03-2018 13:46   application-re.properties
     1204  05-03-2018 13:46   application-local-test.properties
     1093  05-03-2018 13:46   application-unit-test.properties
     1859  05-03-2018 13:46   application-prod-trial.properties
      991  05-03-2018 13:46   application-dev.properties
     4692  05-03-2018 13:46   application.properties
     5242  05-03-2018 13:46   ehcache.xml
     7683  05-03-2018 13:46   logback-spring.xml
     1530  05-03-2018 13:46   banner.txt
    32989  05-03-2018 13:46   META-INF/spring-configuration-metadata.json
     1413  05-03-2018 13:46   com/f6car/report/controller/base/SystemController.class
     1433  05-03-2018 13:46   com/f6car/report/controller/base/BaseController$1.class
     3150  05-03-2018 13:46   com/f6car/report/controller/base/BaseController$2.class
     1834  05-03-2018 13:46   com/f6car/report/controller/base/BaseController$3.class
    16088  05-03-2018 13:46   com/f6car/report/controller/base/BaseController.class
     1181  05-03-2018 13:46   com/f6car/report/controller/base/DisableSwaggerUiController.class
     5647  05-03-2018 13:46   com/f6car/report/controller/base/AuthController.class
    11801  05-03-2018 13:46   com/f6car/report/controller/part/PartController.class
     5992  05-03-2018 13:46   com/f6car/report/controller/maintain/MaintainBusinessController.class
     4139  05-03-2018 13:46   com/f6car/report/controller/finance/FinanceSummaryController.class
    17110  05-03-2018 13:46   com/f6car/report/controller/finance/FinanceDetailController.class
     2612  05-03-2018 13:46   com/f6car/report/controller/custom/DailyCustomReportController.class
    10714  05-03-2018 13:46   com/f6car/report/controller/item/ItemController.class
     2215  05-03-2018 13:46   com/f6car/report/controller/saPerformance/SaCashPerformanceController.class
      895  05-03-2018 13:46   com/f6car/report/config/DataSourceConfig2.class
      367  05-03-2018 13:46   com/f6car/report/config/AbstractDataSourceConfig.class
     2468  05-03-2018 13:46   com/f6car/report/config/ReportStatisticConfig.class
     1688  05-03-2018 13:46   com/f6car/report/config/CacheConfig.class
      599  05-03-2018 13:46   com/f6car/report/config/SSOConfig.class
     2270  05-03-2018 13:46   com/f6car/report/config/SSO.class
      804  05-03-2018 13:46   com/f6car/report/config/DataSourceConfig1.class
      689  05-03-2018 13:46   com/f6car/report/config/AfterCommitConfig.class
      771  05-03-2018 13:46   com/f6car/report/config/ResourceHandler.class
     3750  05-03-2018 13:46   com/f6car/report/config/WebMvcConfigurer$1.class
    13698  05-03-2018 13:46   com/f6car/report/config/WebMvcConfigurer.class
     1064  05-03-2018 13:46   com/f6car/report/config/ResourceHandlerConfig.class
     2376  05-03-2018 13:46   com/f6car/report/config/SwaggerConfig.class
     4472  05-03-2018 13:46   com/f6car/report/config/ShiroConfig.class
      189  05-03-2018 13:46   com/f6car/report/jwt/TokenExtractor.class
     3862  05-03-2018 13:46   com/f6car/report/jwt/JwtTokenFactory.class
     2429  05-03-2018 13:46   com/f6car/report/jwt/RefreshToken.class
     2026  05-03-2018 13:46   com/f6car/report/jwt/RawAccessJwtToken.class
     1761  05-03-2018 13:46   com/f6car/report/jwt/JwtConfig.class
     1766  05-03-2018 13:46   com/f6car/report/jwt/UserContext.class
      809  05-03-2018 13:46   com/f6car/report/jwt/AccessJwtToken.class
      935  05-03-2018 13:46   com/f6car/report/jwt/BloomTokenVerifier.class
      343  05-03-2018 13:46   com/f6car/report/jwt/TokenVerifier.class
     1249  05-03-2018 13:46   com/f6car/report/jwt/Scopes.class
     1532  05-03-2018 13:46   com/f6car/report/jwt/AlgTokenVerifier.class
     1460  05-03-2018 13:46   com/f6car/report/jwt/DefaultTokenExtractor.class
     1409  05-03-2018 13:46   com/f6car/report/jwt/IssueTokenVerifier.class
      746  05-03-2018 13:46   com/f6car/report/jwt/JwtConfiguar.class
     1440  05-03-2018 13:46   com/f6car/report/web/converter/MapWorkBookHandler$1.class
     2852  05-03-2018 13:46   com/f6car/report/web/converter/MapWorkBookHandler.class
     2137  05-03-2018 13:46   com/f6car/report/web/converter/AbstractWorkBookHandler$1.class
     6726  05-03-2018 13:46   com/f6car/report/web/converter/AbstractWorkBookHandler.class
      467  05-03-2018 13:46   com/f6car/report/web/converter/WorkBookHandler.class
     9165  05-03-2018 13:46   com/f6car/report/web/converter/ExcelHttpMessageConverter.class
     2147  05-03-2018 13:46   com/f6car/report/web/converter/NormalWorkBookHandler.class
     4080  05-03-2018 13:46   com/f6car/report/web/interceptor/CleanInterceptor.class
      682  05-03-2018 13:46   com/f6car/report/web/interceptor/AbstractExcludeInterceptor.class
      251  05-03-2018 13:46   com/f6car/report/web/interceptor/ExcludePathable.class
      735  05-03-2018 13:46   com/f6car/report/web/interceptor/SSOInterceptor.class
     3245  05-03-2018 13:46   com/f6car/report/web/interceptor/CSRFInterceptor.class
     5019  05-03-2018 13:46   com/f6car/report/web/interceptor/JWTTokenAuthInterceptor.class
     4335  05-03-2018 13:46   com/f6car/report/web/interceptor/KissoShiroInterceptor.class
      751  05-03-2018 13:46   com/f6car/report/web/json/BigIntegerValueFilter.class
     2167  05-03-2018 13:46   com/f6car/report/web/shiro/ReturnUrlParamFilter.class
     1530  05-03-2018 13:46   com/f6car/report/ApplicationRefreshedListener.class
      910  05-03-2018 13:46   com/f6car/report/Application.class
     5080  05-03-2018 13:46   com/f6car/report/callback/CustomCallback.class
        0  05-03-2018 13:46   META-INF/maven/
        0  05-03-2018 13:46   META-INF/maven/com.f6car.report/
        0  05-03-2018 13:46   META-INF/maven/com.f6car.report/report-web/
     6013  05-03-2018 13:45   META-INF/maven/com.f6car.report/report-web/pom.xml
      127  05-03-2018 13:46   META-INF/maven/com.f6car.report/report-web/pom.properties
---------                     -------
   272795                     105 files

果然可以看到controller出现在前面

而正常的环境下都是

Archive:  report.jar.original
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  04-27-2018 19:52   META-INF/
      376  04-27-2018 19:52   META-INF/MANIFEST.MF
        0  04-27-2018 19:52   j2cache/
        0  04-27-2018 19:52   com/
        0  04-27-2018 19:52   com/f6car/
        0  04-27-2018 19:52   com/f6car/report/
        0  04-27-2018 19:52   com/f6car/report/config/
        0  04-27-2018 19:52   com/f6car/report/web/
        0  04-27-2018 19:52   com/f6car/report/web/converter/
        0  04-27-2018 19:52   com/f6car/report/web/shiro/
        0  04-27-2018 19:52   com/f6car/report/web/json/
        0  04-27-2018 19:52   com/f6car/report/web/interceptor/
        0  04-27-2018 19:52   com/f6car/report/controller/
        0  04-27-2018 19:52   com/f6car/report/controller/saPerformance/
        0  04-27-2018 19:52   com/f6car/report/controller/item/
        0  04-27-2018 19:52   com/f6car/report/controller/base/
        0  04-27-2018 19:52   com/f6car/report/controller/custom/
        0  04-27-2018 19:52   com/f6car/report/controller/maintain/
        0  04-27-2018 19:52   com/f6car/report/controller/part/
        0  04-27-2018 19:52   com/f6car/report/controller/finance/
        0  04-27-2018 19:52   com/f6car/report/callback/
        0  04-27-2018 19:52   com/f6car/report/jwt/
      991  04-27-2018 19:52   application-dev.properties
     7683  04-27-2018 19:52   logback-spring.xml
     1796  04-27-2018 19:52   j2cache/j2cache-prod-trial.properties
     1748  04-27-2018 19:52   j2cache/j2cache-re.properties
     1784  04-27-2018 19:52   j2cache/j2cache-prod.properties
     1749  04-27-2018 19:52   j2cache/application-unit-test.properties
     1977  04-27-2018 19:52   j2cache/j2cache-dev.properties
     1765  04-27-2018 19:52   j2cache/j2cache-local-test.properties
     1204  04-27-2018 19:52   application-local-test.properties
     5242  04-27-2018 19:52   ehcache.xml
     1093  04-27-2018 19:52   application-unit-test.properties
     1530  04-27-2018 19:52   banner.txt
     1064  04-27-2018 19:52   com/f6car/report/config/ResourceHandlerConfig.class
     1688  04-27-2018 19:52   com/f6car/report/config/CacheConfig.class
      367  04-27-2018 19:52   com/f6car/report/config/AbstractDataSourceConfig.class
      771  04-27-2018 19:52   com/f6car/report/config/ResourceHandler.class
     2468  04-27-2018 19:52   com/f6car/report/config/ReportStatisticConfig.class
     2270  04-27-2018 19:52   com/f6car/report/config/SSO.class
      895  04-27-2018 19:52   com/f6car/report/config/DataSourceConfig2.class
      804  04-27-2018 19:52   com/f6car/report/config/DataSourceConfig1.class
     2376  04-27-2018 19:52   com/f6car/report/config/SwaggerConfig.class
      689  04-27-2018 19:52   com/f6car/report/config/AfterCommitConfig.class
    13698  04-27-2018 19:52   com/f6car/report/config/WebMvcConfigurer.class
     4472  04-27-2018 19:52   com/f6car/report/config/ShiroConfig.class
     3750  04-27-2018 19:52   com/f6car/report/config/WebMvcConfigurer$1.class
      599  04-27-2018 19:52   com/f6car/report/config/SSOConfig.class
     2147  04-27-2018 19:52   com/f6car/report/web/converter/NormalWorkBookHandler.class
     9165  04-27-2018 19:52   com/f6car/report/web/converter/ExcelHttpMessageConverter.class
     1440  04-27-2018 19:52   com/f6car/report/web/converter/MapWorkBookHandler$1.class
     2852  04-27-2018 19:52   com/f6car/report/web/converter/MapWorkBookHandler.class
     2137  04-27-2018 19:52   com/f6car/report/web/converter/AbstractWorkBookHandler$1.class
      467  04-27-2018 19:52   com/f6car/report/web/converter/WorkBookHandler.class
     6726  04-27-2018 19:52   com/f6car/report/web/converter/AbstractWorkBookHandler.class
     2167  04-27-2018 19:52   com/f6car/report/web/shiro/ReturnUrlParamFilter.class
      751  04-27-2018 19:52   com/f6car/report/web/json/BigIntegerValueFilter.class
     4335  04-27-2018 19:52   com/f6car/report/web/interceptor/KissoShiroInterceptor.class
     3245  04-27-2018 19:52   com/f6car/report/web/interceptor/CSRFInterceptor.class
      251  04-27-2018 19:52   com/f6car/report/web/interceptor/ExcludePathable.class
      735  04-27-2018 19:52   com/f6car/report/web/interceptor/SSOInterceptor.class
      682  04-27-2018 19:52   com/f6car/report/web/interceptor/AbstractExcludeInterceptor.class
     5019  04-27-2018 19:52   com/f6car/report/web/interceptor/JWTTokenAuthInterceptor.class
     4080  04-27-2018 19:52   com/f6car/report/web/interceptor/CleanInterceptor.class
     2215  04-27-2018 19:52   com/f6car/report/controller/saPerformance/SaCashPerformanceController.class
    10714  04-27-2018 19:52   com/f6car/report/controller/item/ItemController.class
     5647  04-27-2018 19:52   com/f6car/report/controller/base/AuthController.class
     1181  04-27-2018 19:52   com/f6car/report/controller/base/DisableSwaggerUiController.class
     3150  04-27-2018 19:52   com/f6car/report/controller/base/BaseController$2.class
     1413  04-27-2018 19:52   com/f6car/report/controller/base/SystemController.class
    16088  04-27-2018 19:52   com/f6car/report/controller/base/BaseController.class
     1834  04-27-2018 19:52   com/f6car/report/controller/base/BaseController$3.class
     1433  04-27-2018 19:52   com/f6car/report/controller/base/BaseController$1.class
     2612  04-27-2018 19:52   com/f6car/report/controller/custom/DailyCustomReportController.class
     5992  04-27-2018 19:52   com/f6car/report/controller/maintain/MaintainBusinessController.class
    11801  04-27-2018 19:52   com/f6car/report/controller/part/PartController.class
     4139  04-27-2018 19:52   com/f6car/report/controller/finance/FinanceSummaryController.class
    16621  04-27-2018 19:52   com/f6car/report/controller/finance/FinanceDetailController.class
     5080  04-27-2018 19:52   com/f6car/report/callback/CustomCallback.class
     1761  04-27-2018 19:52   com/f6car/report/jwt/JwtConfig.class
      809  04-27-2018 19:52   com/f6car/report/jwt/AccessJwtToken.class
     2026  04-27-2018 19:52   com/f6car/report/jwt/RawAccessJwtToken.class
     1766  04-27-2018 19:52   com/f6car/report/jwt/UserContext.class
      343  04-27-2018 19:52   com/f6car/report/jwt/TokenVerifier.class
     2429  04-27-2018 19:52   com/f6car/report/jwt/RefreshToken.class
     3862  04-27-2018 19:52   com/f6car/report/jwt/JwtTokenFactory.class
     1532  04-27-2018 19:52   com/f6car/report/jwt/AlgTokenVerifier.class
     1249  04-27-2018 19:52   com/f6car/report/jwt/Scopes.class
     1409  04-27-2018 19:52   com/f6car/report/jwt/IssueTokenVerifier.class
      935  04-27-2018 19:52   com/f6car/report/jwt/BloomTokenVerifier.class
     1460  04-27-2018 19:52   com/f6car/report/jwt/DefaultTokenExtractor.class
      189  04-27-2018 19:52   com/f6car/report/jwt/TokenExtractor.class
      746  04-27-2018 19:52   com/f6car/report/jwt/JwtConfiguar.class
     1530  04-27-2018 19:52   com/f6car/report/ApplicationRefreshedListener.class
      910  04-27-2018 19:52   com/f6car/report/Application.class
     1859  04-27-2018 19:52   application-prod-trial.properties
     4692  04-27-2018 19:52   application.properties
     1196  04-27-2018 19:52   application-re.properties
     1506  04-27-2018 19:52   application-prod.properties
    32989  04-27-2018 19:52   META-INF/spring-configuration-metadata.json
        0  04-27-2018 19:52   META-INF/maven/
        0  04-27-2018 19:52   META-INF/maven/com.f6car.report/
        0  04-27-2018 19:52   META-INF/maven/com.f6car.report/report-web/
     6013  03-22-2018 18:37   META-INF/maven/com.f6car.report/report-web/pom.xml
      127  04-27-2018 19:52   META-INF/maven/com.f6car.report/report-web/pom.properties
---------                     -------
   272306                     105 files

看来问题就在于这里不同的环境打包的结果【顺序】出现了些许异常

我们来查看【中间省略N步骤】我们在该jenkins机器上执行对应的File.list

groovy:000> new File("/data/jenkins/workspace/f6-local-test-report-server/report-web/target/classes/com/f6car/report").list()
===> [controller, config, jwt, web, ApplicationRefreshedListener.class, Application.class, callback]
groovy:000> new File("/data/jenkins/workspace/f6-local-test-open-api/web/target/classes/com/f6car/openapi/").list()
===> [config, controller, web, jwt, callback, Application.class, converter]

看起来这个比较特殊导致

/**
 * Returns an array of strings naming the files and directories in the
 * directory denoted by this abstract pathname.
 *
 * <p> If this abstract pathname does not denote a directory, then this
 * method returns {@code null}.  Otherwise an array of strings is
 * returned, one for each file or directory in the directory.  Names
 * denoting the directory itself and the directory's parent directory are
 * not included in the result.  Each string is a file name rather than a
 * complete path.
 *
 * <p> There is no guarantee that the name strings in the resulting array
 * will appear in any specific order; they are not, in particular,
 * guaranteed to appear in alphabetical order.
 *
 * <p> Note that the {@link java.nio.file.Files} class defines the {@link
 * java.nio.file.Files#newDirectoryStream(Path) newDirectoryStream} method to
 * open a directory and iterate over the names of the files in the directory.
 * This may use less resources when working with very large directories, and
 * may be more responsive when working with remote directories.
 *
 * @return  An array of strings naming the files and directories in the
 *          directory denoted by this abstract pathname.  The array will be
 *          empty if the directory is empty.  Returns {@code null} if
 *          this abstract pathname does not denote a directory, or if an
 *          I/O error occurs.
 *
 * @throws  SecurityException
 *          If a security manager exists and its {@link
 *          SecurityManager#checkRead(String)} method denies read access to
 *          the directory
 */
public String[] list() {
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkRead(path);
    }
    return fs.list(this);
}

很明显注释也说明确实没有顺序的保证!

解决

  1. 修改dataSource依赖

    @Configuration(PRIMARY_DATA_SOURCE_NAME)
    @Primary
    @ConfigurationProperties("spring.datasource")
    public class DataSourceConfig1 extends AbstractDataSourceConfig {
    }

     

  2. 这样自然会第一个初始化成功而不至于出现循环依赖!这种改法推荐【当时设计的目的是为了可以自定义设置一些没有暴露出来的参数看来这种有概率导致循环依赖】

  3. 增加参数 由于DataSourceInitializer只有在init参数为true才会执行我们【我们不需要执行sql脚本】自然可以将该参数改为false

  4. spring.datasource.initialize=false

     

 

© 著作权归作者所有

共有 人打赏支持
Mr_Qi

Mr_Qi

粉丝 279
博文 359
码字总数 369228
作品 0
南京
程序员
私信 提问
加载中

评论(3)

Mr_Qi
Mr_Qi

引用来自“芋道源码”的评论

哈哈哈。我们碰到过

坑不坑��
芋道源码
芋道源码
哈哈哈。我们碰到过
彪付_3个字符
能定位到问题还是很吊的
【第三章】 DI 之 3.2 循环依赖 ——跟我学spring3

3.2.1 什么是循环依赖 循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA,则它们最终反映为一个环。此处不是...

azikaxu
2015/04/15
0
0
又一个centos文件顺序导致的问题

背景 新的centos似乎对于文件顺序做了特别的优化 和文件顺序出现的问题确实多了不少 centos7导致的spring循环依赖【实际上和这个问题不一样 不过由此衍生出的问题】 某应用放在新的系统开始报...

Mr_Qi
08/15
0
0
spring循环依赖的三种方式

1.构造器参数循环依赖 对象间在构造函数中有相互依赖,通过构造函数注入 constructor-arg 启动是会报循环依赖错误 2.setter方式单例,默认方式 spring先通过无参构造方法创建bean,然后通过s...

素雷
08/08
0
0
Spring基础系列-Spring事务不生效的问题与循环依赖问题

原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9476550.html 一、提出问题   不知道你是否遇到过这样的情况,在ssm框架中开发web引用,或者使用springboot开...

唯一浩哥
08/14
0
0
Spring是怎么解决循环依赖的

什么是循环依赖? 循环依赖其实就是循环引用,也就是两个或则两个以上的bean互相持有对方,最终形成闭环。比如A依赖于B,B依赖于C,C又依赖于A。如下图: 注意,这里不是函数的循环调用,是对...

Jack1991
04/27
0
0

没有更多内容

加载失败,请刷新页面

加载更多

十月开源项目推荐:专为 Python 初学者准备的 IDE 你用过吗?

每月新增开源项目。顾名思义,每月更新一期。我们会从社区上个月新收录的开源项目中,挑选出有价值的、有用的、优秀的、或者好玩的开源项目来和大家分享。数量不多,但我们力求推荐的都是精品...

编辑部的故事
12分钟前
6
0
Java/Android 获取文件夹的文件列表(file.listFiles())并按名称排序,中文优先

排序规则 因为是中国人,习惯性看中文文件夹放前面比较顺眼,所以在别人博客(https://blog.csdn.net/da_caoyuan/article/details/56664673)的基础上,加上了自己的排序规则。 默认排序规则...

她叫我小渝
12分钟前
0
0
RabbitMQ通过shovel插件迁移数据

前言 生产环境中会遇到RabbitMQ数据迁移的场景,例如:切换云服务厂商、不同Region之间数据迁移、新搭建RabbitMQ实例,数据需要同步至新的RabbitMQ实例。 前提条件: 源RabbitMQ实例打开了s...

中间件小哥
16分钟前
0
0
kubernetes 环境搭建

kubernetes 简介:Kubernetes是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful)。 点击此处查看官网详情。...

MrPei
30分钟前
1
0
关于scala macro的example

http://www.bbartosz.com/blog/2016/09/24/fun-with-scalameta-examples-part1/

Littlebox
32分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部