GranitePowered/Granite — pull request #95 by Hidendra (2014-12-22 15:03:20+00:00)
Title: Initial Guice support.

Hello!

This includes the initial changes for Guice injections. It didn't seem right to use Guice for just plugins themselves, so I've begun integrating Guice a bit more with Granite itself although it's very laissez-faire at the moment.

##### What is not yet supported (should be straightforward to add, just not done yet.):

* Plugin-specific `Logger`
* `@DefaultConfig`

As for what *is* supported right now, `@ConfigDir` and any non plugin-local values (such as `Game`).

##### Overview of structural changes

* `GraniteStartupThread` load order and initialization has been modified to better support Guice. I might change it more in the future because it's still a bit messy.
* `pluginManager.loadPlugins()` is now done *after* everything is initialized & injected (but before the first plugin events are sent) so that plugin classes are not loaded (and then injected) with a `Game (GraniteServer)` instance that has not yet been rewritten yet.
* could likely be moved back if needed by ensuring `bootstrapPlugin` is called *after* all classes are rewritten. (otherwise if a plugin wants a `Game` instance, they'll get a `GraniteServer` instance that is not rewritten => crashes the server!)
* `PluginScope` is quite a bit different from Sponge's at the moment, but might be changed at some point to have the exact same behaviour. Much of it is based off of [official documentation](https://github.com/google/guice/wiki/CustomScopes).
* A lot of the local members inside `Granite` have been made final & replaced with a constructor tagged with `@Inject`. **This is automatically constructed by Guice (see [GraniteServerThread#111](https://github.com/Hidendra/Granite/blob/5ccd329a6e7c05d1033543a02a57db3b203c3b00/src/main/java/org/granitepowered/granite/GraniteStartupThread.java#L111)).** The idea is that eventually `@Inject` should be preferred over directly creating instances where possible.
* `SimpleCommandService` cannot be auto injected at the moment for some reason. It seems to cause duplicate `PluginManager` instances to be created (Sponge's Forge impl does the same thing: creates the instance directly). I will have to look into this more because it should work with Guice without any issues (or so I think).

##### How do plugins use Guice?

If there's any confusion about *how* to use Guice: Guice injects instances *it creates & manages* into your constructor (not for plugins however), local fields, or setter methods tagged with `@Inject`.

Any [bind()s](https://github.com/Hidendra/Granite/blob/5ccd329a6e7c05d1033543a02a57db3b203c3b00/src/main/java/org/granitepowered/granite/impl/guice/GraniteGuiceModule.java#L57) can be injected. So if I wanted a `Game` or `GameRegistry`, no problem. The binds with `annotatedWith` binds signify that they require that annotation *and* `@Inject`.

Example:

@Inject
private Game game;

or:

@Inject
public void setGame(Game game) {
this.game = game;
}

Both will achieve the same thing in the end.

LWC [makes use of these](https://github.com/Hidendra/LWC/blob/5.0/mods/sponge/src/main/java/org/getlwc/sponge/SpongePlugin.java#L66) so feel free to use it as a reference plugin. LWC currently runs great with this PR.

Let me know if any of you have any questions. I should be able to better explain exactly *what* this does over IRC or something if any of you are still really confused about Guice :smile: