2012-05-01 212 views
10

我想在tomcat服務器啓動時啓動守護進程郵件服務線程。所以,我用@Async註釋標註了一個方法。如何在服務器啓動時啓動守護進程

我有一個實現ApplicationListener接口的類。當我從這個類調用異步方法時,它從不會異步啓動並阻塞當前線程。當我從一個彈簧控制器類調用我的異步方法時,它永遠不會阻塞並異步啓動。

爲什麼異步方法從一個類而不是從另一個類成功執行?

我在做什麼錯了,如何在服務器啓動時執行我的異步方法?

在此先感謝。嗨,我嘗試使用InitializingBean接口,@PostConstruct,init-method方法來調用我的異步方法,但它從來沒有執行過。然後我意識到,我的默認lazy-init是真的,所以我讓我的InitializingBean的lazy-init爲false。現在它執行我的asnyc方法,但它阻止了當前的線程,現在我面臨的另一個問題是我的服務器沒有優雅地停止,但我必須強制停止我的服務器。

+2

向我們顯示您的代碼。 –

回答

12

首先你不需要實現ApplicationListener接口。你正在使用Spring - 應用程序上下文就足夠了。

其次你說的是Spring @Async,這意味着你的任務應該從Application Context開始,而Controller bean是它的一部分。

您需要確保在您的spring xml文件中有<annotation-driven>。基於Spring的reference,使用@Async在應用程序啓動時具有侷限性

@Component 
public class SampleBeanImpl implements SampleBean { 

    @Async 
    void doSomething() { … } 
} 


@Component 
public class SampleBeanInititalizer { 

    @Autowired 
    private final SampleBean bean; 

    @PostConstruct 
    public void initialize() { 
    bean.doSomething(); 
    } 
} 
+0

嗨Danny,謝謝,還有一個問題,我如何在服務器啓動時執行一些方法,如果我不實現ApplicationListener接口。 –

+0

看到我更新的答案。 –

+1

接受的解決方案將無法正常工作,如以下錯誤中所述:https://jira.spring.io/browse/SPR-7560 –

0

@asyn是spring framework的一部分,你的listener使用spring的上下文嗎?如果不是,我會建議在異步方法中啓動一個新線程。

4

@Async不能使用

您可以在@PostConstruct功能開始你的任務結合生命週期回調,如 @PostConstruct。爲了異步初始化Spring bean,你當前使用的是一個單獨的初始化Spring bean,然後在目標上調用目標註釋方法 @Async

所以,你的情況,也許它會是很好的有一個InitializingBean實現你的目標bean,然後通過啓動守護進程。

2

您是否已將<annotation-driven>標記添加到您的應用程序上下文中?從Spring reference doc

要同時啓用@Scheduled和@Async註解,只是包括在你的配置任務命名空間中的「註解驅動」元素。

請注意,您還應該考慮配置一個執行器實例。從task schema definition

定義與配置池大小,隊列能力ThreadPoolTask​​Executor類的實例,保活,和拒絕的策略值。關於org.springframework.scheduling.annotation.EnableAsync註解,請參閱Javadoc以獲取有關此XML元素的基於代碼的替代方法的信息。

因此,要創建一個與5個線程備份由一個線程池的執行者,你必須做到以下幾點:

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

對於更多的配置選項,請參閱@EnableAsync javadoc如上所述。

1

我的英語是游泳池。 您必須設置Service Class @Lazy(false)。