Не удается заставить Spring ввести мои зависимости - PullRequest
1 голос
/ 01 октября 2011

Я пытался заставить Spring внедрить зависимость @Autowired в мое приложение безрезультатно.Что я делаю не так?

Я создал компонент с именем TimeService.Его задача - возвращать текущее время всем, кто спрашивает.

package com.foxbomb.springtest.domain.time;

import java.util.Date;
import org.springframework.stereotype.Service;

@Service
public class TimeService {

    public TimeService() {
        super();
        System.out.println("Instantiating TimeService...");
    }

    public Date getTime() {
        return new Date();
    }
}

Конечно, мне нужно сообщить об этом Spring, поэтому я добавил в web.xml следующее:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring-context.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>  

Отлично, и немного конфигурации Spring:

<?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-3.0.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:annotation-config base-package="com.foxbomb.springtest.domain" />

</beans>

Теперь все, что нам нужно, это вызывающий класс, который хотел бы использовать эту зависимость.К сожалению, @Autowired здесь, кажется, ничего не делает:

package com.foxbomb.springtest;

import...

@Configurable
public class TimeManager {

    public TimeManager() {
        super();
        System.out.println("Instantiating TimeManager...");
    }

    @Autowired
    private TimeService timeService;

    public Date getTime() {
        return timeService.getTime();
    }

}

И, наконец, JSP, который хочет отображать время:

<%@page import="com.foxbomb.springtest.ApplicationContextImpl"%>
<%@page import="com.foxbomb.springtest.TimeManager"%>

<html>
    <head>
        <title>Spring Test</title>
    </head>
    <body>
        <h1>Autowired Dependencies....</h1>
        <p>
            Time is now <%=new TimeManager().getTime()%>!
        </p>

    </body>
</html>

Но все, что я получаю, это:

java.lang.NullPointerException
    com.foxbomb.springtest.TimeManager.getTime(TimeManager.java:26)

Ответы [ 5 ]

4 голосов
/ 01 октября 2011

При доступе к TimeManager объекту, подобному этому:

Time is now <%=new TimeManager().getTime()%>!

Весна ничего не знает об этом классе. Вы в основном создаете новый объект, вот и все!

Возможно, Spring создает экземпляр TimeManager и правильно внедряет зависимости (однако вы должны использовать @Service вместо @Configuration аннотации), но вы не используете этот экземпляр в JSP. Вместо этого вы создаете новый, неуправляемый экземпляр, который полностью независим и не знает о Spring и зависимостях ...

Я думаю это будет работать:

<%= WebApplicationContextUtils.
  getWebApplicationContext(application).
  getBean(TimeManager.class).
  getTime() %>

Гадкий? Конечно. Потому что весь подход к доступу к сервисам из JSP (представление) безобразен. Вы должны по крайней мере иметь сервлет, который обращается к бинам Spring и помещает результат в атрибуты запроса. Затем к этим атрибутам можно получить доступ в JSP, к которому вы перенаправляете - без уродливых скриптлетов.

Если вы действительно хотите сделать этот «правильный» путь, попробуйте Spring MVC или другой популярный веб-фреймворк Java.

1 голос
/ 01 октября 2011

Аннотация @Autowire в TimeManager не была распознана, поскольку вы указали Spring начать поиск информации о конфигурации аннотации в неправильном пакете.

TimeManager находится в com.foxbomb.springtest.

У вас есть эта конфигурация:

<context:annotation-config base-package="com.foxbomb.springtest.domain"/>

Обратите внимание, что "com.foxbomb.springtest! = Com.foxbomb.springtest.domain".

Измените свою конфигурацию, чтобы включить это:

<context:annotation-config base-package="com.foxbomb.springtest"/>

Редактировать: Spring должен создать экземпляр TimeManager.

Вам потребуется:

  1. Чтобы TimeManager был членом данных класса контроллера.
  2. @Autowire TimeManager в классе контроллера (или каким-то образом получить его из весны).
  3. Добавьте TimeManager в какую-то подходящую область (возможно, сеанс, возможно запрос, возможно приложение).
  4. Доступ к этому TimeManager на вашемСтраница JSP.Может быть, что-то вроде этого: It is now ${MyTimeManager.time} balonia watch time.
0 голосов
/ 03 октября 2011

Наконец!

Я работал с кодом в приведенном выше примере. Хитрость заключалась в том, чтобы настроить Aspect / J и Weaving. Это позволяет аннотированному классу @Configurable автоматически понимать, что он зависит от Spring для внедрения зависимостей.

В базовом пакете не было много ошибок :) Я случайно сделал опечатку xml, пытаясь добавить атрибут base-package в тег context: annotation-config. Правильное определение было:

<context:annotation-config/>
<context:component-scan base-package="com.foxbomb.springtest"/>

Мне нужно в конечном итоге изменить его на com.foxbomb.springtext, чтобы включить в него класс, который тоже пытался получить доступ к бобу - так как в конце он также аннотирован.

Спасибо всем за помощь!

0 голосов
/ 01 октября 2011

Вы должны использовать @Component (или детскую аннотацию стереотипа), а не @Configuration, и пометить свой TimeManager этим. @Configuration используется для конфигурации контейнера на основе Java, а это не то, что вы здесь делаете.

0 голосов
/ 01 октября 2011

Я склонен согласиться с @TomaszNurkiewicz; использовать рамки. Тем не менее, фреймворк является way избыточным для многих приложений. Если это для вас излишне, этот ответ подробно описывает, как это сделать без ручной работы по получению бина самостоятельно. ИМО делает это вручную, побеждает цель.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...