这是否有正确的名称?
public class SomethingFactory {
private final String someParameter;
public SomethingFactory(String someParameter) {
this.someParameter = someParameter;
}
public Something create(String anotherParameter) {
return new Something(someParameter, anotherParameter);
}
}
public class Something {
public final String someParameter;
public final String anotherParameter;
public Something(String someParameter, String anotherParameter) {
this.someParameter = someParameter;
this.anotherParameter = anotherParameter;
}
}
与常规工厂的不同之处在于,无论何时需要创建对象,都必须在运行时指定一个参数来创建()。
通过这种方式,您可以在Spring上下文中创建单例工厂,在那里配置前半部分参数,然后在调用create()时在运行时完成其余参数。
如果您感到好奇,为什么我首先需要它?
我以前在Spring上下文中有常规的单例对象,并且在每个请求的线程应用程序中都很好,但是现在我的整个应用程序都是非阻塞的,我不能使用ThreadLocal来保存整个请求处理中的内容。例如,使用Apache StopWatch保存有关时间的信息。
我需要找到一种方法来实现"请求范围"在多线程,非阻塞环境中,无需在我的代码的每个方法(这将是愚蠢的)中提供表示范围的对象。
所以我想让我们让每个(服务)类在构造函数中获取这个范围对象,让我们在每个请求中创建这些类,但这违背了单例。我们正在谈论的单身人士就像是记录用户的UserService,或者是生成数字签名的CryptoService。它们在Spring中配置一次,需要时注入,一切都还可以。但是现在我需要在他们需要的每个方法中创建这些服务类,而不是仅仅引用注入的单例实例。
所以我想我们会把那些单身人士称为"模板"无论何时需要实际实例,都可以调用create()来提供所述范围对象。这样每个类都有scope对象,你只需要继续将它提供给其他模板服务构造函数。完整的东西看起来像这样:
public class UserService {
private final Scope scope;
private final Template t;
private UserService(Template t, Scope scope) {
this.t = t;
this.scope = scope;
}
public void login(String username) {
scope.timings.probe("before calling database");
t.database.doSomething(username);
scope.timings.probe("after calling database");
}
public static class Template { /* The singleton configured in Spring */
private Database database;
public void setDatabase(Database database) { /* Injected by Spring */
this.database = database;
}
public UserService create(Scope scope) {
return new UserService(this, scope);
}
}
}
public class LoginHttpHandler { /* Also a Spring singleton */
private UserService.Template userServiceT;
public void setUserServiceT(UserService.Template userServiceT) { /* Injected by Spring */
this.userServiceT = userServiceT;
}
public void handle(HttpContext context) { /* Called on every http request */
userServiceT.create(context.scope).login("billgates");
}
}
在Spring中,您只需使用所需的相应依赖项描述UserService.Template bean,然后在需要UserService时注入该bean。
我只是称之为"模板"。但总是像我一样,我觉得它已经完成了。它有什么名字吗?
答案 0 :(得分:0)
这几乎是Guice' AssistedInject的例子:
public class RealPaymentFactory implements PaymentFactory {
private final Provider<CreditService> creditServiceProvider;
private final Provider<AuthService> authServiceProvider;
@Inject
public RealPaymentFactory(Provider<CreditService> creditServiceProvider, Provider<AuthService> authServiceProvider) {
this.creditServiceProvider = creditServiceProvider;
this.authServiceProvider = authServiceProvider;
}
public Payment create(Date startDate, Money amount) {
return new RealPayment(creditServiceProvider.get(), authServiceProvider.get(), startDate, amount);
}
}
public class RealPayment implements Payment {
public RealPayment(
CreditService creditService, // from the Injector
AuthService authService, // from the Injector
Date startDate, // from the instance's creator
Money amount) // from the instance's creator
{
...
}
}
辅助注射用于在构建时创建需要额外参数的类&#34;
此外,这与partial application类似,因此您可以使用PartialUserService
创建UserService
。