自动assembly任务发送到Spring TaskExecutor

你怎么能有一个实现Runnable并提交给弹簧TaskExecutor自动assembly的类?

例如,我有一个任务:

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); } } 

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

谢谢!

使用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中得到了最好的解释,但在这种情况下,你会将一个TaskFactory注入到@Service注释类中,就像任何其他bean一样,然后执行类似的操作:

 @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映射中对其进行配置。 我每天都使用这两种方法,但我更倾向于使用这两种方法,因为它更易于阅读,并且通过确保他们不会做不易测试的事情来帮助保持开发人员的诚实,坦白说,更多向不经意的观察者说清楚。

尝试

 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); } }