Spring DI - REST 服务中的 Autowired 属性为空 [英] Spring DI - Autowired property is null in a REST service

查看:39
本文介绍了Spring DI - REST 服务中的 Autowired 属性为空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开始使用 Spring DI,但我正在努力解决依赖注入问题,更糟糕的是,我什至不知道为什么,因为这对我来说似乎没问题.希望你们能帮助我!

I'm getting started with Spring DI, but I'm struggling with dependency injection and the worse part is that I'm not even sure why as it seems ok to me. Hopefully you guys can help me out!

问题是注释为@Autowired的属性总是null

The problem is that a property annotated as @Autowired is always null

我有几个具有 Maven 结构的项目:

I've got a few projects with Maven structure:

  • com.diegotutor.lessondeliver
  • com.diegotutor.utility

我在 Tomcat 7 上运行示例

I'm running the examples over Tomcat 7

我在 pom.xml 中使用了以下依赖项:

I'm using the following dependencies in my pom.xml:

  • 弹簧上下文 3.2.4
  • spring-web 3.2.4
  • 球衣服务器 1.17.1
  • 球衣核心 1.17.1
  • 泽西-servlet 1.17.1

简单的想法是拥有一个 RESTful 服务,它通过依赖注入能够打印出位于以下配置文件中的属性值:D:configuracion.conf.

The simple idea is to have a RESTful service that through Dependency Injection is able to print out the value of a property located in a config file located at: 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 的注入实例:

And at com.diegotutor.lessondeliver I have the RESTful service where I would like to use an injected instance of the 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) 注入配置文件读取路径:

Finally at /com.diegotutor.lessondeliver/src/main/webapp/WEB-INF/service-beans.xml I have the following XML application context file, where I use the implementation of ConfigService (PropertyFileConfigService) injecting on it the path for the configuration file to read:

<?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>

显然我已经在 com.diegotutor.lessondeliver Web 应用程序的 web.xml 中指定了我想要 service-beans.xml 作为 ConfigLocation 和一个监听器 ContextLoaderListener,RESTful 服务依赖于 ServletContainer

Obviously I have specified in the web.xml of this com.diegotutor.lessondeliver web app that I want service-beans.xml as ConfigLocation and a listener ContextLoaderListener, and the RESTful service relies on ServletContainer

如果我指定 context:component-scan 以按照建议在 com.diegotutor 中查找组件 这里,我通过不使用建议的任何新语句来强制通过 Spring 创建对象 这里为什么我得到带注释的configService为空?为什么 Spring 无法注入 com.diegotutor.utility.impl.PropertyFileConfigService 的实例?

If I'm specifying context:component-scan to look for Components in com.diegotutor as suggested here and I'm forcing object creation through Spring by not using any new Statement as suggested here, Why am I getting the annotated configService as null? Why Spring is unable to inject an instance of com.diegotutor.utility.impl.PropertyFileConfigService?

任何帮助将不胜感激!

谢谢

按照要求,我的web.xml如下:

As requested, my web.xml is as follows:

<?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.

You were right! It seems that the problem is that Jersey is totally unaware of Spring and instantiates its own object. In order to make Jersey aware of Spring object creations (through dependency injection) I had to integrate Spring + Jersey.

整合:

  1. 添加maven依赖

  1. Add maven dependencies

<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>

  • web.xml

    <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 可以正常工作,并且对象不再为空.

    Now the @Autowired works properly and the object is not null anymore.

    我对使用 jersey-spring 依赖项时必须在 maven 中使用的排除有点困惑,但这是另一个问题 :)

    I'm a little bit confused about the exclusions I have to use in maven when using jersey-spring dependency, but that's another issue :)

    谢谢!

    这篇关于Spring DI - REST 服务中的 Autowired 属性为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆