gpt4 book ai didi

java - Guice 子模块阻止继承绑定(bind)

转载 作者:搜寻专家 更新时间:2023-10-31 19:28:53 26 4
gpt4 key购买 nike

我想在不引入注释或使用字符串键名的情况下完成以下操作,是否可以使用 Guice?此外,为 MyService 引入第三个私有(private)模块及其 ExecutorService 绑定(bind)不太理想,因为我希望 ExecutorService 成为整个应用程序的单例,而不是注入(inject)仅在 MyService 中,但可能还有其他类,例如 MyOtherService

public class Main {
public static void main(String[] args) {
final Injector injector = Guice.createInjector(new MyAppModule());
final MyService service = injector.getInstance(MyService.class);
service.printInternals();
// Ideally this would print something like:
// My Executor: ExecutorImplClass@1
// Red Executor: ExecutorImplClass@2
// Blue Executor: ExecutorImplClass@3
}
}

public class MyAppModule extends PrivateModule {
@Override
protected void configure() {
install(new RedModule());
install(new BlueModule());
bind(ExecutorService.class).toInstance(Executors.newSingleThreadExecutor());
bind(MyService.class).to(MyServiceImpl.class);
expose(MyService.class);
}
}

public class BlueModule extends PrivateModule {
@Override
protected void configure() {
bind(ExecutorService.class).toInstance(Executors.newSingleThreadExecutor());
bind(BlueService.class).to(BlueServiceImpl.class);
expose(BlueService.class);
}
}

public interface BlueService {
void printInternals();
}

class BlueServiceImpl implements BlueService {
private final ExecutorService executor;

@Inject
BlueServiceImpl(final ExecutorService executor) {
this.executor = executor;
}

@Override
public void printInternals() {
System.out.println("Blue Executor: " + executor);
}
}

RedModule、RedService 和 RedServiceImpl 都反射(reflect)了它们各自的 Blue* 类。

最后是 MyService,它使用了 RedBlue Services 以及它自己的 ExecutorService:

class MyServiceImpl implements MyService {
private final ExecutorService executor;
private final RedService red;
private final BlueService blue;

@Inject
MyServiceImpl(final ExecutorService executor, final RedService red, final BlueService blue) {
this.executor = executor;
this.red = red;
this.blue = blue;
}

@Override
public void printInternals() {
System.out.println("My Executor: " + executor);
red.printInternals();
blue.printInternals();
}
}

最佳答案

TL;DR:将 BlueRed 模块隔离到它们自己的注入(inject)器中,并在您的 App 的 模块中创建调用 的提供程序>getInstance() 注入(inject)器的方法,用于检索您的应用所需的服务。

现在我是如何找到解决方案的:

私有(private)模块可以帮助您实现大部分目标,请参阅 my experimentation .

但是……

假设我正在开发一个应用程序,它使用服务来做一些非常棒的事情。

public class MyAppModule extends PrivateModule {
bind(AwesomeService.class).to(AwesomeServiceImpl.class);
expose(AwesomeService.class);
}

现在我的 AwesomeService 的特定实现需要一些东西才能像它一样棒:

class AwesomeServiceImpl implements AwesomeService {
@Inject
AwesomeServiceImpl(BlueService blue, RedService red, ExecutorService executor) { ... }
}

碰巧一些杰出的 Internet 居民创建了一个独立的 jar,其中包含提供 RedBlue 服务的 Guice 模块。所以我将把 jar 添加到我的类路径并修改 MyAppModule 以便我的 AwesomeService 可以使用第三方 RedBlue 服务:

public class MyAppModule extends PrivateModule {
install(new RedModule());
install(new BlueModule());
bind(AwesomeService.class).to(AwesomeServiceImpl.class);
expose(AwesomeService.class);
}

我的 AwesomeService 还需要一个 ExecutorService,所以我现在先绑定(bind)到一个显式实例:

public class MyAppModule extends PrivateModule {
install(new RedModule());
install(new BlueModule());
bind(ExecutorService.class).toInstance(Executors.newSingleThreadExecutor());
bind(AwesomeService.class).to(AwesomeServiceImpl.class);
expose(AwesomeService.class);
}

啊,但是该死,显然我的互联网好 friend 决定不仅公开我的 AwesomeService 需要的 RedServiceBlueService 绑定(bind),而且还有一个我不想要的 ExecutorService:

public final class BlueModule extends PrivateModule {
bind(ExecutorService.class).toInstance(Executors.newCachedThreadPool());
bind(BlueService.class).to(BlueServiceImpl.class);

expose(ExecutorService.class);
expose(BlueService.class);
}

public final class RedModule extends PrivateModule {
bind(ExecutorService.class).toInstance(Executors.newCachedThreadPool());
bind(RedService.class).to(RedServiceImpl.class);

expose(ExecutorService.class);
expose(RedService.class);
}

没问题,我只是将他的模块包装在一个私有(private)模块中,只公开我关心的服务:

public class MyAppModule extends PrivateModule {
install(new PrivateModule() {
install(new RedModule());
expose(RedService.class);
});
install(new PrivateModule() {
install(new BlueModule());
expose(BlueService.class);
});
bind(ExecutorService.class).toInstance(Executors.newSingleThreadExecutor());
bind(AwesomeService.class).to(AwesomeServiceImpl.class);
expose(AwesomeService.class);
}

啊,但该死的,我的 ExecutorService 绑定(bind)被我的私有(private)包装器模块继承,并且与 RedModuleBlueModule< 中定义的内部绑定(bind)冲突。我想我可以在我的 AwesomeService 构造函数中注释或命名我的 ExecutorService,但是如果我想让 ExecutorService 成为一个在我的整个系统中共享的单例怎么办?应用程序,通过 20、30 或 40 种不同的服务。我将不得不用这个注解污染我所有的 ExecutorService 注入(inject)。

或者我想我可以做一些诡计,交错绑定(bind)并隐藏 ExecutorService 这样它就不会与 RedModuleExecutorService 冲突> 和 BlueModule 创建,但这似乎是错误的:

public class MyAppModule extends PrivateModule {
install(new PrivateModule() {
install(new RedModule());
expose(RedService.class);
});
install(new PrivateModule() {
install(new BlueModule());
expose(BlueService.class);
});

final Module myAppExecutorService = new PrivateModule() {
bind(ExecutorService.class).toInstance(Executors.newSingleThreadExecutor());
expose(ExecutorService.class);
};
install(new PrivateModule() {
install(myAppExecutorService);
bind(AwesomeService.class).to(AwesomeServiceImpl.class);
expose(AwesomeService.class);
});
expose(AwesomeService.class);
}

一定有更好的方法……而且有……注入(inject)器!

public class MyAppModule extends PrivateModule {
private static final Injector blueInjector = Guice.createInjector(new BlueModule());
private static final Injector redInjector = Guice.createInjector(new RedModule());

@Override
protected void configure()
{
bind(ExecutorService.class).toInstance(Executors.newSingleThreadExecutor());
bind(MyService.class).to(MyServiceImpl.class);
bind(MyOtherService.class).to(MyOtherServiceImpl.class);
expose(MyService.class);
expose(MyOtherService.class);
}

@Provides
RedService getRedService()
{
return redInjector.getInstance(RedService.class);
}

@Provides
BlueService getBlueService()
{
return blueInjector.getInstance(BlueService.class);
}
}

现在 BlueModuleRedModule 中绑定(bind)和暴露的 ExecutorService 不会污染我的 AwesomeService ExecutorService,但我仍然可以获得我非常想要的那些多汁的 BlueServiceRedService 类。

希望这能在将来为其他人节省一些时间!

关于java - Guice 子模块阻止继承绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16230334/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com