众所周知,spring是Java中一个非常非常重要的框架,主要提供了依赖注入DI,和切面编程AOP。我多年前做过一段时间的Java,不过那时候项目中没有用Spring,所以一直也没有特别注意,最近看了一下spring的作用,觉得它提供的功能非常好,所以觉得需要多学习一下。
首先从网上下载spring4.x的一系列包,我下载了带source的包,方便了解spring的内部流程。
在下载了Spring4.0.4之后,写了一个简单的DI测试,不过却在运行的时候报错了,错误信息如下:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
at org.springframework.context.support.AbstractApplicationContext.<init>(AbstractApplicationContext.java:153)
at org.springframework.context.support.AbstractApplicationContext.<init>(AbstractApplicationContext.java:217)
at org.springframework.context.support.AbstractRefreshableApplicationContext.<init>(AbstractRefreshableApplicationContext.java:88)
at org.springframework.context.support.AbstractRefreshableConfigApplicationContext.<init>(AbstractRefreshableConfigApplicationContext.java:58)
at org.springframework.context.support.AbstractXmlApplicationContext.<init>(AbstractXmlApplicationContext.java:61)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:136)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at DI.knight.test.main(test.java:10)
这个错误,是因为缺少commons-logging库,从网上下载了commons-logging-1.1.jar,导入到项目之后,此错误消失
再次运行之后,还是报错,这次报的是xml文件没有找到,错误信息如下:
Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [xml/BraveKnight.xml]; nested exception is java.io.FileNotFoundException: class path resource [xml/BraveKnight.xml] cannot be opened because it does not exist
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:343)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:303)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:180)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:216)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:187)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:251)
at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:127)
at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:93)
at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:129)
at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:540)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:454)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at DI.knight.test.main(test.java:11)
这个其实是因为spring解析XML路径的问题,如果使用FileSystemXmlApplicationContext,就使用系统的文件路径,比如("xml/bean.xml"),bean.xml在xml路径下面。如果使用ClassPathXmlApplicationContext,就需要使用xml所在的package目录,比如("com/test/bean.xml"),bean.xml在com.test包下面。
再运行,其实还是报了一个错误,这个错误,我google了多次,都没有找到解决方案,其实是一个自己的笔误导致的,当然主要还是对spring的报错不太了解。错误是这样的:
Caused by: org.xml.sax.SAXParseException: Element type "bean" must be followed by either attribute specifications, ">" or "/>".
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.seekCloseOfStartTag(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
其实原因非常简单,是因为我在<bean>中多加了一个逗号。。。
<bean id="quest", class="DI.knight.SlayDragonQuest"/>,去掉逗号改成<bean id="quest" class="DI.knight.SlayDragonQuest"/>就可以了。
还有就是spring xml文件编写的时候,需要注明一系列beans的属性,包括xmlns, xsi:schemaLocation等,网上很多示例都是对应特定版本的,后来在stackoverflow上面找了一种不需要对应特定spring版本的写法,如下:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> </beans>
没有过多测试不同的spring版本,不过在spring4.0.4下面是可以正常解析的。
最后运行我们的DI测试程序,程序正常输出结果。程序非常非常简单,就不再列出来了。