Spring Autowiring «забыл» о зависимости

Я хотел поиграть с различными типами областей действия bean-компонентов. Поэтому я написал тестовую среду, которая должна генерировать случайное число, чтобы я мог видеть, изменился ли компонент. Моя тестовая установка не работает, и я не могу объяснить, что я обнаружил.

Я использую Spring Boot 2.13 с Spring Framework 5.15.

Следующая настройка:

Основной класс:

package domain.webcreator;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class WebcreatorApplication {

    public static void main(String[] args) {
        SpringApplication.run(WebcreatorApplication.class, args);
    }
}

Класс фасоли:

package domain.webcreator;

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

import java.util.Random;

@Configuration
public class Beans {
    @Bean
    public Random randomGenerator() {
        return new Random();
    }
}

Класс области видимости:

package domain.webcreator;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import java.util.Random;

@Service
@Scope("singleton")
public class Scoper {
    private Random rand;

    public Scoper(Random rand) {
        this.rand = rand;
    }

    public int getNumber(int max) {
        return rand.nextInt(max);
    }
}

Контроллер индекса

package domain.webcreator.controller;

import domain.webcreator.Scoper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class IndexController {
    @GetMapping("/")
    @ResponseBody
    @Autowired
    public String indexAction(Scoper scoper) {
        return String.valueOf(scoper.getNumber(50));
    }
}

Моя проблема в том, что я получаю NPE при вызове scoper.getNumber (50). Это странно, потому что при отладке генерируется bean-компонент Random и передается в конструктор области видимости. Позже в контроллере свойство rand равно null. Spring Autowiring «забыл» о зависимостиSpring Autowiring «забыл» о зависимости

Что я делаю неправильно?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
0
107
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы пытаетесь применить @Autowired к случайному методу, а Spring работает иначе. Параметры метода контроллера предназначены для информации, специфичной для этого HTTP-запроса, а не для общих зависимостей, поэтому Spring пытается создать новый Scoper, связанный с запросом, но у него нет входящих значений в запросе для заполнения. (Я действительно удивлен, что вы не получаете сообщение об отсутствии конструктора по умолчанию.)

Вместо этого передайте свой Scoper в конструкторе.

@RestController
public class IndexController {
    private final Scoper scoper;

    public IndexController(Scoper scoper) {
        this.scoper = scoper;
    }

    @GetMapping("/")
    public String indexAction(Scoper scoper) {
        return String.valueOf(scoper.getNumber(50));
    }
}

Пара замечаний:

  • Область Singleton используется по умолчанию, и ее не нужно указывать.
  • @RestController предпочтительнее повторения @ResponseBody, если у вас нет смешанного класса контроллера.

Спасибо, очень полезно. Я читал об этом некоторое время назад, но я не мог вспомнить это, чувствуя себя немного глупо сейчас. Если другие наткнутся на это, здесь вы можете найти поддерживаемые аргументы метода @Controller: docs.spring.io/spring/docs/5.1.5.RELEASE/…

devnull 16.03.2019 21:29

Другие вопросы по теме