Поле автоматической загрузки Spring Boot в одноэлементном сервисе / контроллере по запросу - PullRequest
1 голос
/ 19 июня 2019

У меня есть одноэлементный класс обслуживания с автоматическим полем, например:

@Service
public class MyService{

     @Autowired
     private List<POJO> listWithObjectsForRequest;

}

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

@Configuration
public class MyServiceConfiguration{

    @Bean
    @RequestScope
    public List<POJO> listWithObjectsForRequest(){
        return heavyCalculations() // signature: public List<POJO> heavyCalculations()...
    }

}

Но при запуске приложения я получаю следующую ошибку:

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'myService': Unsatisfied dependency expressed through field 'listWithObjectsForRequest'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.listWithObjectsForRequest': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1411)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1247)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1167)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593)
    ... 31 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.listWithObjectsForRequest': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:365)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:193)
    at com.sun.proxy.$Proxy84.equals(Unknown Source)
    at java.util.concurrent.ConcurrentHashMap.containsValue(ConcurrentHashMap.java:985)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.determineAutowireCandidate(DefaultListableBeanFactory.java:1501)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1222)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1167)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593)
    ... 44 common frames omitted
Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
    at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131)
    at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:42)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:353)
    ... 53 common frames omitted

Мне показалось, что я нашел ответ здесь: Внедрить объектный запрос в другой компонент , но мое приложение все еще не работает с этим сообщением об ошибке.

Я знаю, что listWithObjectsForRequest может быть толькорассчитывается в объеме запроса, но как сказать Spring, что поле MyService должно быть инициализировано только (один раз) в запросе?

Ответы [ 3 ]

1 голос
/ 19 июня 2019

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

Если вы хотите внедрить bean-компонент области действия request в singleton, вы можете сделать это либо с помощью

Вставьте ApplicationContext в MyService, как -

        @Autowired
        private ApplicationContext context;

Затем, вместо autowiring listWithObjectsForRequest, каждый раз получайте ссылку на компонент из контекста приложения.Хотя этот подход решит проблему, но свяжет ваш код с Spring.Если вы согласны с этим, вы можете использовать его.

или

Вы можете использовать метод инъекции, как упомянуто здесь - https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-method-injection

1 голос
/ 19 июня 2019

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

Вам просто нужно использовать

@Autowired // provider from javax.inject.Provider; private Provider<List<POJO>> listWithObjectsForRequest;

Ссылки Когда использовать javax.inject.Provider в Spring?

0 голосов
/ 19 июня 2019

в классе POJO пытаться @Scope ( "прототип") до объявления класса

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