我想将一个实现AutoClosable的对象注入一个球衣资源,并在请求结束时由框架自动关闭。
基本上这是一个数据库连接提供程序,应在请求结束时关闭打开的连接
使用@inject
注释时,对象未关闭
这有可能,怎么样?
答案 0 :(得分:2)
您可以使用CloseableService
可以在请求范围内使用该服务,以便在请求超出范围时添加要关闭的
Closeable
实例,更具体地说,在处理请求并返回响应之后
您可以将此服务注入Factory
,您可以在其中创建您的提供商。只需将提供商添加到CloseableService
内的Factory
,它就会在请求结束时关闭。
public class ConnectionProviderFactory implements Factory<ConnectionProvider> {
@Inject
private CloseableService closeableService;
@Override
public ConnectionProvider provider() {
ConnectionProvider provider = new ConnectionProvider();
closeableService.add(provider);
return provider;
}
@Override
public void dispose(ConnectionProvider provider) {
}
}
然后只需在工具栏中注册工厂
bindFactory(ConnectionProviderFactory.class)
.to(ConnectionProvider.class)
.in(RequestScoped.class);
请注意,Factory
类具有dispose
方法。我不是百分之百肯定它的工作原理的细节,因为我有经验,有时它被调用,有时它不是。我发现CloseableService
更可靠。也许有一天我会去挖掘,试图为自己解决dispose
方法的奥秘。
不完全确定您的做法有何不同,但以下是使用Jersey Test Framework进行的完整测试。像任何其他JUnit测试一样运行它。只有差异而不是AutoCloseable
,我使用Closeable
import java.io.Closeable;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import org.glassfish.hk2.api.Factory;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.filter.LoggingFilter;
import org.glassfish.jersey.process.internal.RequestScoped;
import org.glassfish.jersey.server.CloseableService;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class InjectCloseableTest extends JerseyTest {
public static final String CONNECTION_MSG = "Connection";
public static class ConnectionProvider implements Closeable {
private static final Logger LOGGER
= Logger.getLogger(ConnectionProvider.class.getName());
public String getConnection() {
return CONNECTION_MSG;
}
@Override
public void close() {
LOGGER.info("---- Closing Connection ----");
}
}
@Path("connection")
public static class ConnectionResource {
@Inject
ConnectionProvider connectionProvider;
@GET
public String get() {
return connectionProvider.getConnection();
}
}
public static class ConnectionProviderFactory implements Factory<ConnectionProvider> {
@Inject
CloseableService closeableService;
@Override
public ConnectionProvider provide() {
ConnectionProvider provider = new ConnectionProvider();
closeableService.add(provider);
return provider;
}
@Override
public void dispose(ConnectionProvider t) {}
}
@Override
public ResourceConfig configure() {
return new ResourceConfig(ConnectionResource.class)
.register(new LoggingFilter(Logger.getAnonymousLogger(), true))
.register(new AbstractBinder() {
@Override
protected void configure() {
bindFactory(ConnectionProviderFactory.class)
.to(ConnectionProvider.class)
.in(RequestScoped.class);
}
});
}
@Test
public void doit() {
Response response = target("connection").request().get();
assertEquals(200, response.getStatus());
assertEquals(CONNECTION_MSG, response.readEntity(String.class));
response.close();
}
}
这是您运行它所需的唯一依赖项。
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>${jersey2.version}</version>
<scope>test</scope>
</dependency>
答案 1 :(得分:0)
我认为您正在寻找@Disposes
注释。
@Disposes
注释标识disposer method的已处置参数,允许应用程序对producer method或producer field返回的对象执行自定义清理。当范围结束时,将自动调用disposer方法。
我不知道您的数据库连接提供程序是什么样的,但是这个示例将为您提供有关如何使用@Disposes
注释的一般概念:
public class Resources {
@Produces
@UserDatabase
@RequestScoped
@PersistenceContext
private EntityManager em;
public void close(@Disposes @UserDatabase EntityManager em) {
em.close();
}
}