背景
由于一些变化 公司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
首先分析一下出现错误的场景
- spring初始化controller 发觉依赖service
- spring初始化service发觉依赖dao
- spring初始化dao发觉依赖sqlSession
- spring初始化sqlSession发觉依赖dataSource
- spring初始化dataSource(见上方代码)
- 此时由于dataSource需要执行processor DataSourceInitializerPostProcessor
-
该processor会在dataSource初始化完成后调用init方法 实质上 就是
this.beanFactory.getBean(DataSourceInitializer.class);
-
上述代码可以看到需要初始化DataSourceInitializer 而该类的作用是用于dataSource初始化执行一些脚本
-
该类的方法如下使用
@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(); }
-
此时applicationContext.getBean(DataSource.class) 实质上会调用某个dataSource【如果有多个怎么办???】当存在多个的时候会选择含有primary的bean 对于本篇文章就是PRIMARY_DATA_SOURCE_NAME
- 那么如果当PRIMARY_DATA_SOURCE_NAME还在创建过程中就会出现此问题【在此处表现在sqlSession依赖PRIMARY_DATA_SOURCE_NAME】
那么为何在centos6上编译出现的jar没有此问题呢???
分析
从上述描述中我们可以看到当sqlSession依赖的dataSource导致出现此问题
那么出现了两个问题
- 为何其他服务迁移到新环境【新的jenkins编译】没有问题
- 为何该服务在以前环境编译没问题在新的环境出现了问题
首先解释第二个问题
我们看了上述的分析其实很容易将依赖循环打破===》
很简单 只要我们在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); }
很明显注释也说明确实没有顺序的保证!
解决
-
修改dataSource依赖
@Configuration(PRIMARY_DATA_SOURCE_NAME) @Primary @ConfigurationProperties("spring.datasource") public class DataSourceConfig1 extends AbstractDataSourceConfig { }
-
这样自然会第一个初始化成功而不至于出现循环依赖!这种改法推荐【当时设计的目的是为了可以自定义设置一些没有暴露出来的参数看来这种有概率导致循环依赖】
-
增加参数 由于DataSourceInitializer只有在init参数为true才会执行我们【我们不需要执行sql脚本】自然可以将该参数改为false
-
spring.datasource.initialize=false