我对Guice来说相对较新,有些事情仍然让我很难过。 我特别的问题是,你如何在Guice中处理嵌套注射。 示例:
A类通过@Inject
使用B类,B类使用C类。
显式:
我的模块,我绑定到提供商。
public class ModuleBinder extends AbstractModule {
@Override
protected void configure() {
bind(DatabaseControllerInterface.class)
.toProvider(DatabaseControllerProvider.class).asEagerSingleton();
bind(AnalyzerInterface.class)
.toProvider(AnalyzerProvider.class).asEagerSingleton();
bind(SystemAdministrationInterface.class)
.toProvider(SystemAdministrationProvider.class).asEagerSingleton();
bind(LogInServiceInterface.class)
.toProvider(LogInServiceProvider.class);
}
}
DatabaseControllerProvider:
public class DatabaseControllerProvider implements Provider<DatabaseControllerInterface> {
@Override
public DatabaseControllerInterface get() {
return new DatabaseControllerImpl();
}
}
LogInServiceProvider:
public class LogInServiceProvider implements Provider<LogInServiceInterface> {
@Override
public LogInServiceInterface get() {
return new LogInServiceImpl();
}
}
最后,LogInService使用:
public class LogInServiceImpl implements LogInServiceInterface{
@Inject
private DatabaseControllerProvider databaseControllerProvider;
private final DatabaseControllerInterface databaseController;
public LogInServiceImpl() {
this.databaseController = databaseControllerProvider.get();
}
@Override
public User register(final String mail, final String userName, final String password) {
databaseController.registerUser(userName, mail, password, UserRole.ADMIN);
}
}
然后打电话:
public class Test() {
public static test() {
final Injector injector = Guice.createInjector(new ModuleBinder());
logInService = injector.getInstance(LogInServiceInterface.class);
logInService.registerUser("test", "test", "test");
}
}
我知道你们中的大多数人都会厌倦那些代码,但是,嘿,我是Guice的初学者,所以请温柔地对待我。
我想使用Constructor注入,我已经意识到现场注入被认为是&#34; evil&#34;。您是否知道如何通过保留提供商(我需要它们)来实现这一目标?
使用示例中的注入对&#34; second&#34;级别,DatabaseControllerImpl
中的LogInServiceImpl
为null
。
我配错了吗?我是否误解了提供和/或模块的用法?
我希望有人可以而且想要帮助我。如果您需要更多信息,请发表评论。
最诚挚的问候,
JosefRucksack
答案 0 :(得分:0)
您的直接答案:您在提供商中呼叫new T();
,但不支持现场注入。
首先,真正节省时间:不要保留明确的提供商。如果您绑定了T
,Guice允许您为Provider
注入Injector.getProvider
或致电T
,即使您尚未自己明确创建提供商。请参阅维基上的Built-In Bindings页面,
或Injector docs(强调我的):
包含多个默认绑定:
- 此Injector实例本身
Provider<T>
类型T
的每个绑定的public class ModuleBinder extends AbstractModule { @Override protected void configure() { bind(DatabaseControllerInterface.class) .to(DatabaseControllerImpl.class).asEagerSingleton(); bind(AnalyzerInterface.class) .to(AnalyzerImpl.class).asEagerSingleton(); bind(SystemAdministrationInterface.class) .to(SystemAdministrationImpl.class).asEagerSingleton(); bind(LogInServiceInterface.class) .to(LogInServiceImpl.class); } }
- 正在注入的类的记录器
- 创建注射器的阶段
相反,这样做:
T
您现在可以选择同一个注入Provider<T>
或getInstance
并根据需要致电getProvider
或@Inject
。
如果您的提供商绝对必要,特别是如果他们实际从其他系统或服务定位器接收实例,则另一个选项是将public class LogInServiceProvider implements Provider<LogInServiceInterface> {
@Inject MembersInjector<LogInServiceImpl> logInServiceImplInjector;
@Override
public LogInServiceInterface get() {
LogInServiceImpl logInServiceImpl = YourExternalDep.getLogInService();
logInServiceImplInjector.injectMembers(logInServiceImpl);
return logInServiceImpl;
}
}
字段添加到其中,如同Provider bindings wiki page并将它们传递给您的构造函数,或仅传递给inject a MembersInjector<T>
:
{{1}}
但是,此显式提供程序解决方案不是惯用的Guice,只应与外部或遗留代码一起使用。 Guice存在的全部理由是使样板自动化,让您的系统清晰灵活地融合在一起。提供商是一个实施细节;让Guice为你创造它们。