class-path順序導致的問題

最近遇到兩個關於class-path順序導致的問題

問題1. application.properties重複的問題

業務應用會誤把application.properties打入二方包中,這樣在class-path會同時出現好幾個application.properties文件,Spring都是通過ClassLoader.getResource(「application.properties」)獲取其中的一個。 通過spring-boot啓動每次都能正確獲取到應用的application.properties,但是通過nest容器啓動之後就會讀取二方庫中的application.properties,爲什麼會有不一致的情況呢?

原來正常IDE啓動時會按照jvm,project,lib的順序作爲class-path,但nest容器在過濾class-path把順序打亂了,詳見: https://github.com/alipay/sofa-ark/issues/236

ClassLoader在查找資源的時候也是按照class-path的順序讀取,讀到第一個就返回。

問題2. mybatis導致的MalformedParameterizedTypeException

通過spring-boot IDE和java-jar 不會報錯,通過容器 ide方式啓動也不會報錯,但是通過容器java -jar方式啓動會報告如下錯誤:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'assetsSqlSessionFactory' defined in URL [jar:file:/work/dist/branch/xxx/apps/inner-test/tesla-loan/provider/target/tesla-loan-provider-1.0.0.jar!/SOFA-ARK/biz/tesla-loan-provider-1.0.0.jar.original!/spring/spring-database.xml]: Initialization of bean failed; nested exception is java.lang.reflect.MalformedParameterizedTypeException
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
	... 63 more
Caused by: java.lang.reflect.MalformedParameterizedTypeException
	at sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl.validateConstructorArguments(ParameterizedTypeImpl.java:58)
	at sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl.<init>(ParameterizedTypeImpl.java:51)
	at sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl.make(ParameterizedTypeImpl.java:92)
	at sun.reflect.generics.factory.CoreReflectionFactory.makeParameterizedType(CoreReflectionFactory.java:105)
	at sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:140)
	at sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49)
	at sun.reflect.generics.visitor.Reifier.visitArrayTypeSignature(Reifier.java:159)
	at sun.reflect.generics.tree.ArrayTypeSignature.accept(ArrayTypeSignature.java:42)
	at sun.reflect.generics.repository.ConstructorRepository.getParameterTypes(ConstructorRepository.java:94)
	at java.lang.reflect.Executable.getGenericParameterTypes(Executable.java:283)
	at java.lang.reflect.Method.getGenericParameterTypes(Method.java:283)
	at java.beans.FeatureDescriptor.getParameterTypes(FeatureDescriptor.java:387)
	at java.beans.MethodDescriptor.setMethod(MethodDescriptor.java:116)
	at java.beans.MethodDescriptor.<init>(MethodDescriptor.java:72)
	at java.beans.MethodDescriptor.<init>(MethodDescriptor.java:56)
	at java.beans.Introspector.getTargetMethodInfo(Introspector.java:1205)
	at java.beans.Introspector.getBeanInfo(Introspector.java:426)
	at java.beans.Introspector.getBeanInfo(Introspector.java:173)
	at org.springframework.beans.CachedIntrospectionResults.<init>(CachedIntrospectionResults.java:279)

網上搜索 MalformedParameterizedTypeException 能找到大部分都是mybatis衝突導致的,檢查依賴關係確實引入了兩個mybatis,原因是因爲我們內部定義了一個mybatis(groupId=com.xxx),業務依賴的一個api依賴了開源版本的mybatis(groupId=org.apache)
在這裏插入圖片描述

但是爲什麼只有通過容器java -jar 的方式纔會報錯,其他方式都不會報錯呢?

原因還是和class-path順序相關,通過容器打包之後的classpath順序,mybatis-3.0.5剛好在mybatis-3.5.1之前,導致加載到了錯誤的版本,而另外三種方式都是mybatis-3.5.1在mybatis-3.0.5之前,所以錯誤沒有暴露出來。