在spring bean中是否可以使用可以使用事务的shutdown方法?

时间:2011-05-04 23:28:36

标签: spring shutdown

在spring bean的destroy方法中,我想执行一些查询来清理数据库中的一些东西。 Spring似乎无法以任何方式找到它。

错误总是如下:

  

调用destroy方法失败   名为'someBean'的bean:   org.springframework.beans.factory.BeanCreationNotAllowedException:   使用名称创建bean时出错   'transactionManager':单例bean   创造不允许的时候   这家工厂的单身人士都在   破坏(不要求bean   来自destroy方法中的BeanFactory   实施!)

以下将告诉spring在不再需要bean之后调用shutdownDestroy。但是,我在尝试使用事务时遇到上述错误。

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

使用以下命令启用公共生命周期注释时也是如此:

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

然后使用@PreDestroy标记方法。该方法也不能使用交易。

有没有办法做到这一点?

编辑: 谢谢!我有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;
}

2 个答案:

答案 0 :(得分:14)

有趣的问题。我会说你应该可以通过letting your bean implement SmartLifeCycle来做到这一点。

这样,如果您的int getPhase();方法返回Integer.MAX_VALUE,那么当ApplicationContext最终关闭时,它将成为第一个被调用的方法。

<强>参考:

答案 1 :(得分:1)

我遇到过同样的问题。检查spring的源代码后,U可以尝试实现

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

onApplicationEvent将在bean destory之前调用,你可以在spring的org.springframework.context.support.AbstractApplicationContext#doClose方法中检查它。我把它贴在下面,所以ContextEvent - &gt; LifeCycle - &gt;豆祸。

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