...如果需要手动构建实例,可能是第三方工厂类?以前,(泽西岛1.x),你会做这样的事情:
public class MyInjectableProvider extends PerRequestTypeInjectableProvider<Context, MyInjectable> {
public MyInjectableProvider() {
super(MyInjectable.class);
}
@Override
public Injectable<MyInjectable> getInjectable(ComponentContext ic, Context context) {
MyInjectable myInjectableInstance = //...
return new Injectable<MyInjectable>() {
@Override
public MyInjectable getValue() {
return myInjectableInstance;
}
};
}
}
匿名本地类能够访问要在某个范围内返回的实例。当您不使用具有默认构造函数的类时,这很有用,但它们需要基于每个请求构建。
Jersey 2.0切换到HK2作为依赖注入框架,但是,迁移页面(https://jersey.java.net/documentation/latest/migration.html)没有提供这种绑定的示例,HK2文档没有提供使用示例一个AbstractBinder。
为了进一步阐述,我正在尝试向我的资源提供资源本地的,与容器无关的JPA EntityManager实例。这些必须从单件工厂类中获取,并且应该只针对单个“工作单元”,这在我的情况下是一个请求。我知道有一些解决方法(只是注入工厂,或绑定到threadlocal),但我发现以前的解决方案很优雅,如果可能的话我想重新创建它。
修改
在仔细研究了HK2 javadocs后,我发现类似的东西可以实现如下:
public class MyInjectableProvider extends AbstractBinder
implements Factory<MyInjectable> {
@Override
protected void configure() {
bindFactory(this).to(MyInjectable.class);
}
@Override
public MyInjectable provide() {
return getMyInjectable();
}
@Override
public void dispose(MyInjectable instance) {}
}
注册它......
public class MyResourceConfig extends ResourceConfig {
public MyResourceConfig() {
register(new MyInjectableProvider());
}
}
这“似乎有效”,但似乎有点不清楚。例如,从不调用dispose()。此外,此绑定似乎隐含地表现为RequestScoped。将配置修改为bindFactory(this).to(MyInjectable.class).in(RequestScoped.class);
似乎并未实际更改行为。我错过了什么,或者这是预期的解决方案?
答案 0 :(得分:2)
代替Factory<T>.dispose(T)
,注册注射CloseableService
可能会完成您想要的大部分工作。将需要CloseableFactory
适配器。退出请求范围时,CloseableService
closes()
所有注册资源。
有关具体示例,请参阅下面的ConnectionFactory
。
import org.glassfish.hk2.api.Factory;
import org.glassfish.jersey.server.CloseableService;
import javax.inject.Inject;
import javax.ws.rs.InternalServerErrorException;
import java.sql.Connection;
import java.sql.SQLException;
import static com.google.common.base.Preconditions.checkNotNull;
public class ConnectionFactory implements Factory<Connection> {
private final CloseableService closeableService;
@Inject
public ConnectionFactory(CloseableService closeableService) {
this.closeableService = checkNotNull(closeableService);
}
public Connection provide() {
final Connection connection;
try {
connection = acquireConnection();
} catch (SQLException e) {
throw new InternalServerErrorException(e);
}
try {
closeableService.add(new CloseableConnection(connection));
} catch (Throwable t) {
closeQuietly(connection);
throw runtime(t);
}
return connection;
}
public void dispose(Connection connection) {
closeQuietly(connection);
}
private static RuntimeException runtime(Throwable t) {
throw ConnectionFactory.<RuntimeException>unchecked(t);
}
private static <T extends Throwable> T unchecked(Throwable t) throws T {
throw (T) t;
}
private static void closeQuietly(Connection connection) {
try {
connection.close();
} catch (SQLException ignore) {}
}
}
以下是CloseableFactory
的一般性较低版本 - CloseableConnection
。
import java.io.Closeable;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import static com.google.common.base.Preconditions.checkNotNull;
public final class CloseableConnection implements Closeable {
private final Connection connection;
public CloseableConnection(Connection connection) {
this.connection = checkNotNull(connection);
}
public void close() throws IOException {
try {
connection.close();
} catch (SQLException e) {
throw new IOException(e);
}
}
}