在Runnable线程中访问Spring bean

时间:2016-07-14 16:44:45

标签: java spring multithreading spring-mvc executorservice

我需要在下面的Runnable Thread中访问Spring bean(featureServiceuxService),但null的值为applicationContext因此我无法获取Spring bean Runnable接口。我想知道是否可以访问runnable中的spring bean?如果没有,请建议我另一种方法。

我正在使用Spring 4.0.6Java 8

@Component
public class UserMenuUpdateTask implements Runnable, Serializable, ApplicationContextAware {


    private static final long    serialVersionUID = 3336518785505658027L;

    List<User>                   userNamesList;

    FeatureService               featureService;

    UXService uxService;

    private ApplicationContext   applicationContext;

    public UserMegaMenuUpdateTask() {}

    public UserMegaMenuUpdateTask(List<User> userNamesList) {
        this.userNamesList = userNamesList;
    }

    @Override
    public void run() {
        try {
            for (User user : userNamesList) {

                    featureService = (FeatureService) applicationContext.getBean("featureService");
                    uxService = (UxService) applicationContext.getBean("uxService");                    
                //.........
            }
        } catch (BaseApplicationException ex) {
            throw new BaseApplicationException(ex);
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;

    }
}

我正在调用runnable,如下所示

ExecutorService es = Executors.newCachedThreadPool();
es.execute(new UserMenuUpdateTask(activeUsers));

3 个答案:

答案 0 :(得分:1)

Spring使用ThreadLocal来存储applicationContext,但ExecutorService创建了一个不同的Thread,其中没有bean被管理和/或beanContext找不到任何bean。

请改为使用此instructions

答案 1 :(得分:1)

ApplicationContextAware是Spring用来将其上下文设置为Spring自身管理(知道)的bean的接口。由于您自己创建了UserMenuUpdateTask,因此Spring甚至不知道该实例,也无法设置该字段。

如果你不需要每个调用/每个线程的runnable的新实例(即如果UserMenuUpdateTask是无状态或线程安全的),你可以让Spring管理它(通过注释或XML配置)并使用ExecutorService.execute()中的Spring实例化实例。

如果每次都需要UserMenuUpdateTask的新实例,则需要改为调用类ApplicationContextAware(假设它的实例由Spring管理),并将指针设置为application UserMenuUpdateTask中的上下文,然后将其提供给ExecutorService

答案 2 :(得分:0)

ApplicationContextAware接口仅在Spring内部实例化对象时起作用。当您执行 new UserMenuUpdateTask(activeUsers)时,spring对此对象一无所知,因此它不会设置applicationContext。

编写没有参数的构造函数,将范围设置为prototype并从spring获取此对象,在下一行设置activeUsers,它应该可以工作。或者在创建对象后手动设置应用程序。

我也建议你改变这一行

    for (User user : userNamesList) {

        featureService = (FeatureService) applicationContext.getBean("featureService");
        uxService = (UxService) applicationContext.getBean("uxService");                    
            //.........
        }

    featureService = (FeatureService) applicationContext.getBean("featureService");
    uxService = (UxService) applicationContext.getBean("uxService");      

    for (User user : userNamesList) {
        //.........
    }