Google Guice provides some great dependency injection features.
I came across the @Nullable feature recently which allows you to mark constructor arguments as optional (permitting null) since Guice does not permit these by default:
e.g.
public Person(String firstName, String lastName, @Nullable Phone phone) {
this.firstName = checkNotNull(firstName, "firstName");
this.lastName = checkNotNull(lastName, "lastName");
this.phone = phone;
}
https://github.com/google/guice/wiki/UseNullable
What are the other useful features of Guice (particularly the less obvious ones) that people use?
None of 'em are intended to be hidden, but these are my favorite 'bonus features' in Guice:
- Guice can inject a TypeLiteral<T>, effectively defeating erasure.
- TypeLiteral can do generic type resolution: this tells you that
get()
on aList<String>
returns anIterator<String>
. - Types is a factory for implementations of Java's generic type interfaces.
- Grapher visualizes injectors. If your custom provider implements HasDependencies, it can augment this graph.
- Modules.override() is incredibly handy in a pinch.
- Short syntax for defining parameterized keys:
new Key<List<String>>() {}
. - Binder.skipSources() lets you to write extensions whose error messages track line numbers properly.
- The SPI. Elements.getElements() breaks a module into atoms and Elements.getModule() puts them back together.
- If you implement
equals()
andhashCode()
in aModule
, you can install that module multiple times without problem.
I like how totally open the Scope
interface is: basically, it's just a transformation from Provider
to Provider
. (Okay, from Key
and Provider
to Provider
)
Want some things to be basically Singleton, but re-read from the database every half hour? It's easy to make a scope for that. Want to run some requests in the background, and have a scope that means "all background requests started from the same HTTP request?" It's relatively easy to write that Scope
too.
Want to scope some Key
on your server during tests so that it uses a separate instance for each test that you're running from a client? (With the test passing the test id in a Cookie or extra HTTP parameter) That's harder to do, but it's perfectly possible and so someone's already written that for you.
Yes, excessive abuse of Scope
will cause Jesse to start hunting around for the stakes and garlic cloves, but its amazing flexibility can be really useful.
One great feature of Guice is how easy it makes implementing method interceptors in any Module
, using:
public void bindInterceptor(
Matcher<? super Class<?>> classMatcher,
Matcher<? super Method> methodMatcher,
MethodInterceptor... interceptors);
Now, any method matching methodMatcher
within a class matching classMatcher
in that Module
's scope is intercepted by interceptors
.
For example:
bindInterceptor(
Matchers.any(),
Matchers.annotatedWith(Retryable.class),
new RetryableInterceptor());
Now, we can simply annotate any method with @Retryable
and our RetryableInterceptor
can
retry it if it fails.
精彩评论