On Tuesday, May 10, 2011 10:47:51 AM UTC+2, dhoffer wrote:
>
> 1. Hum, perhaps I'm doing more work than I need to...perhaps just out
> of habit of previously using manual factories...but I think I got this
> from the Guice online docs. Here is what I do:
>
> Class A takes 4 parameters where all are interfaces of course. I add
> @Inject annotation to the constructor and optionally scope annotation
> to the class. I then create a module for this class that extends from
> AbstractModule that implements configure. In this method I create and
> maintain 4 bind() method calls that map the interface to the actual
> class. I assume the order of these bind statements much match the
> order in the constructor. Repeat for every IoC class in the
> application.
>
You're doing it wrong. Modules are not factories, they're configuration.
1. the bind() order is not significant
2. using a module per "class requiring injection", you'll probably have
duplicate bindings (classes Foo and Bar have a dependency on Baz, following
your "rule", both FooModule and BarModule will
bind(Baz.class).to(BazImpl.class), this will cause an error) or conflicts
(FooModule binds Baz to BazImpl whereas BarModule binds Baz to AnotherBaz).
If you want to make very fine-grained modules (really not sure that's a best
practice), you'd rather have one per "interface some other class depends on"
(i.e. interface Baz), but then you could in simple cases just as easily use
an @ImplementedBy annotation.
You have to think at a wider level than "one class", think "module" instead
(I'm not talking about Guice modules, but application/feature modules).
As an example, we have "api modules" (Maven modules, think of them as JARs
or Eclipse projects if you prefer) comprised mostly of interfaces (we have
one for managing entities in a simple datastore, one for indexing and
searching them, one for validating them, one for dispatching events on a
bus, etc.) Then we have "implementation modules" where the storage is
implemented using Morphia/MongoDB, the indexing/searching backed by Solr,
validation by Hibernate Validator and JSR303, and the event bus by HornetQ.
In each of these "implementation modules", we have only a single Guice
module that binds each interface from the "api module" to the concrete
implementation of the "implementation module" (Indexer to a SolrIndexer
backed by a SolrServer, EntityManager to a MorphiaEntityManager backed by a
Morphia Datastore, etc.)
Then we have several applications (a webapp and a bunch or "executables")
that make use of these modules, each one creates a Guice Injector installing
the required modules; the code only depends on the interfaces from the "api
modules" though.
I guess I just don't get your comment 'bind()ings are about *what* to
> inject, not *where* to inject them.'
>
It's not where I use an EntityManager that I decide which one I'll use (i.e.
it's not in a FooModule along side a Foo class with an "@Inject
EntityManager em" field, that I bind(EntityManager.class)), it's at the
application level that I instead decide which modules I'll install, those
modules providing the bindings (some classes need an EntityManager, and the
bootstrap code for the app chooses to use the MorphiaStorageModule that
binds EntityManager to an implementation based on Morphia).
It seems you need some way to
> specify the *where* too.
>
If you need several implementations of a given interface to be injected at
different places in your app, then you have to annotate those places. For
instance, we have several Solr indexes –Solr cores–, one used for "suggest
as you type" and one for "advanced search", because they need different Solr
configurations. In our app, both are accessed through a Searcher interface.
We created a "binding annotation" (or you could use @Named if your prefer)
so that anywhere I need a "searcher for suggest-as-you-type" I declare a
"@ForIndex(Index.Suggest) Searcher" field or constructor argument, and
anywhere I need a "searcher for advanced search" I declare a
"@ForIndex(Index.AdvancedSearch) Searcher" field or constructor argument.
In the SolrSearchModule, we then have two bindings (in the form of @Provides
methods):
@Provides @ForIndex(Index.Suggest) Searcher provideSuggestSearcher(...other
dependencies...) { ... }
@Provides @ForIndex(Index.AdvancedSearch) Searcher
provideAdvancedSearchSearcher(...other dependencies...) { ... }
See, it's about *what* you depend on/inject, not about *where* you inject
it.
--
You received this message because you are subscribed to the Google Groups
"google-guice" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/google-guice?hl=en.