在 Spring bean 中是否可以有一个可以使用事务的关闭方法?
在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
有趣的问题。我想说你应该能够通过 让您的 bean 实现
SmartLifeCycle
。这样,如果您的
int getPhase();
方法返回Integer.MAX_VALUE
,那么当ApplicationContext
最终时,它将是最先被调用的方法之一关闭。参考:
回调
SmartLifeCycle
javadocsInteresting Question. I'd say you should be able to do it by letting your bean implement
SmartLifeCycle
.That way, if your
int getPhase();
method returnsInteger.MAX_VALUE
, it will be among the first to be called when theApplicationContext
finally shuts down.Reference:
callbacks
SmartLifeCycle
javadocs我遇到了同样的问题。检查spring的源代码后,您可以尝试实现
onApplicationEvent将在bean销毁之前调用,您可以在spring的org.springframework.context.support.AbstractApplicationContext#doClose方法上检查它。我把它粘贴在下面,所以 ContextEvent ->生命周期->豆子毁灭。
I come across this same issue. After check spring's source code, U can try to implements
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.