Может ли он ввести компонент RequestScope в одноэлементный компонент, используя инъекцию конструктора весной?

#spring-boot #dependency-injection #scope #requestscope

Вопрос:

Он работает, насколько я проверил. Но я не понимаю, почему и как это работает.(Также я не уверен, что это безопасно использовать в производстве)

Вот мой тестовый код

 @Service
public class SomeService {

    private static final Logger logger = LoggerFactory.getLogger(SomeService.class);

    private final RequestContext requestContext; // @RequestScope   @Component Bean
    public SomeService(RequestContext requestContext) {
        this.requestContext = requestContext;
    }

    public void checkBean() {
        logger.info("Singleton Bean: {}, RequestScope Bean: {}", this, this.requestContext);
        String clientId = recommendContext.getClientId();
    }
}
 

Сценарий, как показано ниже

  • Получить запрос от контроллера
  • SomeService вводится контроллером
  • У каждого запроса есть свой собственный RequestContext компонент
  • В контроллере, позвоните someService.checkBean()

Дело в том, что я считаю странным, что

  • SomeService является одноэлементным бобом
  • RequestContext объявляется как final переменная и инициируется только конструктором
  • Однако, похоже, это работает.

Результат выполнения кода выглядит следующим образом

 2021-06-14 09:56:26.010 INFO  23075 --- [nio-8888-exec-1] p.service.SomeService   : Singleton Bean: pkgs.service.SomeServiceImpl@3c65ee26, RequestScope Bean: pkgs.context.RequestContext@56867592
2021-06-14 09:56:30.933 INFO  23075 --- [nio-8888-exec-3] p.service.SomeService   : Singleton Bean: pkgs.service.SomeServiceImpl@3c65ee26, RequestScope Bean: pkgs.context.RequestContext@73ddb7a4
2021-06-14 09:56:31.687 INFO  23075 --- [nio-8888-exec-4] p.service.SomeService   : Singleton Bean: pkgs.service.SomeServiceImpl@3c65ee26, RequestScope Bean: pkgs.context.RequestContext@56b4f7c8
2021-06-14 09:56:32.352 INFO  23075 --- [nio-8888-exec-5] p.service.SomeService   : Singleton Bean: pkgs.service.SomeServiceImpl@3c65ee26, RequestScope Bean: pkgs.context.RequestContext@33469287
 

Как вы можете видеть, сервис единичен, а компонент RequestContext уникален для каждого запроса.
Мне нужно какое-то объяснение того, что происходит внутри spring

Спасибо

Ответ №1:

Когда компонент имеет область запроса, Spring создает прокси-сервер. Всякий раз, когда вызывается этот прокси-сервер, он делегирует экземпляр компонента, специфичного для текущего запроса.

В вашем случае RequestContext экземпляр, который вводится в SomeService переменную и хранится в requestContext final ней, является прокси-сервером. Если вы попытаетесь вызвать службу за пределами веб-запроса, это приведет к сбою, так как прокси-сервер не сможет найти текущий запрос.