14

你怎么会有一个实现 Runnable 并自动提交给 springs TaskExecutor 的类?

例如,我有一个任务:

public class MyTask implements Runnable {

    @Autowired private MyRepository myRepository;

    @Override
    public void run() {
        myRepository.doSomething();
    }
}

还有一个向spring TaskExecutor 发送任务的服务:

@Service
public class MyService {

    @Autowired private TaskExecutor taskExecutor;

    public void someMethod() {

        MyTask myTask = new MyTask();
        taskExecutor.execute(myTask);

    }

}

我知道这些字段没有被自动连接,因为 MyTask 正在使用 new MyTask() 进行实例化。但是,我该如何解决这个问题?我应该访问 Spring 的 ApplicationContext 并通过它创建 bean 吗?您将如何在 Web 应用程序环境中执行此操作?

谢谢!

4

2 回答 2

12

尝试

public class MyTask implements Runnable {
    private MyRepository myRepository;

    public MyTask(MyRepository myRepository) {
         this.myRepository = myRepository;
    }

    @Override
    public void run() {
        myRepository.doSomething();
    }
}

@Service
public class MyService {
    @Autowired private TaskExecutor taskExecutor;
    @Autowired private MyRepository myRepository;


    public void someMethod() {
        MyTask myTask = new MyTask(myRepository);
        taskExecutor.execute(myTask);
    }
}

或者您可以声明 MyTask 的 scope = "prototype" 并将 MyService 更改为

@Service
public class MyService {
    @Autowired private ApplicationContext ctx;

    public void someMethod() {
        MyTask myTask = ctx.getBean(MyTask.class);
        taskExecutor.execute(myTask);
    }
}
于 2013-04-19T00:10:30.027 回答
4

使用 Spring 至少有两种好方法可以做到这一点。首先,@Configurable注解。使用这意味着对 AspectJ 的依赖,但它允许您注入不受 Spring 管理的 bean(即,您正在使用 new 运算符)。这将涉及使用 @Configurable 注释 MyTask,并在您的 Spring 配置中添加几行,如链接中所述。

@Configurable
public class MyTask implements Runnable { ... }

@Service
public class MyService {
   @Autowired private TaskExecutor taskExecutor;

   public void someMethod() {

     // AspectJ would jump in here and inject MyTask transparently
     MyTask myTask = new MyTask();
     taskExecutor.execute(myTask);

}

}

第二种方法将涉及使用 Spring 的 ServiceLocatorFactoryBean 特性来创建原型 bean。这在JavaDoc中得到了最好的解释,但在这种情况下,您将像任何其他 bean 一样将 TaskFactory 注入您的 @Service 注释类,然后执行以下操作:

@Service
public class MyService {
  @Autowired private TaskExecutor taskExecutor;
  @Autowired private MyRepository myRepository;
  @Autowired private TaskFactory taskFactory;


public void someMethod() {
    MyTask myTask = taskFactory.getTask("myTask")
    taskExecutor.execute(myTask);
}

}

MyTask 已经被注入到您的存储库中,因为您可以在 XML 映射中配置它。我每天都使用这两种方法,但我倾向于使用第二种方法,因为它更易于阅读,并通过确保开发人员不做不易测试的事情来帮助他们保持诚实,坦率地说,它更多对不经意的观察者来说很清楚。

于 2013-04-19T00:36:43.550 回答