10

我想在 tomcat 服务器启动时启动一个守护邮件服务线程。所以,我用@Async 注释注释了一个方法。

我有一个实现 ApplicationListener 接口的类。当我从这个类调用我的异步方法时,它永远不会异步启动并阻塞当前线程。当我从 spring 控制器类调用我的异步方法时,它永远不会阻塞和异步启动。

为什么异步方法从一个类而不是另一个类成功执行?

我在做什么错,如何在服务器启动时执行我的异步方法?

提前致谢。

编辑:我尝试使用 InitializingBean 接口、@PostConstruct、init-method 方法来调用我的异步方法,但它从未执行。然后我意识到,我的默认lazy-init 是true,所以我将我的InitializingBean 的lazy-init 设置为false。现在它执行我的 asnyc 方法,但它阻塞了当前线程,现在还有一个问题,我面临的是我的服务器没有正常停止,但我必须强制停止我的服务器。

4

5 回答 5

13

首先你不需要实现ApplicationListener接口。您正在使用 Spring - 应用程序上下文就足够了。

其次,您在谈论 Spring @Async,这意味着您的任务应该从 Application Context 开始,而 Controller bean 是其中的一部分。

您需要确保<annotation-driven>在您的 spring xml 文件中有。

您可以在 @PostConstruct 函数上开始您的任务:

@Component
public class SampleBeanImpl implements SampleBean {

  @Async
  void doSomething() { … }
}


@Component
public class SampleBeanInititalizer {

  @Autowired
  private final SampleBean bean;

  @PostConstruct
  public void initialize() {
    bean.doSomething();
  }
}
于 2012-05-01T08:23:15.947 回答
4

根据 Spring 的参考@Async,在应用程序启动期间使用有限制:

@Async不能与生命周期回调一起使用,例如 @PostConstruct. 要异步初始化 Spring bean,您当前必须使用单独的初始化 Spring bean, @Async然后调用目标上的注释方法。

InitializingBean所以,在你的情况下,用你的目标 bean 实现一个实现然后通过它启动守护进程可能会很好。

于 2012-05-01T08:30:01.870 回答
2

您是否已将<annotation-driven>标签添加到您的应用程序上下文中?来自Spring 参考文档

要同时启用@Scheduled 和@Async 注释,只需在配置中包含任务命名空间中的“注释驱动”元素。

注意,您还应该考虑配置一个执行器实例。从任务模式定义

定义具有可配置池大小、队列容量、保持活动和拒绝策略值的 ThreadPoolTask​​Executor 实例。有关此 XML 元素的基于代码的替代方案的信息,请参阅 org.springframework.scheduling.annotation.EnableAsync 注释的 Javadoc。

因此,要创建一个由具有 5 个线程的线程池备份的执行程序,您必须执行以下操作:

<task:annotation-driven executor="myExecutor"/>
<task:executor id="myExecutor" pool-size="5"/>

有关更多配置选项,请参阅上述@EnableAsync javadoc

于 2012-05-01T08:53:07.027 回答
1

我的英语是台球。您必须设置服务类@Lazy(false)。

于 2013-11-05T03:10:56.857 回答
0

@asyn是弹簧框架的一部分,你的听众是否使用弹簧上下文?如果没有,我会建议在您的异步方法中启动一个新线程。

于 2012-05-01T08:21:27.377 回答