When you annotate a method with @Provides the type of the object you want to inject is the same as the method return type. On the other hand when you use @CheckedProvides you can inject the provider not the object that the provider provides
https://github.com/google/guice/wiki/FrequentlyAskedQuestions
https://github.com/google/guice/wiki/JustInTimeBindings
https://softwareengineering.stackexchange.com/questions/284111/what-is-the-motivation-behind-the-implementedby-annotation-in-guice?rq=1
having your interfaces depend on your implementation can be a code smell;
http://gotolongjump.blogspot.com/2012/05/use-guice-simplest-way.html
With Foo as the root application-level binding, Guice already has full knowledge of Bar, Baz and Doh dependencies through reflection. It will report errors the same way as if you wrote explicit bindings for Bar and Baz. There is no need to manually "tell" Guice about them.
https://www.tutorialspoint.com/guice/guice_just_in_time_bindings
https://github.com/google/guice/wiki/JustInTimeBindings
https://www.hackingnote.com/en/versus/dagger-vs-guice
The key difference is that Guice is dependency injection at runtime, while Dagger is at compile time. This leads to the following comparisons:
https://github.com/google/guice/wiki/InjectOnlyDirectDependencies
Inject only direct dependencies
Keep constructors on Guice-instantiated classes as hidden as possible.
https://www.tutorialspoint.com/guice/guice_provides_annotation
Guice provides a way to create bindings with complex objects using @provides method
@Provides methods can have parameters that are injected by Guice
https://stackoverflow.com/questions/28202882/guice-provides-methods-vs-provider-classes
https://github.com/google/guice/wiki/ProvidesMethods
https://www.baeldung.com/guice
Anti-Pattern: Field Injection
https://liviutudor.com/2017/03/17/java-dependency-injection-and-a-useless-annotation/#sthash.4A7bMjA1.dpbs
Look closely here — there is no @PostConstruct or @PreDestroy kicking in! Wait, what???
As it turns out, Google Guice on its own does not provide any lifecycle management support — I found this post from ages ago mentioning it: https://groups.google.com/forum/#!topic/google-guice/0M3molmK4IU ; as a suggestion to the Guice peeps, it would be good if their (otherwise excellent) docco states this clearly too. Since they are referencing the java.annotation package, one is lead to believe they support this too — I definitely was.
OK, so note to all Guice users: unless you add other libraries in your app you do not get any lifecycle support such as @PostCreate and @PreDestroy in your app!
https://discursive.com/2011/01/26/creating-a-simple-google-guice-application/
we need to provide some hints to Guice to tell it what class to instantiate when it is asked for a particular interface.
private static class AModule extends AbstractModule {
@Override
protected void configure() {
bind(ObjectMapper.class).toInstance(new ObjectMapper()
.configure(SerializationFeature.INDENT_OUTPUT, true)
.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false)
....
}
}
You can use a TypeLiteral to create the binding.
TypeLiteral
is a special class that allows you to specify a full parameterized type. @Override public void configure() {
bind(new TypeLiteral<List<String>>() {}).toInstance(new ArrayList<String>());
}
Alternately, you can use an @Provides method.
@Provides List<String> providesListOfString() {
return new ArrayList<String>();
}
https://github.com/google/guice/wiki/JustInTimeBindings
https://softwareengineering.stackexchange.com/questions/284111/what-is-the-motivation-behind-the-implementedby-annotation-in-guice?rq=1
having your interfaces depend on your implementation can be a code smell;
Use@ImplementedBy
carefully; it adds a compile-time dependency from the interface to its implementation.
Such dependency may not be a problem in many cases but I personally see it as a code smell.
What use cases make the
@ImplementedBy
annotation worth using?
One possible way seems to be to employ it in the code of a library or framework. As described in the docs, the annotation can provide a default binding easily overriden by an explicit one.
https://github.com/google/guice/wiki/InjectingProvidersIf a type is in both abind()
statement (as the first argument) and has the@ImplementedBy
annotation, thebind()
statement is used. The annotation suggests a default implementation that can be overridden with a binding.
Use providers when you need multiple instances of the same type. Suppose your application saves a summary entry and a details when a pizza charge fails. With providers, you can get a new entry whenever you need one.
public class LogFileTransactionLog implements TransactionLog {
private final Provider<LogFileEntry> logFileProvider;
@Inject
public LogFileTransactionLog(Provider<LogFileEntry> logFileProvider) {
this.logFileProvider = logFileProvider;
}
public void logChargeResult(ChargeResult result) {
LogFileEntry summaryEntry = logFileProvider.get();
summaryEntry.setText("Charge " + (result.wasSuccessful() ? "success" : "failure"));
summaryEntry.save();
if (!result.wasSuccessful()) {
LogFileEntry detailEntry = logFileProvider.get();
detailEntry.setText("Failure result: " + result);
detailEntry.save();
}
}
Providers for lazy loading
Providers for Mixing Scopes
It is an error to depend on an object in a narrower scope. Suppose you have a singleton transaction log that needs on the request-scoped current user. Should you inject the user directly, things break because the user changes from request to request. Since providers can produce values on-demand, they enable you to mix scopes safely:
@Singleton
public class ConsoleTransactionLog implements TransactionLog {
private final AtomicInteger failureCount = new AtomicInteger();
private final Provider<User> userProvider;
@Inject
public ConsoleTransactionLog(Provider<User> userProvider) {
this.userProvider = userProvider;
}
public void logConnectException(UnreachableException e) {
failureCount.incrementAndGet();
User user = userProvider.get();
System.out.println("Connection failed for " + user + ": " + e.getMessage());
System.out.println("Failure count: " + failureCount.incrementAndGet());
}
With Foo as the root application-level binding, Guice already has full knowledge of Bar, Baz and Doh dependencies through reflection. It will report errors the same way as if you wrote explicit bindings for Bar and Baz. There is no need to manually "tell" Guice about them.
Main supposed benefits I've heard about preferring explicit bindings:
- "They give up-front error reporting." Again, this is simply irrelevant because implicit bindings do the same.
As bindings are defined in Binding Module, Guice uses them whenever it needs to inject dependencies. In case bindings are not present, it can attempt to create just-in-time bindings. Bindings present in binding module are called explicit bindings and are of higher precedence whereas just-in-time bindings are called implicit bindings. If both type of bindings are present, explicit bindings are considered for mapping.
Sr.No. | Binding Type & Description |
---|---|
1 | Injectable Constructors
Non-private, No-argument constructors are eligible for just-in-time bindings. Another way is to annotate a constructor with @Inject annotation.
|
2 | @ImplementatedBy annotation
@ImplementatedBy annotation tells the guice about the implementation class. No binding is required in Binding Module in such a case.
|
3 | @ProvidedBy annotation
@ProvidedBy annotation tells the guice about the provider of implementation class. No binding is required in Binding Module in such a case
|
https://www.hackingnote.com/en/versus/dagger-vs-guice
The key difference is that Guice is dependency injection at runtime, while Dagger is at compile time. This leads to the following comparisons:
- Guice is base on reflection, while Dagger is generating extra code during compile-time; reflection is much slower than the pre-generated code.
- Dagger is often used in Android development(reflection is even slower in Android)
- Dagger has simpler APIs, and the stacktrace is easier to understand
Minimize mutability
Wherever possible, use constructor injection to create immutable objects. Immutable objects are simple, shareable, and can be composed
Method injection is most useful when you need to initialize an instance that is not constructed by Guice. Extensions like AssistedInject and Multibinder use method injection to initialize bound objects.
Field injection has the most compact syntax, so it shows up frequently on slides and in examples. It is neither encapsulated nor testable. Never inject final fields; the JVM doesn't guarantee that the injected value will be visible to all threads.
Inject only direct dependencies
Yes. You should always be using packages anyway. Use of the default package is discouraged for all but toy-sized programs.
I would typically expect to have a
org.whatever.foo.some.feature
package with a module class called FeatureModule
(i.e. the name of the package + Module
, not specifically FeatureModule
).Second, you can see unit testing the class through means of direct instantiation. This means we should do unit testing a class using direct instantiation, not Guice's Module? I think Guice is also useful for a testing, especially unit testing as they said.
It's just easier to see exactly what you're testing with if you directly inject the things you want to test with.
Sure, you can use guice, but there's a certain amount of "magic happens here" with the bindings, which can hide unexpected behaviour in the test.
This applies to unit testing; if you're doing integration testing, you likely do want to be using something close to how your production code does it, which may involve guice.
As a correction, simply limit the visibility of both your implementation classes, and their constructors. Typically package private is preferred for both, as this facilitates:
- binding the class within a
Module
in the same package - unit testing the class through means of direct instantiation
Conditional logic in itself isn't too bad. But problems arise when configurations are untested. In this example, the
InMemoryFooService
is used for development and RemoteFooService
is used in production. But without testing this specific case, it's impossible to be sure that RemoteFooService
works in the integrated application.
To overcome this, minimize the number of distinct configurations in your applications. If you split production and development into distinct modules, it is easier to be sure that the entire production codepath is tested. In this case, we split
FooModule
into RemoteFooModule
and InMemoryFooModule
. This also prevents production classes from having a compile-time dependency on test code.
The preferred solution is to not inject closable resources, but instead, objects that can expose short-lived closable resources that are used as necessary
Guice forbids null by default. It will refuse to inject
null
, failing with a ProvisionException
instead. If null
is permissible by your class, you can annotate the field or parameter with @Nullable
. Guice recognizes any @Nullable
annotation, like edu.umd.cs.findbugs.annotations.Nullable or javax.annotation.Nullable.- Modules start up, but they don't shut down. Should you open a database connection in your module, you won't have any hook to close it.
- Modules should be tested. If a module opens a database as a course of execution, it becomes difficult to write unit tests for it.
- Modules can be overridden. Guice modules support overrides, allowing a production service to be substituted with a lightweight or test one. When the production service is created as a part of module execution, such overrides are ineffective.
Rather than doing work in the module itself, define an interface that can do the work at the proper level of abstraction.
After creating the Injector, we finish bootstrapping our application by starting its services. We also add shutdown hooks to cleanly release resources when the application is stopped.
public static void main(String[] args) throws Exception {
Injector injector = Guice.createInjector(
new DatabaseModule(),
new WebserverModule(),
...
);
Service databaseConnectionPool = injector.getInstance(
Key.get(Service.class, DatabaseService.class));
databaseConnectionPool.start();
addShutdownHook(databaseConnectionPool);
Service webserver = injector.getInstance(
Key.get(Service.class, WebserverService.class));
webserver.start();
addShutdownHook(webserver);
}
Guice provides a way to create bindings with complex objects using @provides method
@Provides methods can have parameters that are injected by Guice
https://stackoverflow.com/questions/28202882/guice-provides-methods-vs-provider-classes
The main advantage of @Provides is compactness, especially in comparison to anonymous inner Provider implementations. Note, however, that there might be a few cases where you'd want to favor Provider classes:
- You can create your own long-lived Provider instances, possibly with constructor parameters, and bind keys to those instances instead of to class literals.
bind(Foo.class).toProvider(new FooProvisioner("bar", "baz"));
- If you're using a framework compatible with JSR 330 (javax.inject), you can easily bind to javax.inject.Provider classes or instances. com.google.inject.Provider extends that interface.
bind(Foo.class).toProvider(SomeProviderThatDoesntKnowAboutGuice.class);
- Your Provider may be complex enough to factor into its own class. Depending on how you've structured your tests, it may be easier to test your Provider this way.
- Providers can extend abstract classes. It may not be easy or intuitive to do this with @Provides methods.
- You can bind several keys to the same Provider directly. Each @Provides method produces exactly one binding, though you could bind other keys to the key (@Quux Foo here) and let Guice do a second lookup.
- Providers are easy to decorate or wrap, if you wanted to (for instance) cache or memoize instances without using Guice scopes or bindings.
bind(Foo.class).toProvider(new Cache(new FooProvisioner("bar", "baz")));
IMPORTANT: Though this is a good strategy for classes that Guice can't create, bear in mind that Guice can automatically create and inject a
Provider<T>
for any T that you bind
in any way, including to a class name, key, or instance. No need to create an explicit provider unless there's actual logic of your own involved.https://github.com/google/guice/wiki/ProvidesMethods
@Provides Methods
When you need code to create an object, use an
@Provides
method. The method must be defined within a module, and it must have an @Provides
annotation. The method's return type is the bound type. Whenever the injector needs an instance of that type, it will invoke the method.public class BillingModule extends AbstractModule {
@Override
protected void configure() {
...
}
@Provides
TransactionLog provideTransactionLog() {
DatabaseTransactionLog transactionLog = new DatabaseTransactionLog();
transactionLog.setJdbcUrl("jdbc:mysql://localhost/pizza");
transactionLog.setThreadPoolSize(30);
return transactionLog;
}
}
If the
@Provides
method has a binding annotation like @PayPal
or @Named("Checkout")
, Guice binds the annotated type. Dependencies can be passed in as parameters to the method. The injector will exercise the bindings for each of these before invoking the method. @Provides @PayPal
CreditCardProcessor providePayPalCreditCardProcessor(
@Named("PayPal API key") String apiKey) {
PayPalCreditCardProcessor processor = new PayPalCreditCardProcessor();
processor.setApiKey(apiKey);
return processor;
}
https://www.baeldung.com/guice
The Module is the basic unit of definition of bindings (or wiring, as it’s known in Spring).
Guice has adopted a code-first approach for dependency injection and management so you won’t be dealing with a lot of XML out-of-the-box.
Another incarnation of this mechanism is the named binding. Consider the following variable declaration:
1
2
| @Inject @Named ( "DefaultCommunicator" ) Communicator communicator; |
For this, we will have the following binding definition:
1
2
3
4
5
6
| @Override protected void configure() { bind(Communicator. class ) .annotatedWith(Names.named( "DefaultCommunicator" )) .to(Communicator. class ); } |
This binding will provide an instance of Communicator to a variable annotated with the @Named(“DefaultCommunicator”) annotation.
You’ll notice the @Inject and @Named annotations appear to be loan annotations from JavaEE’s CDI, and they are. They are in the com.google.inject.* package
You can also inject a dependency that doesn’t have a default no-arg constructor using constructor binding:
1
2
3
4
5
6
7
8
| public class BasicModule extends AbstractModule { @Override protected void configure() { bind(Boolean. class ).toInstance( true ); bind(Communication. class ).toConstructor( Communication. class .getConstructor(Boolean.TYPE)); } |
The snippet above will inject an instance of Communication using the constructor that takes a boolean argument. We supply the true argument to the constructor by defining an untargeted binding of the Boolean class.
This untargeted binding will be eagerly supplied to any constructor in the binding that accepts a boolean parameter. With this approach, all dependencies of Communication are injected.
Another approach to constructor-specific binding is the instance binding, where we provide an instance directly in the binding:
1
2
3
4
5
6
7
8
| public class BasicModule extends AbstractModule { @Override protected void configure() { bind(Communication. class ) .toInstance( new Communication( true )); } } |
This binding will provide an instance of the Communication class wherever a Communicationvariable is declared.
Implicit Injections
Guice will implicitly inject some general purpose components like the Injector and an instance of java.util.Logger, among others.
The asEagerSingleton() call defines the singleton as eagerly instantiated.
In addition to these two scopes, Guice supports custom scopes as well as the web-only @RequestScoped and @SessionScoped annotations, supplied by JavaEE (there are no Guice-supplied versions of those annotations).
Anti-Pattern: Field Injection
Look closely here — there is no @PostConstruct or @PreDestroy kicking in! Wait, what???
As it turns out, Google Guice on its own does not provide any lifecycle management support — I found this post from ages ago mentioning it: https://groups.google.com/forum/#!topic/google-guice/0M3molmK4IU ; as a suggestion to the Guice peeps, it would be good if their (otherwise excellent) docco states this clearly too. Since they are referencing the java.annotation package, one is lead to believe they support this too — I definitely was.
OK, so note to all Guice users: unless you add other libraries in your app you do not get any lifecycle support such as @PostCreate and @PreDestroy in your app!
https://discursive.com/2011/01/26/creating-a-simple-google-guice-application/
we need to provide some hints to Guice to tell it what class to instantiate when it is asked for a particular interface.
private static class AModule extends AbstractModule {
@Override
protected void configure() {
bind(ObjectMapper.class).toInstance(new ObjectMapper()
.configure(SerializationFeature.INDENT_OUTPUT, true)
.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false)
....
}
}