请求scoped bean不会调用@PreDestroy方法

时间:2015-09-09 08:14:41

标签: java spring

我已经创建了一个请求范围的bean,它应该在请求结束后调用方法。 我尝试使用@PreDestroy注释方法这样做,但这不起作用。

@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class SessionProvider {
    @PreDestroy
    public void cleanup() {
        // DO STUFF
    }
}

如何实现所描述的行为?

2 个答案:

答案 0 :(得分:0)

我通过注册自己的RequestContextListener解决了这个问题:

public class MyRequestContextListener
        extends RequestContextListener {

    @Override
    public void requestDestroyed( ServletRequestEvent requestEvent ) {

        super.requestDestroyed( requestEvent );
        applicationContext.getBean( SessionProvider.class ).cleanup();
    }
}

希望这有助于其他人。

最好的问候,克里斯

答案 1 :(得分:0)

如果您正在使用过滤器或拦截器,则可以避免编写自定义请求上下文侦听器,而是在过滤器中注入请求范围的bean并在那里进行清理。

例如,在我们使用jersey的rest应用程序中,我们以下列方式释放应用程序中的资源 -

public class MyResourceManager implements ContainerResponseFilter {

    /* MyCustomIO class is defined to be request 
    scoped using proxyMode = TARGET_CLASS */
    @Inject  // Use @Autowired if you aren't using JSR-330 annotations
    private MyCustomIO myIO;

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
        // Perform your clean up here
        myIO.cleanup();
    }

}

有些人可能认为过滤器不适用于此,但我们意识到有时过滤器是在“请求”级别进行资源清理的最佳位置 - 这是因为通常我们的目标是释放资源请求完成后(或在完成之前)在请求期间接收。依赖于bean的destroy方法回调可能不一定在请求完成时释放资源,因为我们对垃圾收集没有任何控制。

此外,由于在过滤器执行后发生的唯一主要事情是响应对象序列化,它不需要任何IO,因此在此时清理资源而不用担心它们仍在使用中是相当安全的。 但是,当然,此解决方案不能用于会话或应用程序级别的清理。