Guice: Creating Injectors for Shared Libs

我的未来我决定 提交于 2019-12-08 06:56:31

问题


New to Google Guice. I'd like to use it to handle all IoC and AOP method interception for three components I am developing:

  • WidgetClient - a Swing app
  • WidgetServer - a small EAR that the client will connect to/communicate with
  • WidgetShared - a "commons" JAR that contains common classes used by both client and server

With the Swing app, somewhere I'll make an explicit call that might look like:

public static void main(String[] args) {
    initGuiceInjectors();
}

private static initGuiceInjectors() {
    Guice.createInjector(mySwingAppModule);
}

The mySwingAppModule will define all the bindings for the Swing app's dependencies. I will do something very similar in the server EAR.

When it comes to the WidgetShared library, I'm choking, because the lib doesn't have a single entry point: it's just a bunch of packages, classes, interfaces and enums that the client and server will use all over the place.

So my first question: where do I invoke Guice.createInjector() for the WidgetShared JAR?

This question underscores a segue into a second (similar) question, which is why I chose to group it here as well.

I read up on Guice's "best practices", and the overwhelming consensus seems to be to (where applicable), keep Module implementations at the package level. Thus for every package, there will be one Module concretion defining bindings for all types within that package. This is an improvement over a single monolithic Module defining bindings for the entire app.

So, the code snippet above (Guice.createInjector(mySwingAppModule)) is actually not what my code will eventually look like (sorry I lied!).

My second question is: what are the "best practices" for creating multiple injectors?

I see that createInjector(Module... modules) can take vararg Module arguments. So, to me it seems like if I want to embrace this "1-module-per-package" best practice, at some point I have to have code that either looks like this:

Guice.creatorInjector(package1Module, package2Module, package3Module,
    package4Module, package5Module, package6Module, ..., packageNModule);

or, like this:

Guice.createInjector(package1Module);
Guice.createInjector(package2Module);
Guice.createInjector(package3Module);

...

Guice.createInjector(packageNModule);

Both of these look really nasty! Is there a better way to accomplish this?!?

Thanks in advance!


回答1:


Adam,

There are two elements to your question, but clearly both related. I'll go backwards, starting with the second element first.

The organization of one module per package is important because it gives a predictable convention of where bindings should be placed, and as a bonus, it allows you to package protect your classes accordingly. There is also the popular notion of creating composite modules that act primarily to install a collection of per-package modules in order to act as the single module that needs to be installed to add bindings for a given configuration of a library. Installing this single module becomes the main integration point between the library and the server/application that uses it.

Bouncing back to your first point, it's not recommended to have multiple injectors per application. What is better is to have a single injector install the modules that it needs to satisfy all bindings used in the app.

In the end, you'd have something like:

public WidgetSharedLibraryModule extends AbstractModule {
  @Override protected void configure() {
    install(new WidgetSublibraryModule1());
    install(new WidgetSublibraryModule2());
    ...
  }
}

And your main method would look like:

public static void main(String[] args) {
    Injector injector = Guice.createInjector(
        new WidgetSharedLibrary(),
        new WidgetSwingAppModule());
    WidgetSwingApp app = injector.getInstance(WidgetSwingApp.class);
    app.run();
}


来源:https://stackoverflow.com/questions/8852276/guice-creating-injectors-for-shared-libs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!