在 Spring bean 中是否可以有一个可以使用事务的关闭方法?

发布于 2024-11-05 18:09:50 字数 1400 浏览 0 评论 0原文

在 Spring bean 的 destroy 方法中,我想执行一些查询来清理数据库中的一些内容。以我能找到的任何方式,Spring似乎都不允许这样做。

错误总是类似于:

调用销毁方法失败 名为“someBean”的 bean: org.springframework.beans.factory.BeanCreationNotAllowedException: 使用名称创建 bean 时出错 'transactionManager':单例 bean 不允许创建,而 该工厂的单身人士在 销毁(不请求 bean 从 BeanFactory 的 destroy 方法中 实施!)

下面将告诉 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;
}

In the destroy method of a spring bean I want to execute some queries to clean up some stuff in the database. Spring doesn't seem to allow this by any means I can find.

The error is always something like:

Invocation of destroy method failed on
bean with name 'someBean':
org.springframework.beans.factory.BeanCreationNotAllowedException:
Error creating bean with name
'transactionManager': Singleton bean
creation not allowed while the
singletons of this factory are in
destruction (Do not request a bean
from a BeanFactory in a destroy method
implementation!)

The following will tell spring to call shutdownDestroy after the bean is no longer needed. But, I get the above error when trying to use transactions.

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

The same is true when I enable common lifecycle annotations using:

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

and then mark the method with @PreDestroy. That method can't use transactions either.

Is there any way to do this?

EDIT:
Thanks! I had the bean implement SmartLifecycle and adding the following and it works very nicely.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

骷髅 2024-11-12 18:09:50

有趣的问题。我想说你应该能够通过 让您的 bean 实现 SmartLifeCycle

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

参考:

Interesting Question. I'd say you should be able to do it by letting your bean implement SmartLifeCycle.

That way, if your int getPhase(); method returns Integer.MAX_VALUE, it will be among the first to be called when the ApplicationContext finally shuts down.

Reference:

篱下浅笙歌 2024-11-12 18:09:50

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

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

onApplicationEvent将在bean销毁之前调用,您可以在spring的org.springframework.context.support.AbstractApplicationContext#doClose方法上检查它。我把它粘贴在下面,所以 ContextEvent ->生命周期->豆子毁灭。

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

I come across this same issue. After check spring's source code, U can try to implements

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

onApplicationEvent will be call before bean destory, you can check it on spring's org.springframework.context.support.AbstractApplicationContext#doClose method. I paste it below, so 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();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文