有没有更方便地提供(绑定到 guice 模块)已经创建的实例?
Is there a more convinient to provide (bind to guice module) already created instances?
我在桌面应用程序中使用 Guice,我想为服务添加通用绑定。这些服务是单例(绑定)实例,是在应用程序启动期间手动创建的。我只使用 IoC 容器来创建 GUI。我手动创建这些服务,因为在启动期间我想发布进度。
由于 GUI 使用这些服务,它们必须绑定到 guice GUI 模块。
我想不出不使用 class 与 setter 和 getter 来绑定它们的方法,每个 class.
假设我有 CarService 和 EngineService。我现在拥有的是:
public class GuiceServices {
public static void main(String[] args) {
ServicesModule servicesModule = new ServicesModule();
CarService carService = new CarServiceImpl();
servicesModule.setCarService(carService);
System.out.println("progress: 50%");
EngineService engineService = new EngineServiceImpl();
servicesModule.setEngineService(engineService);
System.out.println("Progress: 100%");
Injector i = Guice.createInjector(new GuiModule(), servicesModule);
i.getInstance(MainView.class).show();
}
class ServicesModule extends AbstractModule {
private CarService carService;
private EngineService engineService;
@Override
protected void configure() {
}
public void setCarService(CarService carService) {
this.carService = carService;
}
public void setEngineService(EngineService engineService) {
this.engineService = engineService;
}
@Provides
public CarService getCarService() {
return carService;
}
@Provides
public EngineService getEngineService() {
return engineService;
}
}
}
但这有点痛苦,因为这些服务很多。
有没有办法避免这种情况?
理想情况下,地图更方便。类似于:
public class GuiceServices {
public static void main(String[] args) {
ServicesMap servicesMap = new ServicesMap();
CarService carService = new CarServiceImpl();
servicesMap.put(CarService.class, carService);
System.out.println("progress: 50%");
EngineService engineService = new EngineServiceImpl();
servicesMap.put(EngineService.class, engineService);
System.out.println("Progress: 100%");
Injector i = Guice.createInjector(new GuiModule(), new ServicesModule(servicesMap));
i.getInstance(MainView.class).show();
}
class ServicesModule extends AbstractModule {
private ServicesMap services;
public SerrvicesModule(ServicesMap services) {
this.services = services;
}
@Override
protected void configure() {
for (Class<?> serviceType : services.keySet())
{
bind(serviceType).toInstance(services.get(serviceType));
}
}
}
}
但是我找不到创建和实现这个“servicesMap”的方法。因为绑定方法 returns 是一个通用的构建器。 Guice(或 Guava)是否为这种情况提供了一些东西?
我知道我可以使用 Guice 创建服务并使用 injection/type 侦听器发布进度,但是我包含所有服务的业务包(模块)没有 javax.inject 依赖项。另外,创建这些服务很复杂,因此最好手动创建。此外,在 Guice 模块中发布 GUI 进度听起来太复杂了,无法在 Guice 模块中发布。
那么,有办法吗?除了上面代码段中的 System.out.println
,还有一个手动创建的启动画面。
只需将构建每个服务实现的代码移动到相应服务接口的@Provides 方法的主体中。您提到希望这些是单例,因此您还需要使用 @Singleton 注释提供者方法。
至于地图,您可以使用 Multibinder 做类似的事情,但我想在推荐之前更好地了解您的设计。
我居然自己实现了
我所做的是在模块中创建一个 List<Consumer<Binder>>
,然后在 configure()
方法中使用它们。
class ServicesModule extends AbstractModule {
private List<Consumer<Binder>> consumers = new ArrayList<>();
ServicesModule() {
}
@Override
protected void configure() {
consumers.forEach(c -> c.accept(binder()));
}
<T> void putService(Class<T> clazz, T instance) {
consumers.add(t -> t.bind(clazz).toInstance(instance));
}
}
然后,在应用程序启动期间,我可以逐渐提供服务依赖项:
public static void main(String[] args) {
ServicesModule services = new ServicesModule();
CarService carService = new CarServiceImpl();
serviceModule.putService(CarService.class, carService);
publishProgress(35);
EngineService engineService = new EngineServiceImpl(carService);
serviceModule.putService(EngineService.class, engineService);
publishProgres(50);
//...
Injector i = Guice.createInjector(new GuiModule(), services);
i.getInstance(MainView.class).show();
}
您提出的答案需要有关服务实现 类 的依赖关系的知识,以便传播到那些 类 之外。依赖注入的整个思想是封装实现依赖。例如,只有 EngineServiceImpl
应该知道它依赖于 CarService
。封装使您的代码更容易推理和测试。
class ServiceModule extends AbstractModule {
protected void configure() {
bind(CarService.class).to(CarServiceImpl.class).in(Singleton.class);
bind(EngineService.class).to(EngineServiceImpl.class).in(Singleton.class);
}
}
class CarServiceImpl implements CarService {
@Inject
CarServiceImpl() {} // Not necessary, but adds clarity
// ...
}
class EngineServiceImpl implements EngineService {
private final CarService carService;
@Inject
EngineServiceImpl(CarService carService) {
this.carService = carService;
}
// ...
}
class Main {
public static void main(String[] args) {
// I find it clearer to get the starting-point class instance from the injector
// creation chain, then operate on that instance.
MainView mainView =
Guice.createInjector(new GuiModule(), new ServiceModule())
.getInstance(MainView.class);
mainView.show();
}
}
我在桌面应用程序中使用 Guice,我想为服务添加通用绑定。这些服务是单例(绑定)实例,是在应用程序启动期间手动创建的。我只使用 IoC 容器来创建 GUI。我手动创建这些服务,因为在启动期间我想发布进度。
由于 GUI 使用这些服务,它们必须绑定到 guice GUI 模块。
我想不出不使用 class 与 setter 和 getter 来绑定它们的方法,每个 class.
假设我有 CarService 和 EngineService。我现在拥有的是:
public class GuiceServices {
public static void main(String[] args) {
ServicesModule servicesModule = new ServicesModule();
CarService carService = new CarServiceImpl();
servicesModule.setCarService(carService);
System.out.println("progress: 50%");
EngineService engineService = new EngineServiceImpl();
servicesModule.setEngineService(engineService);
System.out.println("Progress: 100%");
Injector i = Guice.createInjector(new GuiModule(), servicesModule);
i.getInstance(MainView.class).show();
}
class ServicesModule extends AbstractModule {
private CarService carService;
private EngineService engineService;
@Override
protected void configure() {
}
public void setCarService(CarService carService) {
this.carService = carService;
}
public void setEngineService(EngineService engineService) {
this.engineService = engineService;
}
@Provides
public CarService getCarService() {
return carService;
}
@Provides
public EngineService getEngineService() {
return engineService;
}
}
}
但这有点痛苦,因为这些服务很多。
有没有办法避免这种情况?
理想情况下,地图更方便。类似于:
public class GuiceServices {
public static void main(String[] args) {
ServicesMap servicesMap = new ServicesMap();
CarService carService = new CarServiceImpl();
servicesMap.put(CarService.class, carService);
System.out.println("progress: 50%");
EngineService engineService = new EngineServiceImpl();
servicesMap.put(EngineService.class, engineService);
System.out.println("Progress: 100%");
Injector i = Guice.createInjector(new GuiModule(), new ServicesModule(servicesMap));
i.getInstance(MainView.class).show();
}
class ServicesModule extends AbstractModule {
private ServicesMap services;
public SerrvicesModule(ServicesMap services) {
this.services = services;
}
@Override
protected void configure() {
for (Class<?> serviceType : services.keySet())
{
bind(serviceType).toInstance(services.get(serviceType));
}
}
}
}
但是我找不到创建和实现这个“servicesMap”的方法。因为绑定方法 returns 是一个通用的构建器。 Guice(或 Guava)是否为这种情况提供了一些东西?
我知道我可以使用 Guice 创建服务并使用 injection/type 侦听器发布进度,但是我包含所有服务的业务包(模块)没有 javax.inject 依赖项。另外,创建这些服务很复杂,因此最好手动创建。此外,在 Guice 模块中发布 GUI 进度听起来太复杂了,无法在 Guice 模块中发布。
那么,有办法吗?除了上面代码段中的 System.out.println
,还有一个手动创建的启动画面。
只需将构建每个服务实现的代码移动到相应服务接口的@Provides 方法的主体中。您提到希望这些是单例,因此您还需要使用 @Singleton 注释提供者方法。
至于地图,您可以使用 Multibinder 做类似的事情,但我想在推荐之前更好地了解您的设计。
我居然自己实现了
我所做的是在模块中创建一个 List<Consumer<Binder>>
,然后在 configure()
方法中使用它们。
class ServicesModule extends AbstractModule {
private List<Consumer<Binder>> consumers = new ArrayList<>();
ServicesModule() {
}
@Override
protected void configure() {
consumers.forEach(c -> c.accept(binder()));
}
<T> void putService(Class<T> clazz, T instance) {
consumers.add(t -> t.bind(clazz).toInstance(instance));
}
}
然后,在应用程序启动期间,我可以逐渐提供服务依赖项:
public static void main(String[] args) {
ServicesModule services = new ServicesModule();
CarService carService = new CarServiceImpl();
serviceModule.putService(CarService.class, carService);
publishProgress(35);
EngineService engineService = new EngineServiceImpl(carService);
serviceModule.putService(EngineService.class, engineService);
publishProgres(50);
//...
Injector i = Guice.createInjector(new GuiModule(), services);
i.getInstance(MainView.class).show();
}
您提出的答案需要有关服务实现 类 的依赖关系的知识,以便传播到那些 类 之外。依赖注入的整个思想是封装实现依赖。例如,只有 EngineServiceImpl
应该知道它依赖于 CarService
。封装使您的代码更容易推理和测试。
class ServiceModule extends AbstractModule {
protected void configure() {
bind(CarService.class).to(CarServiceImpl.class).in(Singleton.class);
bind(EngineService.class).to(EngineServiceImpl.class).in(Singleton.class);
}
}
class CarServiceImpl implements CarService {
@Inject
CarServiceImpl() {} // Not necessary, but adds clarity
// ...
}
class EngineServiceImpl implements EngineService {
private final CarService carService;
@Inject
EngineServiceImpl(CarService carService) {
this.carService = carService;
}
// ...
}
class Main {
public static void main(String[] args) {
// I find it clearer to get the starting-point class instance from the injector
// creation chain, then operate on that instance.
MainView mainView =
Guice.createInjector(new GuiModule(), new ServiceModule())
.getInstance(MainView.class);
mainView.show();
}
}