Spring计划任务:范围'请求'当前线程无效

时间:2018-05-29 11:15:57

标签: spring asynchronous cron request

我正在用Spring Boot 1.5.8编写一个项目。 我有一些生成的实体类,包含bean(例如FooBean),它只存在于请求范围内。重要的是:我无法改变代码的这一部分。所以假设我有一个Entty:

@Enitty
public class FooEntity{
    @Transient protected FooBean fooBean;
}

和FooBean实现:

@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class FooBean {

    ...
}

我也有一些代码的部分,其中我有方法应该由Spring CRON运行:

@Scheduled(cron = "0 0/2 * * * ?")
@Transactional(value = Transactional.TxType.REQUIRES_NEW)
void scheduledTask() {
    ...
}

重要的是:在那个scheduledTask中我将一些FooEntity实例保存到DB。 当然:当我尝试调用repository.saveAll()时,Spring会抛出异常:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.fooBean ': Scope 'request' is not active for the current thread;

有没有可能解决这个问题?如何覆盖此作用域bean,以便它可以在非请求范围内使用?

1 个答案:

答案 0 :(得分:1)

我想稍后再写:),但是您可以创建自己的bean实例。 在春季启动中,您可以像这样简单地创建自己的bean单例实例:

@Configuration
@EnableScheduling
public class ApiConfig {
    @Bean
    @Primary
    public FooBean fooBean(){
       return new FooBean();
    }
}

如果您的bean在必须自动装配的构造函数中有某些依赖关系(构造函数自动装配),则只需将这些bean放入方法params中,spring就会为您提供此类服务:

@Bean
@Primary
public FooBean fooBean(BeanToAutowire myBean){
   return new FooBean(myBean);
}

如果您的bean没有构造函数自动关联的依赖项,而是注释自动关联的(使用@Autowired),则可以像下面这样简单地完成它:

@Bean
@Primary
public FooBean fooBean(AutowireCapableBeanFactory beanFactory){
   FooBean bean = new FooBean(myBean);
   beanFactory.autowireBean(bean); // here spring will autowire all dependencies for you
   return bean;
}

这不是最优雅的方法,但是可以。副作用是在应用程序上下文中将有两个FooBean实例,但是spring将使用您的实例,因为您使用@Primary注释将此实例设置为主实例。只有将Autowired注释与限定符注释一起使用的bean才可以选择将FooBean的实例进行自动接线。