@RequestScopedCallable中对象的引用?seedMap?是否意味着覆盖默认绑定?Gil*_*ili 12
回答我自己的问题:
static或者顶级课程是你的朋友.Callable传递给ServletScopes.scopeRequest()之前注入.因此,您必须小心Callable包含哪些字段.更多关于此的信息.seedMap允许您将非范围对象注入范围.这很危险,所以要注意你注射的东西.那么,最好的方法是什么?
如果您不需要将用户对象传递到Callable:注入Callable请求范围外部,并将其传递给ServletScopes.scopeRequest().该Callable只可参考Provider<Foo>,而不是Foo,否则你会与请求范围之外注入情况下结束.
如果您需要将用户对象传递给Callable,请继续阅读.
假设您有一个将名称插入数据库的方法.我们有两种方式将名称传递给Callable.
方法1:使用子模块传递用户对象:
定义InsertName,Callable插入数据库的a:
@RequestScoped
private static class InsertName implements Callable<Boolean>
{
private final String name;
private final Connection connection;
@Inject
public InsertName(@Named("name") String name, Connection connection)
{
this.name = name;
this.connection = connection;
}
@Override
public Boolean call()
{
try
{
boolean nameAlreadyExists = ...;
if (!nameAlreadyExists)
{
// insert the name
return true;
}
return false;
}
finally
{
connection.close();
}
}
}
Run Code Online (Sandbox Code Playgroud)绑定子模块中的所有用户对象,并使用RequestInjector.scopeRequest()来调用可调用范围:
requestInjector.scopeRequest(InsertName.class, new AbstractModule()
{
@Override
protected void configure()
{
bind(String.class).annotatedWith(Names.named("name")).toInstance("John");
}
})
Run Code Online (Sandbox Code Playgroud)我们实例化一个RequestInjector请求外,它,反过来,注射第二Callable 内部请求.第二个Callable可以Foo直接引用(不需要提供者),因为它是在请求范围内注入的.
import com.google.common.base.Preconditions;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.servlet.ServletScopes;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.Callable;
/**
* Injects a Callable into a non-HTTP request scope.
* <p/>
* @author Gili Tzabari
*/
public final class RequestInjector
{
private final Map<Key<?>, Object> seedMap = Collections.emptyMap();
private final Injector injector;
/**
* Creates a new RequestInjector.
*/
@Inject
private RequestInjector(Injector injector)
{
this.injector = injector;
}
/**
* Scopes a Callable in a non-HTTP request scope.
* <p/>
* @param <V> the type of object returned by the Callable
* @param callable the class to inject and execute in the request scope
* @param modules additional modules to install into the request scope
* @return a wrapper that invokes delegate in the request scope
*/
public <V> Callable<V> scopeRequest(final Class<? extends Callable<V>> callable,
final Module... modules)
{
Preconditions.checkNotNull(callable, "callable may not be null");
return ServletScopes.scopeRequest(new Callable<V>()
{
@Override
public V call() throws Exception
{
return injector.createChildInjector(modules).getInstance(callable).call();
}
}, seedMap);
}
}
Run Code Online (Sandbox Code Playgroud)
方法2:Callable在引用的请求之外注入Provider<Foo>.call()然后get(),该方法可以是请求范围内的实际值.对象对象通过a传递seedMap(我个人觉得这种方法反直觉):
定义InsertName,Callable插入数据库的a.请注意,与方法1不同,我们必须使用Providers:
@RequestScoped
private static class InsertName implements Callable<Boolean>
{
private final Provider<String> name;
private final Provider<Connection> connection;
@Inject
public InsertName(@Named("name") Provider<String> name, Provider<Connection> connection)
{
this.name = name;
this.connection = connection;
}
@Override
public Boolean call()
{
try
{
boolean nameAlreadyExists = ...;
if (!nameAlreadyExists)
{
// insert the name
return true;
}
return false;
}
finally
{
connection.close();
}
}
}
Run Code Online (Sandbox Code Playgroud)为您要传入的类型创建伪造的绑定.如果不这样做,您将获得:No implementation for String annotated with @com.google.inject.name.Named(value=name) was bound. https://stackoverflow.com/a/9014552/14731解释了为什么需要这样做.
使用所需的值填充seedMap:
ImmutableMap<Key<?>, Object> seedMap = ImmutableMap.<Key<?>, Object>of(Key.get(String.class, Names.named("name")), "john");
Run Code Online (Sandbox Code Playgroud)调用ServletScopes.scopeRequest():
ServletScopes.scopeRequest(injector.getInstance(InsertName.class), seedMap);
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
2892 次 |
| 最近记录: |