Spring在存在xml配置文件的情况下找不到bean。

86

我正在尝试制作Spring中的第一个bean,但在加载上下文时遇到问题。 我有一个bean的配置XML文件在src/main/resources中。

我收到以下IOException:

Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException:从类路径资源[src/main/resources/beans.xml]解析XML文档时出现IOException; 嵌套异常是

java.io.FileNotFoundException: 因为不存在,所以无法打开类路径资源[src/main/resources/beans.xml]

但我不理解,因为我执行了以下代码测试:

File f = new File("src/main/resources/beans.xml");
System.out.println("Exist test: " + f.exists());

这让我得到了true! resources 在类路径中。有什么问题吗?


你如何加载上下文? - Aleksandr M
25个回答

190

谢谢,但那不是解决方案。我找到了为什么它对我不起作用的原因。

因为我已经声明了:

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

我原本认为,当beans.xml文件在项目根目录下时,会引用根目录。 然后我把配置文件放到了src/main/resources下,并将初始化改为:

ApplicationContext context = new ClassPathXmlApplicationContext("src/main/resources/beans.xml");

仍然是一个IO异常。

然后文件被留在src/main/resources/,但我将声明更改为:

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

问题已经解决了-希望对某些人有帮助。

编辑:

由于我得到了很多人为这个解决方案点赞,并在几年前作为学生第一次接触Spring,所以我想简要解释一下它为什么有效。

当项目被编译和打包时,项目中的所有文件和子目录从'src/main/java'进入打包的jar的根目录(我们要创建的工件)。同样的规则适用于'src/main/resources'。

这是许多工具(如maven或sbt)在构建项目过程中遵守的约定(请注意:默认配置!)。当代码(来自帖子)处于运行模式时,它找不到类似“src/main/resources/beans.xml”的内容,因为beans.xml在jar的根目录中(复制到/beans.xml/jar/ear/war中创建的)。

当使用ClassPathXmlApplicationContext时,这种情况下beans xml定义的正确位置声明是“/beans.xml”,因为这是它在jar中和后来在classpath中所属的路径。

可以通过使用存档程序(例如rar)解压缩jar并查看其具有目录结构的内容来进行验证。

我建议阅读与classpath有关的文章作为补充。


我看不出 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); 之间的区别。 - Florian F
1
@FlorianF 没有区别。区别在于文件放置的位置,这在帖子中有所描述。 - dawrutowicz
3
我看到你将 beans.xml 更改为 src/main/resources/beans.xml,然后又到了 beans.xml。谢谢。 - Florian F
你不应该在类路径上放置src文件。当你构建项目时,这些资源将被打包到其他地方。 - OrangeDog
1
嗨,如果我们从命令行运行这个JAR文件,它似乎无法像预期的那样工作(在Eclipse上运行良好)。 - Dhruv Singhal

71

试试这个:

new ClassPathXmlApplicationContext("file:src/main/resources/beans.xml");

file: 前缀指向文件系统资源,而不是类路径。

文件路径可以是相对或系统路径 (/home/user/Work/src...)


1
嗯,最好将资源保留在类路径中而不是硬编码,但还是谢谢。那时我没有使用过 CP 的经验 :-) - dawrutowicz
1
最好使用FileSystemXmlApplicationContext来处理文件。 - romnempire
我遇到了类似的问题,这个解决方案对我有用。 - Avdhut
1
这是答案 - Supun Sandaruwan
终于成功了!!! - Deepak Kumar

24

我也遇到了类似的问题,但是原因稍有不同。在这里分享一下,希望能够帮助到其他人。

我的文件位置

beans.xml文件

我如何使用

ClassPathXmlApplicationContext("beans.xml");

有两个解决方案

  1. 将beans.xml文件移出包并放置于默认包中。
  2. 在使用时指定包名,例如:

ClassPathXmlApplicationContext("com/mypackage/beans.xml");


1
说实话,"com/mypackage/beans.xml" 的引用路径和 "/com/mypackage/beans.xml" 是一样的,因为 "com/mypackage/beans.xml" 是一个相关路径,使用 "/"(根目录)来构建绝对路径。 - dawrutowicz

9
这是因为applicationContext.xml或任何_filename.XML未放置在正确的路径下。
故障排除步骤:
1:将XML文件添加到资源文件夹中。
2:如果您没有资源文件夹,请通过右键单击项目新建>源文件夹进行创建,将其命名为“resource”,并将您的XML文件放在其中。

9

src/main/resources是一个源代码目录,你不应该直接引用它。当你构建/打包项目时,内容将被复制到正确的类路径位置。然后你应该像这样加载它:

new ClassPathXmlApplicationContext("beans.xml")

Or like this

new GenericXmlApplicationContext("classpath:beans.xml");

使用 new ClassPathXmlApplicationContext("beans.xml") 无法工作,但是使用 new GenericXmlApplicationContext("classpath:beans.xml"); 可以在 Java 命令行中工作。 - Martín Alcubierre

5

使用它

ApplicationContext context = new FileSystemXmlApplicationContext("Beans.xml");
(注:该段文本已经是中文,无需翻译)

3

嗨...抱歉有点晚问,但您能否详细说明如何将输入流转换为应用程序上下文?我目前正在尝试运行一个可执行的jar文件,但它说无法加载bean xml,因为它不存在。 - Dhruv Singhal

3

您已经查看了src目录。xml文件确实存在于那里。但请查看class或bin/build目录,其中设置了所有输出类。我怀疑您只需要使用resources/beans.xml路径。


3
请注意,第一个应用程序上下文是作为web.xml的一部分加载的;如下所述。
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>META-INF/spring/applicationContext.xml</param-value>
</context-param>

<servlet>
    <servlet-name>myOwn-controller</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>META-INF/spring/applicationContext.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

然而下面的代码也会尝试创建另一个applicationContext。

private static final ApplicationContext context = 
               new ClassPathXmlApplicationContext("beans.xml");

请查看这里,了解beans.xmlapplicationContext.xml之间的区别。

如果在<META-INF/spring/>下声明了appliationContext.xml并使用了<import resource="beans.xml"/>,那么appliationContext.xml将会加载与其位于同一位置META-INF/spring下的beans.xml

而在代码中,如果声明如下:

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

这是查找位于WEB-INF/classes或在eclipse的src/main/resources中的beans.xml文件。
如果您已将beans.xml添加到src/main/resources,则在创建WAR时它可能会被放置在WEB-INF/classes中。因此,总共会查找两个文件。
我通过在applicationContext.xml导入时添加类路径查找来解决了这个问题,如下所示:
<import resource="classpath*:beans.xml" />

在Java代码中,我已经删除了ClassPathXmlApplicationContext("beans.xml")这一行,这样只会加载一个ApplicationContext。

2
在Spring中,所有的源代码文件都在src/main/java目录下。同样地,资源文件通常保存在src/main/resources目录下。因此,请将您的Spring配置文件放在资源文件夹中。
确保您的文件在src/main/resources目录下有ClassPath条目。
在.classpath文件中检查以下两行。如果缺少,请添加它们。
<classpathentry path="src/main/java" kind="src"/>
<classpathentry path="src/main/resources" kind="src" />

所以,如果你已经准备就绪,以下代码应该能够正常工作。
ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring-Module.xml");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接