ClassNotFoundException的:org.springframework.context.support.ClassPathXmlApplicationContext

问题描述:

我工作的一个独立的应用程序构建与行家,我在使用一个lib文件夹添加依赖目标罐子 maven-dependency-pluginmaven-assembly-plugin该应用程序在eclipse中运行良好,没有问题,但是当试图从命令行运行生成的jar文件时,出现以下异常:ClassNotFoundException的:org.springframework.context.support.ClassPathXmlApplicationContext

Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/context/support/ClassPathXmlApplicationContext 
     at com.spring.sample.MainClass.main(MainClass.java:11) 
Caused by: java.lang.ClassNotFoundException: org.springframework.context.support.ClassPathXmlApplicationContext 
     at java.net.URLClassLoader$1.run(Unknown Source) 
     at java.security.AccessController.doPrivileged(Native Method) 
     at java.net.URLClassLoader.findClass(Unknown Source) 
     at java.lang.ClassLoader.loadClass(Unknown Source) 
     at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) 
     at java.lang.ClassLoader.loadClass(Unknown Source) 
     ... 1 more 

我看着生成的JAR lib文件夹里面,我发现弹簧上下文support.jar已经在那里,所以我想知道为什么我收到这样的例外。

这里是我的Maven构建配置

<build> 

    <resources> 

      <resource> 
       <directory>src/main/resources</directory> 
       <filtering>true</filtering> 
      </resource> 

    </resources> 

     <plugins> 


      <plugin> 
      <groupId>org.apache.maven.plugins</groupId> 
      <artifactId>maven-dependency-plugin</artifactId> 
      <executions> 
       <execution> 
        <id>copy-dependencies</id> 
        <phase>prepare-package</phase> 
        <goals> 
         <goal>copy-dependencies</goal> 
        </goals> 
        <configuration> 
         <outputDirectory>${project.build.directory}/classes/lib</outputDirectory>      
         <overWriteReleases>false</overWriteReleases> 
         <overWriteSnapshots>false</overWriteSnapshots> 
         <overWriteIfNewer>true</overWriteIfNewer> 
        </configuration> 
       </execution> 
      </executions> 
     </plugin> 

     <plugin> 
      <groupId>org.apache.maven.plugins</groupId> 
      <artifactId>maven-jar-plugin</artifactId> 
      <configuration> 
       <archive> 
        <manifest> 
         <addClasspath>true</addClasspath> 
         <classpathPrefix>lib/</classpathPrefix> 
         <mainClass>com.myapp.MainClass</mainClass> 
        </manifest> 
       </archive> 
      </configuration> 
     </plugin> 


      <plugin> 
       <groupId>org.apache.maven.plugins</groupId> 
       <artifactId>maven-compiler-plugin</artifactId> 
       <configuration> 
        <source>1.6</source> 
        <target>1.6</target> 
       </configuration> 
      </plugin> 

      <plugin> 
       <groupId>org.apache.maven.plugins</groupId> 
       <artifactId>maven-dependency-plugin</artifactId> 
       <executions> 
        <execution> 
         <id>install</id> 
         <phase>install</phase> 
         <goals> 
          <goal>sources</goal> 
         </goals> 
        </execution> 
       </executions> 
      </plugin> 

      <plugin> 
       <groupId>org.apache.maven.plugins</groupId> 
       <artifactId>maven-resources-plugin</artifactId> 
       <version>2.5</version> 
       <configuration> 
       <encoding>UTF-8</encoding> 
       </configuration> 
      </plugin> 


      <plugin> 
       <groupId>org.apache.maven.plugins</groupId> 
       <artifactId>maven-assembly-plugin</artifactId> 
        <executions> 
         <execution> 
          <id>create-my-bundle</id> 
           <phase>package</phase> 
            <goals> 
             <goal>single</goal> 
            </goals> 
         <configuration> 
          <descriptorRefs> 
          <descriptorRef>jar-with-dependencies</descriptorRef> 
          </descriptorRefs> 

         </configuration> 
         </execution> 
        </executions> 

      </plugin> 


     </plugins> 
    </build> 

你已经有了一堆POM,你正在建造两个罐子。

其中一个瓶子是通过首先将您的依赖关系复制到target/classes/lib - 一个有问题的做法开始的 - 并让jar插件的默认执行构建它的普通jar来构建的。这个jar包含所有你的代码,就像一个普通的jar文件一样,但是它里面的所有依赖jar也在/lib之间。它还有一个清单,指定Main-ClassClass-Path列出相对路径为lib/...jar的所有需要​​的罐子。听起来这是你试图运行的那个。它找不到需要的类的原因是,独立Java应用程序的类路径是文件系统上包含类文件的文件夹或jar文件的列表。换句话说,它不会在另一个jar文件里面找到jar文件,这就是你所拥有的。为了达到这个目标,你需要一个lib目录,紧邻你的jar文件,它具有所有的依赖关系。这是什么导致你现在的问题。

另一个jar由程序集插件构建。由于你之前的依赖插件的滑稽动作,这个应该在/lib中也有所有的依赖关系罐,我已经解释过它不会完成任何事情,但是由于描述符是如何工作的,它也会被提取所有的罐子,并把他们的所有课程和你自己的课程一起放到你的罐子里。如果你要运行这个jar,你可能会超过ClassNotFoundException,但是像这样的“fat jars”存在众所周知的问题,这意味着你不应该这样做,除非你有一些非常有说服力的理由。一个这样的问题,在以下问题描述:

Maven and Spring = Unable to create application context: Unable to locate Spring NamespaceHandler

+0

感谢这样宝贵的答案,所以我从它到目前为止得到的是,maven无法从jar中加载依赖关系,而是从外部文件夹中文件系统,为了做到这一点,我需要使用这个库http://one-jar.sourceforge.net/? – 2011-12-24 12:53:36

+0

并且为了清楚所有内容,在文件系统中收集外部lib文件夹中的所有依赖项所需的最低配置是多少。 – 2011-12-24 12:54:41

+0

这不是Maven加载依赖关系。这是Java。 Java总是这样工作。 One-JAR是从一个jar中打包和运行应用程序的一种方式。至于你的第二个评论,maven assembly插件会做到这一点。您只需编写一个描述符,将所有编译范围的依赖关系放入一个'lib'文件夹中。请参见[dependencySet](http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html#class_dependencySet)。 – 2011-12-24 17:44:17

类位于弹簧context.jar。在pom.xml中添加该依赖项。

+0

不,这是在已经加入弹簧上下文support.jar http://static.springsource.org/spring/docs/2.5.x /api/org/springframework/context/support/ClassPathXmlApplicationContext.html – 2011-12-24 02:50:07