Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
166 views
in Technique[技术] by (71.8m points)

java - Is there a more convinient to provide (bind to guice module) already created instances?

I use Guice in a desktop application and I want to add generic bindings for services. These services are singleton (binded) instances and are created during application startup manually. I use the IoC container only to create the GUI. I create these services manually because during start up I want to publish the progress.

Since the GUI consume these services, they must been binded to the guice GUI module.

I can't think of a way to bind them without using a class with setter and getter for each class.

Let's say I have CarService and EngineService. What I have now is:

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;
        }
    }
}

But it is kind of pain since these services are plenty.

Is there a way to avoid this?

Ideally, a map is more convenient. Something like:

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));
            }
        }       
    }
}

But I cannot find a way to create-implement this "servicesMap". Because the bind method returns a generic builder. Does Guice (or Guava) provide something for cases like this?

I know that I can use Guice to create the services and publish the progress using an injection/type listener, but my business package (module) that contains all the services has no javax.inject dependency. Plus, the creation of these services is complex hence is better to make it manually. Also, publishing a GUI progress within a Guice module sounds too complex to be in a Guice module.

So, is there a way? Instead of the System.out.println in the above snippets, there is a splash screen that is created manually as well.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Just move the code that builds each service impl inside the body of the @Provides method for the corresponding service interface. You mentioned wanting these to be singletons, so you'll also want to annotate the provider methods with @Singleton.

As for the map, you could do something like that with a Multibinder, but I'd want to understand your design better before recommending that.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...