首页 > 解决方案 > 提供(绑定到 guice 模块)已经创建的实例是否更方便?

问题描述

我在桌面应用程序中使用 Guice,我想为服务添加通用绑定。这些服务是单例(绑定)实例,并在应用程序启动期间手动创建。我只使用 IoC 容器来创建 GUI。我手动创建这些服务,因为在启动期间我想发布进度。

由于 GUI 使用这些服务,它们必须绑定到 guice GUI 模块。

如果不对每个类使用带有 setter 和 getter 的类,我想不出一种方法来绑定它们。

假设我有 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”的方法。因为 bind 方法返回一个通用的构建器。Guice(或 Guava)是否为这种情况提供了一些东西?

我知道我可以使用 Guice 创建服务并使用注入/类型侦听器发布进度,但是包含所有服务的业务包(模块)没有 javax.inject 依赖项。另外,这些服务的创建很复杂,因此最好手动创建。此外,在 Guice 模块中发布 GUI 进度听起来过于复杂,无法在 Guice 模块中使用。

那么,有没有办法呢?除了System.out.println上面的片段之外,还有一个手动创建的启动画面。

标签: javadependency-injectionguavaguice

解决方案


只需将构建每个服务 impl 的代码移动到相应服务接口的 @Provides 方法主体内即可。您提到希望这些是单例,因此您还需要使用 @Singleton 注释提供程序方法。

至于地图,你可以用 Multibinder 做类似的事情,但我想在推荐之前更好地理解你的设计。


推荐阅读