报这个异常java.lang.IllegalStateException: Failed to load ApplicationContext的时候,通常是因为applicationContent.xml里面的bean初始化失败的原因。
在maven的项目中,直接启动服务器没有报错,但在用maven进行的单元测试中,有时会报
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1058E:(pos 1): A problem occurred when trying to resolve bean 'props':'
Could not resolve bean reference against BeanFactory'
原因是这样的,applicationContext.xml里面的那个bean props,是用jndi的形式注入进来的,一般用jndi形式都是配置一些缓存和数据源的,如
<jee:jndi-lookup id="props" jndi-name="java:comp/env/props"/> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations" value="file:#{@props}"/> <property name="ignoreResourceNotFound" value="true"/> <property name="ignoreUnresolvablePlaceholders" value="true"/> <property name="valueSeparator" value=":=" /> </bean> <bean id="mccSocketIOPool" class="com.danga.MemCached.SockIOPool" factory-method="getInstance" init-method="initialize" destroy-method="shutDown" p:servers="${memcached.servers}" p:maxConn="${memcached.maxConn}" p:initConn="${memcached.initConn}" p:socketConnectTO="${memcached.socketConnectTO}" p:socketTO="${memcached.socketTO}" p:maintSleep="${memcached.maintSleep}" p:failover="${memcached.failover}" p:failback="${memcached.failback}" p:nagle="${memcached.nagle}" > <constructor-arg value="morden"/> </bean> <bean id="mcc" class="com.danga.MemCached.MemCachedClient" p:sanitizeKeys="false" > <constructor-arg value="morden"/> </bean> <jee:jndi-lookup id="dataSource" jndi-name="jdbc/morden"/>
,而jndi的配置通常在服务器的配置文件里面配置的,如resin服务器,conf下面某个应用的数据源配置:
<database> <jndi-name>jdbc/morden</jndi-name> <driver type="com.mysql.jdbc.Driver"> <url>jdbc:mysql://localhost:3306/gltest?useUnicode=true&characterEncoding=UTF-8</url> <user>root</user> <password>root</password> </driver> <prepared-statement-cache-size>8</prepared-statement-cache-size> <max-connections>20</max-connections> <max-idle-time>30s</max-idle-time> </database>
如果应用经过服务器(resin)启动,那么应用首先会加载jndi的配置,然后在spring的applicationContext.xml配置文件里面就会加载相应的属性值,就会正常注入相关的bean。但,如果用maven的单元测试来跑应用的话,maven不会启动应用服务器(resin),然后spring初始化bean的时候就找不到相应属性值,就报上面那个错误了。解决方案也很简单,就是在单元测试的时候,把要加载的spring bean的配置文件里面的jndi方式都改为hard code形式,就可以了。为了不影响原来的配置文件,最好用一个新的配置文件作为测试。修改后的配置文件形式如下,主要是缓存服务器和datasource的配置:
<bean id="mccSocketIOPool" class="com.danga.MemCached.SockIOPool" factory-method="getInstance" init-method="initialize" destroy-method="shutDown" p:servers="127.0.0.1:11211" p:maxConn="10" p:initConn="20" p:socketConnectTO="3000" p:socketTO="3000" p:maintSleep="30" p:failover="false" p:failback="true" p:nagle="false" > <constructor-arg value="morden"/> </bean> <bean id="mcc" class="com.danga.MemCached.MemCachedClient" p:sanitizeKeys="false" > <constructor-arg value="morden"/> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/gltest?useUnicode=true&characterEncoding=UTF-8"> </property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean>