Задать вопрос
@sulik93
Начал изучать Java. Продолжаю изучать Java.

Что не так с внедрением зависимостей?

Всем привет!
Осваиваю DI.
Создал три простых класса:

1.
package lessons.started;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Starter {
    private static final Logger logger = LogManager.getLogger(Starter.class);

    @Autowired
    private static GreetingServiceImpl greetingService;

    public static void main(String[] args) {
        logger.info("Starting configuration...");
        ApplicationContext context = new AnnotationConfigApplicationContext(LessonsConfiguration.class);
        logger.info(
                greetingService.sayGreeting()
        );
    }
}


2.
package lessons.started;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan
public class LessonsConfiguration {

    @Bean
    public GreetingServiceImpl greetingService(){
        return new GreetingServiceImpl();
    }
}


3.
package lessons.started;

import org.springframework.stereotype.Component;

@Component
public class GreetingServiceImpl {

    public String sayGreeting() {
        return "Greeting, user!";
    }
}


При запуске приложения помимо прочих логов вылетает ошибка:
Exception in thread "main" java.lang.NullPointerException
	at lessons.started.Starter.main(Starter.java:22)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)


т.е. ссылке greetingService не присвоилось значение.

Почему не работает Внедрение зависимостей?
Что я делаю не так?
  • Вопрос задан
  • 313 просмотров
Подписаться 2 Оценить Комментировать
Решения вопроса 3
причем тут
new AnnotationConfigApplicationContext(LessonsConfiguration.class)

и

starter
@Autowired
private static GreetingServiceImpl greetingService;

?

Так ничего вроде в коде и нет,чтобы то поле инициализировалось.
Ответ написан
@void_phoenix
В общем вам уже правильно ответили выше. От себя добавлю. Чтобы что-то внедрялось в ваш класс, этот класс должен создаваться фреймворком, который реализует внедрение зависимостей. То есть вы должны из контекста получить нужный объект, и тогда Spring перед передачей объекта вам подставит туда нужные поля.

Класс Starter в вашем случае создается не через фреймворк внедрения зависимостей, это обычный класс с методом main, то есть он вызывается при старте приложения. И естественно java ничего в @Autowired не подставляет, потому что это аннотация спринга, а спринг у вас инициализируется уже после, через contxt.

Если подытожить. Чтобы срабатывал @Autowired, объект должен быть создан фреймворком (получен из контекста), например спрингом. class Starter не создается спингом, так что никакое внедрение зависимостей в нем не работает.
Ответ написан
Комментировать
jaxtr
@jaxtr
JavaEE/Spring-разработчик
Во-первых:
@Autowired
    private static GreetingServiceImpl greetingService;

у тебя greetingService является статическим. Внедрение зависимостей при помощи @Autowired работает не со свойствами/методами классов, а со свойствами/методами объектов.

Во-вторых класс Starter не является управляемым, соответственно, внедрение зависимости в объект этого класса невозможно. Да и объект этого класса ты не создаёшь.

Что бы твой пример заработал, в методе main класса Starter после создания контекста получи нужный компонент из контекста и вызови метод. Получится что-то вроде:
public static void main(String[] args) {
        logger.info("Starting configuration...");
        ApplicationContext context = new AnnotationConfigApplicationContext(LessonsConfiguration.class);
        logger.info(
                context.getBean(GreetingServiceImpl.class).sayGreeting()
        );
    }


И ещё у тебя на классе GreetingServiceImpl есть аннотация @Component, но при этом ты ещё и в конфигурации создаёшь компонент этого же класса. По-хорошему либо убери @Component, либо удали метод
@Bean
    public GreetingServiceImpl greetingService(){
        return new GreetingServiceImpl();
    }


Про внедрение зависимостей в Spring Framework я вкратце писал тут.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы