我刚开始使用Spring DI,但是我在依赖注入方面苦苦挣扎,更糟糕的是,我什至不确定为什么对我来说似乎还可以。希望你们能帮助我!
问题是注释为@Autowired的属性始终为null
我有一些具有Maven结构的项目:
我正在通过Tomcat 7运行示例
我在我的使用以下依赖项pom.xml:
pom.xml
一个简单的想法是拥有一个RESTful服务,该服务通过Dependency Injection能够打印出位于以下位置的配置文件中的属性值: D:\configuracion.conf.
在com.diegotutor.utility,我具有以下接口:
package com.diegotutor.utility; public interface ConfigService { public String getProperty(final String propertyName); }
实施者:
package com.diegotutor.utility.impl; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.util.Properties; import com.diegotutor.utility.ConfigService; public class PropertyFileConfigService implements ConfigService{ Properties prop; public PropertyFileConfigService (final InputStream input) throws IOException { if(input == null) { throw new IllegalArgumentException("Input stream can't be null"); } prop = new Properties(); prop.load(input); } public PropertyFileConfigService (final String fileName) throws IOException { final FileInputStream input = new FileInputStream(fileName); prop = new Properties(); prop.load(input); } public PropertyFileConfigService(final Reader input) throws IOException { prop = new Properties(); prop.load(input); } public String getProperty(final String propertyName) { return prop.getProperty(propertyName); } }
在com.diegotutor.lessondeliver上,我拥有RESTful服务,我想在其中使用ConfigService的注入实例:
package com.diegotutor.lessondeliver; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.diegotutor.utility.ConfigService; @Path("/") @Component public class HelloWorld { private static final Log log = LogFactory.getLog(HelloWorld.class); @Autowired private ConfigService configService; @Path("/helloworld") @GET @Produces(MediaType.TEXT_PLAIN) public String getHello() { String host = configService.getProperty("host"); return "Hello World! HOST" + host; // configService IS NULL!! //SO IT THROWS A NULLPOINTER EXCEPTION WHEN INVOKING getProperty ON IT } }
最后,/com.diegotutor.lessondeliver/src/main/webapp/WEB-INF/service-beans.xml在下面的XML应用程序上下文文件中,我使用在其上ConfigService (PropertyFileConfigService)注入配置文件读取路径的实现:
<?xml version="1.0" encoding="UTF-8"?> <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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <bean id="configService" class="com.diegotutor.utility.impl.PropertyFileConfigService"> <constructor-arg type="java.lang.String" value="D:\configuracion.conf" /> </bean> <context:component-scan base-package="com.diegotutor" /> </beans>
显然,我已在web.xml此com.diegotutor.lessondeliverWeb应用程序的中指定了我希望service-beans.xml作为ConfigLocation和侦听器ContextLoaderListener,并且RESTful服务依赖于ServletContainer
web.xml
com.diegotutor.lessondeliverWeb
ContextLoaderListener
如果我com.diegotutor按照这里的建议指定context:component-scan来查找Components,并且不按照这里的建议使用任何新的Statement来强制通过Spring创建对象,为什么我将带注释的configService设置为null?为什么Spring无法注入的实例com.diegotutor.utility.impl.PropertyFileConfigService?
com.diegotutor.utility.impl.PropertyFileConfigService
任何帮助都感激不尽!
谢谢
编辑:
根据要求,我的web.xml如下:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>com.diegotutor.lessondeliver</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/service-beans.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>jersey-servlet</servlet-name> <servlet-class> com.sun.jersey.spi.container.servlet.ServletContainer </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>jersey-servlet</servlet-name> <url-pattern>/rest/*</url-pattern> </servlet-mapping> </web-app>
你是对的!问题似乎在于Jersey完全不了解Spring并实例化了自己的对象。为了使Jersey知道Spring对象的创建(通过依赖注入),我必须集成Spring + Jersey。
集成:
<dependency> <groupId>com.sun.jersey.contribs</groupId> <artifactId>jersey-spring</artifactId> <version>1.17.1</version> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> </exclusion> </exclusions> </dependency>
<servlet> <servlet-name>jersey-servlet</servlet-name> <servlet-class> com.sun.jersey.spi.spring.container.servlet.SpringServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet>
现在,@ Autowired可以正常工作,并且该对象不再为null。
我对使用jersey-spring依赖项时必须在maven中使用的排除感到有些困惑,但这是另一个问题:)