at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.detectValidationMode(XmlBeanDefinitionReader.java:418)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.getValidationModeForResource(XmlBeanDefinitionReader.java:400)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:360)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:313)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:290)
at org.springframework.beans.factory.xml.XmlBeanFactory.<init>(XmlBeanFactory.java:73)
at org.springframework.beans.factory.xml.XmlBeanFactory.<init>(XmlBeanFactory.java:61)
at com.spring.unit1.TestMain.main(TestMain.java:31)
Exception in thread "main" java.lang.NullPointerException
at com.spring.unit1.TestMain.main(TestMain.java:40)
今天开始正式学习Spring,从《Spring in Action》开始,虽然版本老了一些,但是关键是思想,在做第一个练习的时候,原书中代码如下:
BeanFactory factory = new XmlBeanFactory(new FileInputStream("hello.xml"));
可是在2.0以后的版本中,XmlBeanFactory已经被修改;查阅了API发现构造方法的参数修改为Resource类型
查看了一下InputStreamResource 就是Resource接口的实现类;
于是:
File file = new File("D:/eclipse/workSpace/aSpringDemo/src/hello.xml");
InputStream is = new FileInputStream(file);
InputStreamResource isr = new InputStreamResource(is);
bf = new XmlBeanFactory(isr);
但是却出了上边的异常;
查看源码发现:
reader.loadBeanDefinitions(resource);方法会调用如下代码:
protected int detectValidationMode(Resource resource)
{
InputStream inputStream;
IOException ex;
if(resource.isOpen())
throw new BeanDefinitionStoreException("Passed-in Resource [" + resource + "] contains an open stream: " + "cannot determine validation mode automatically. Either pass in a Resource " + "that is able to create fresh streams, or explicitly specify the validationMode " + "on your XmlBeanDefinitionReader instance.");
再次查看InputStreamResource API:
implementation for a given InputStream. Should only be used if no specific Resource implementation is applicable. In particular, prefer or any of the file-based Resource implementations where possible.
In contrast to other Resource implementations, this is a descriptor for an already opened resource - therefore returning "true" from isOpen()
. Do not use it if you need to keep the resource descriptor somewhere, or if you need to read a stream multiple times.
显然
public boolean isOpen()
{
return true;
}
于是,使用其他Resource实现类替换比如FileSystemResource,一切OK
例:
File file = new File("F:/java web2.0/javawebProject/SpringApp/src/spring-beans.xml");
FileSystemResource fsr = new FileSystemResource(file);
XmlBeanFactory factory = new XmlBeanFactory(fsr);
在API中,关于InputStreamResource有这样一段描述:它只有在没有其他合适的Resource实现时才使用。而且,只要有可能就尽量使用ByteArrayResource或者其他基于文件的Resource实现。
与其他Resource实现不同的是,这是个 已经 打开资源的描述符-因此isOpen()方法返回true。如果你需要在其他位置保持这个资源的描述符或者多次读取一个流,请不要使用它。