17

私はSpring DIを使い始めていますが、依存性注入に苦労しています.さらに悪いことに、私には問題ないように思えますが、その理由さえわかりません. うまくいけば、皆さんが私を助けてくれます!

問題は、@Autowiredとして注釈が付けられたプロパティが常にnullであることです。

Maven 構造のプロジェクトがいくつかあります。

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

私はTomcat 7で例を実行しています

私は私ので次の依存関係を使用していますpom.xml:

  • 春のコンテキスト 3.2.4
  • スプリングウェブ 3.2.4
  • ジャージサーバー1.17.1
  • ジャージコア1.17.1
  • ジャージサーブレット 1.17.1

簡単なアイデアは、次の場所にある構成ファイルにあるプロパティの値を依存性注入によって出力できる RESTful サービスを用意することです。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には、注入された ConfigService のインスタンスを使用したい RESTful サービスがあります。

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.xmlConfigLocation と listener として必要なものを指定しました。RESTfulContextLoaderListenerサービスは ServletContainer に依存しています。

com.diegotutorここで提案されているようにコンポーネントを探すために context:component-scan を指定していて、ここで提案されているように新しいステートメントを使用せずに Spring を介してオブジェクトの作成を強制している場合、注釈付きの configService を null として取得するのはなぜですか? Spring が のインスタンスを注入できないのはなぜ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>
4

4 に答える 4

21

君は正しかった!問題は、Jersey が Spring をまったく認識しておらず、独自のオブジェクトをインスタンス化していることにあるようです。Jersey に Spring オブジェクトの作成を (依存性注入を通じて) 認識させるために、Spring + Jersey を統合する必要がありました。

統合するために:

  1. Maven の依存関係を追加する

    <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>
    
  2. jersey-servlet に SpringServlet を使用する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 が適切に機能し、オブジェクトが null ではなくなりました。

jersey-spring依存関係を使用するときにmavenで使用する必要がある除外について少し混乱していますが、それは別の問題です:)

ありがとうございました!

于 2013-11-03T10:33:15.563 に答える
5

または、単に SpringBeanAutoWiringSupport クラスを拡張できます。このように: public class DemoRestService extends SpringBeanAutoWiringSupport. このサポート クラスを拡張することにより、サービス クラスのプロパティを自動配線できます。

于 2016-01-06T19:13:36.403 に答える
2

別の可能なオプションは、jersey リソースでオートワイヤーを手動で呼び出すことです。

@Context
private ServletContext servletContext;

@PostConstruct
public void init() {
    SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, servletContext);
}

うーん、「手動自動配線」が表示されます...

于 2014-12-09T09:06:37.323 に答える