在不修改 Interface/Impl class 的情况下将参数传递给 Guice 中的构造函数
Pass Parameters to constructor in Guice with no modifications to the Interface/Impl class
我想在使用 Guice 中的 Impl 绑定接口时传递构造函数参数。
有几个解决方案,但我没有这些 interfaces/Impl 的代码访问权限。
它们是由其他团队开发的,我已将它们包含在我的项目中。
- @Named/@Assisted - 两者都需要更改 Impl 的源代码(构造函数)以包含这些注释。 (我无权访问此代码)
- 实现 Provider - 通过加载所需的参数实现 Impl 的 returns 实例。 这有效。
但问题是我有 200 多个这样的现有 DI,我将不得不编写 200 多个提供程序。
目前我们正在使用 Spring DI 并且正在迁移到 Guice。
所以我需要定义类似
的东西
<bean name="clientWrapper" class="com.wrapper.client.ClientWrapper">
<constructor-arg index="0" value="${server.ip}" />
<constructor-arg index="1" value="${server.port}" />
</bean>
在 Guice 中。但是传递那些构造函数参数。
bind(IClientWrapper.class).to(ClientWrapper.class);
如何在不使用提供程序的情况下实现这一点?
我认为你最好的选择是Provides
methods and toConstructor
binding。
当您的对象具有无法单独通过类型解决的依赖项时,请使用 @Provides
方法绑定。
public class ProvidesModule extends AbstractModule {
@Provides
IClientWrapper clientWrapper(@Named("server.ip") String ip,
@Named("server.port") int port) {
return new ClientWrapper(ip, port);
}
}
在整体代码大小中,这并不比 Spring 多很多,而且类型安全。
当构造函数仅具有可以单独按类型计算的依赖项时,则使用 toConstructor 绑定
protected void configure() {
try {
bind(TransactionLog.class).toConstructor(
DatabaseTransactionLog.class.getConstructor(DatabaseConnection.class));
} catch (NoSuchMethodException e) {
addError(e);
}
}
最后一个选项:
我们的遗产:
interface LegacyThing {
}
class LegacyThingImp implements LegacyThing {
public LegacyThingImp(String test) {
System.out.println(test);
}
}
GitHub 是我的魔术师。这需要一个实现 class 和依赖项列表(如 Key
s),然后通过 Magic(或反射)找到正确的构造函数。
public class TestMagic {
public static void main(final String... arg) {
Guice.createInjector(
new AbstractModule() {
@Override
protected void configure() {
bind(String.class).annotatedWith(Names.named("testString")).toInstance("Guice!");
bind(LegacyThing.class).toProvider(new MagicLegacyProvider<>(LegacyThingImp.class, Key.get(String.class, Names.named("testString"))));
}
}).getInstance(LegacyThing.class);
}
}
我想在使用 Guice 中的 Impl 绑定接口时传递构造函数参数。
有几个解决方案,但我没有这些 interfaces/Impl 的代码访问权限。 它们是由其他团队开发的,我已将它们包含在我的项目中。
- @Named/@Assisted - 两者都需要更改 Impl 的源代码(构造函数)以包含这些注释。 (我无权访问此代码)
- 实现 Provider - 通过加载所需的参数实现 Impl 的 returns 实例。 这有效。 但问题是我有 200 多个这样的现有 DI,我将不得不编写 200 多个提供程序。
目前我们正在使用 Spring DI 并且正在迁移到 Guice。 所以我需要定义类似
的东西<bean name="clientWrapper" class="com.wrapper.client.ClientWrapper">
<constructor-arg index="0" value="${server.ip}" />
<constructor-arg index="1" value="${server.port}" />
</bean>
在 Guice 中。但是传递那些构造函数参数。
bind(IClientWrapper.class).to(ClientWrapper.class);
如何在不使用提供程序的情况下实现这一点?
我认为你最好的选择是Provides
methods and toConstructor
binding。
当您的对象具有无法单独通过类型解决的依赖项时,请使用 @Provides
方法绑定。
public class ProvidesModule extends AbstractModule {
@Provides
IClientWrapper clientWrapper(@Named("server.ip") String ip,
@Named("server.port") int port) {
return new ClientWrapper(ip, port);
}
}
在整体代码大小中,这并不比 Spring 多很多,而且类型安全。
当构造函数仅具有可以单独按类型计算的依赖项时,则使用 toConstructor 绑定
protected void configure() {
try {
bind(TransactionLog.class).toConstructor(
DatabaseTransactionLog.class.getConstructor(DatabaseConnection.class));
} catch (NoSuchMethodException e) {
addError(e);
}
}
最后一个选项:
我们的遗产:
interface LegacyThing {
}
class LegacyThingImp implements LegacyThing {
public LegacyThingImp(String test) {
System.out.println(test);
}
}
GitHub 是我的魔术师。这需要一个实现 class 和依赖项列表(如 Key
s),然后通过 Magic(或反射)找到正确的构造函数。
public class TestMagic {
public static void main(final String... arg) {
Guice.createInjector(
new AbstractModule() {
@Override
protected void configure() {
bind(String.class).annotatedWith(Names.named("testString")).toInstance("Guice!");
bind(LegacyThing.class).toProvider(new MagicLegacyProvider<>(LegacyThingImp.class, Key.get(String.class, Names.named("testString"))));
}
}).getInstance(LegacyThing.class);
}
}