2011-05-04 19 views
12

在spring bean的destroy方法中,我想執行一些查詢來清理數據庫中的某些東西。春天似乎不允許我以任何方式找到它。在spring bean中是否有可以使用事務的關閉方法?

錯誤總是一樣的東西:

調用destroy方法失敗的 豆名爲 'someBean': org.springframework.beans.factory.BeanCreationNotAllowedException:與名 錯誤創建豆「 transactionManager':Singleton bean 創建不允許,而該工廠的 單例在 銷燬(請勿在BeanFactory中請求bean的銷售方法 實施中的 !)

以下將告訴spring在不再需要bean之後調用shutdownDestroy。但是,嘗試使用事務時出現上述錯誤。

<bean class="org.springframework. ... .CommonAnnotationBeanPostProcessor"/> 

然後標記與@PreDestroy方法:

<bean id="someId" name="someName" class="someClass" 
destroy-method="shutdownDestroy"/> 

同樣,當我使得能夠使用共同的生命週期的註釋是真實的。該方法也不能使用事務。

有沒有辦法做到這一點?編輯: 謝謝!我有這個bean實現SmartLifecycle並添加以下內容,它的工作原理非常好。

private boolean isRunning = false; 

@Override 
public boolean isAutoStartup() {return true;} 

@Override 
public boolean isRunning() {return isRunning;} 

/** Run as early as possible so the shutdown method can still use transactions. */ 
@Override 
public int getPhase() {return Integer.MIN_VALUE;} 

@Override 
public void start() {isRunning = true;} 

@Override 
public void stop(Runnable callback) { 
    shutdownDestroy(); 
    isRunning = false; 
    callback.run(); 
} 

@Override 
public void stop() { 
    shutdownDestroy(); 
    isRunning = false; 
} 
+0

我假設你的方法shutdownDestroy()有@Transactional註釋?你如何在該方法中執行查詢?我正在試着用Spring自動裝入的EntityManager來做到這一點。自動裝配工作正常,但當我嘗試執行我的查詢時,我得到:javax.persistence。TransactionRequiredException:執行更新/刪除查詢 – mag382 2013-04-24 20:11:15

回答

12

有趣的問題。我會說你應該可以做到這一點letting your bean implement SmartLifeCycle

這樣,如果您的int getPhase();方法返回Integer.MAX_VALUE,它將成爲ApplicationContext最後關閉時首先調用的方法。

參考:

+1

實際上,啓動過程以'Integer.MIN_VALUE'開始,以'Integer.MAX_VALUE'結束,而關閉過程將應用相反的順序,所以如果您希望您的方法在關閉時首先執行應該使用'Integer.MAX_VALUE'而不是'Integer.MIN_VALUE'。但是,在這種特殊情況下,任何值都允許從「停止」使用事務。 – John29 2014-08-25 14:00:53

1

我碰到過同樣的問題。檢查彈簧的源代碼後,U可以嘗試實現

public class SomeBean implements ApplicationListener<ContextClosedEvent> { 
    public void onApplicationEvent(ContextClosedEvent event) { 
     stopHook(); 
    } 
} 

onApplicationEvent將豆destory之前調用,您可以檢查它在春天的org.springframework.context.support.AbstractApplicationContext#doClose方法。我把它粘貼在下面,所以ContextEvent - > LifeCycle - > Bean destory。

 try { 
      // Publish shutdown event. 
      publishEvent(new ContextClosedEvent(this)); 
     } 
     catch (Throwable ex) { 
      logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex); 
     } 

     // Stop all Lifecycle beans, to avoid delays during individual destruction. 
     try { 
      getLifecycleProcessor().onClose(); 
     } 
     catch (Throwable ex) { 
      logger.warn("Exception thrown from LifecycleProcessor on context close", ex); 
     } 

     // Destroy all cached singletons in the context's BeanFactory. 
     destroyBeans(); 

     // Close the state of this context itself. 
     closeBeanFactory(); 

     // Let subclasses do some final clean-up if they wish... 
     onClose(); 
相關問題