最近遇到两个关于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之前,所以错误没有暴露出来。