maven引入多个spring jar包中存在同名文件的问题

项目打包后执行报错:
Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespacehttp://www.springframework.org/schema/tx

直接执行main类没问题, 使用mvn clean package 打包后 执行 java -jar
xxx.jar 报上述错误。

spring配置文件中namespace定义:

<?xml version="1.0" encoding="UTF-8" ?>
<beans default-autowire="byName"
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
classpath:/org/springframework/beans/factory/xml/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
classpath:/org/springframework/context/config/spring-context-3.1.xsd
http://www.springframework.org/schema/tx
classpath:/org/springframework/transaction/config/spring-tx-3.1.xsd
">

pom 打包插件配置, 采用maven-assembly-plugin:

<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<!-- 添加上版本,如果去掉此version,则jar包里会出现重复的xml -->
<version>2.2-beta-5</version>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.hunantv.bigdata.mls.main.Main</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>assembly</goal>
</goals>
</execution>
</executions>
</plugin>

namespace中所有路径都能访问, 并且打包后确认各包都已经被包含,涉及的类都存在。

原因:
with this error message in IntelliJ IDEA

if you have multiple jars with many:
spring.handlers
spring.schemas

then they overwrite each other and the last loaded file win.
Workaround:
copy all settings from spring.handlers and spring.schemas to the same files in the
other jar so you have a combined content. then the last file win after loading and
all settings are there.

spring多个框架都包含有这两个同名的文件spring.handlers,spring.schemas,加载的时候,后面加载的文件替换了前面的文件,而不是将内容合并。https://github.com/gwtproject/gwt/issues/5727

解决办法:

需要将所有spring.handlers,spring.schemas文件内容进行合并。 
第一种方式是手动将所有文件的内容合并到一个文件中。但需要去找到所有的文件,且不一定生效(自己建立合并文件没有生效)。
第二种方式是通过maven-shade-plugin 来打包。

maven-shade-plugin 配置:

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>:</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.hunantv.bigdata.mls.main.Main</mainClass>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.handlers</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.schemas</resource>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

替换maven-assembly-plugin后, 执行mvn clean package, 报错:

[WARNING] Error injecting: org.apache.maven.shared.dependency.graph.internal.Maven3DependencyGraphBuilder
java.lang.NoClassDefFoundError: org/sonatype/aether/graph/DependencyNode
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2531)
at java.lang.Class.getDeclaredMethods(Class.java:1855)
at com.google.inject.spi.InjectionPoint.getInjectionPoints(InjectionPoint.java:674)
at com.google.inject.spi.InjectionPoint.forInstanceMethodsAndFields(InjectionPoint.java:366)
at com.google.inject.internal.ConstructorBindingImpl.getInternalDependencies(ConstructorBindingImpl.java:165)
at com.google.inject.internal.InjectorImpl.getInternalDependencies(InjectorImpl.java:609)
at com.google.inject.internal.InjectorImpl.cleanup(InjectorImpl.java:565)
at com.google.inject.internal.InjectorImpl.initializeJitBinding(InjectorImpl.java:551)
at com.google.inject.internal.InjectorImpl.createJustInTimeBinding(InjectorImpl.java:865)
at com.google.inject.internal.InjectorImpl.createJustInTimeBindingRecursive(InjectorImpl.java:790)
at com.google.inject.internal.InjectorImpl.getJustInTimeBinding(InjectorImpl.java:278)
at com.google.inject.internal.InjectorImpl.getBindingOrThrow(InjectorImpl.java:210)
at com.google.inject.internal.InjectorImpl.getProviderOrThrow(InjectorImpl.java:986)
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1019)
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:982)
at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1032)
at org.eclipse.sisu.space.AbstractDeferredClass.get(AbstractDeferredClass.java:48)
at com.google.inject.internal.ProviderInternalFactory.provision(ProviderInternalFactory.java:86)
at com.google.inject.internal.InternalFactoryToInitializableAdapter.provision(InternalFactoryToInitializableAdapter.java:55)
at com.google.inject.internal.ProviderInternalFactory$1.call(ProviderInternalFactory.java:70)
at com.google.inject.internal.ProvisionListenerStackCallback$Provision.provision(ProvisionListenerStackCallback.java:100)
at org.eclipse.sisu.plexus.PlexusLifecycleManager.onProvision(PlexusLifecycleManager.java:133)
at com.google.inject.internal.ProvisionListenerStackCallback$Provision.provision(ProvisionListenerStackCallback.java:109)
at com.google.inject.internal.ProvisionListenerStackCallback.provision(ProvisionListenerStackCallback.java:55)
at com.google.inject.internal.ProviderInternalFactory.circularGet(ProviderInternalFactory.java:68)
at com.google.inject.internal.InternalFactoryToInitializableAdapter.get(InternalFactoryToInitializableAdapter.java:47)
at com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46)
at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1054)
at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
at com.google.inject.Scopes$1$1.get(Scopes.java:59)
at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:41)
at com.google.inject.internal.InjectorImpl$2$1.call(InjectorImpl.java:997)
at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1047)
at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:993)
at org.eclipse.sisu.inject.LazyBeanEntry.getValue(LazyBeanEntry.java:82)
at org.eclipse.sisu.plexus.LazyPlexusBean.getValue(LazyPlexusBean.java:51)
at org.codehaus.plexus.DefaultPlexusContainer.lookup(DefaultPlexusContainer.java:260)
at org.codehaus.plexus.DefaultPlexusContainer.lookup(DefaultPlexusContainer.java:240)
at org.apache.maven.shared.dependency.graph.internal.DefaultDependencyGraphBuilder.buildDependencyGraph(DefaultDependencyGraphBuilder.java:60)
at org.apache.maven.plugin.dependency.TreeMojo.execute(TreeMojo.java:202)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:133)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:108)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:76)
at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:116)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:361)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:155)
at org.apache.maven.cli.MavenCli.execute(MavenCli.java:584)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:213)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:157)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
Caused by: java.lang.ClassNotFoundException: org.sonatype.aether.graph.DependencyNode
at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:50)
at org.codehaus.plexus.classworlds.realm.ClassRealm.unsynchronizedLoadClass(ClassRealm.java:259)
at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:235)
at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:227)
... 62 more

该问题是由于maven 3中一些包进行了迁移,导致不兼容,在maven-shade-plugin 2.1版本中修复了。
参考:
https://cwiki.apache.org/confluence/display/MAVEN/AetherClassNotFound

将pom中maven-shade-plugin 版本改为2.1后。 问题解决。

mvn clean package 打包后,java -jar 运行无问题。

上一篇:Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析


下一篇:java基础-day16