Java and Google Guice?
Introduction
Guice is Google’s attempt to create a feature-rich, independent DI facility. It is useful in most applications.
Agile Lightweight Dependency Injection Framework will not only tell you "how," it will also tell you "why" and "why not," so that all the knowledge you gain will be as widely applicable as possible
Setup
gradle
implementation 'com.google.inject:guice:5.1.0'
pom.xml
<dependency
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>5.1.0</version>
</dependency>>
Basic Dependency Injection With Guice
public class Publication {
@Inject
private Logger log;
@Inject
private Publisher publisher;
public Publication(Boolean persist) {
if (persist) {
System.out.println("Persistence Enabled");
}
}
public boolean publish(String message) {
return publisher.sendMessage(message);
}
}
Here instance of Publisher is used to publish a messages using a publisher injected by Guice injector as below
public static void main(String[] args){
Injector injector = Guice.createInjector(new BasicModule());
Publication publication=injector.getInstance(Publication.class);
}
This main method retrieves an instance of our Publication class. It also introduces a fundamental concept of Guice: the Module (using BasicModule in this example). 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 we won't be dealing with a lot of XML out-of-the-box.
Guice Basic Bindings
Binding is to Guice as wiring is to Spring. With bindings, we define how Guice is going to inject dependencies into a class.
A binding is defined in an implementation of com.google.inject.AbstractModule:
public class BasicModule extends AbstractModule {
@Override
protected void configure() {
bind(Publisher.class).to(SamplePublisher.class);
}
}
Another incarnation of this mechanism is the named binding
@Inject @Named("SamplePublisher"
Publisher publisher;)
For this, we'll have the following binding definition:
@Override
protected void configure() {
bind(Publisher .class)
.annotatedWith(Names.named("SamplePublisher"))
.to(SamplePublisher.class);
}
This binding will provide an instance of Communicator to a variable annotated with the @Named(“DefaultCommunicator”) annotation.
We can also see that the @Inject and @Named annotations appear to be loan annotations from Jakarta EE's CDI, and they are. They're in the com.google.inject.* package, and we should be careful to import from the right package when using an IDE.
Tip: While we just said to use the Guice-provided @Inject and @Named, it's worthwhile to note that Guice does provide support for javax.inject.Inject and javax.inject.Named, among other Jakarta EE annotations.
Constructor Binding
We can also inject a dependency that doesn't have a default no-arg constructor using constructor binding:
public class BasicModule extends AbstractModule {
@Override
protected void configure() {
bind(Boolean.class).toInstance(true);
bind(Publisher.class).toConstructor(
Publisher.class.getConstructor(Boolean.TYPE));
}
Types of Dependency Injection
Field Injection
@Inject @Named("TVBroadcaster"
PublicationMode tvBroadcaster;)
Method Injection
@Inject
public void setEmailPublisher(@Named("EmailPublisher") PublicationMode emailPub) {
this.emailPub = emailPub;
}
Constructor Injection
@Inject
public Publication(@Named("IMPubs") PublicationMode imPubs) {
this.imPubs= imPubs;
}t
Implicit Injection
Guice alos implecitly inject some genral pupose components like the injector and instance of java.util.Logger, amond others. Please note that we're using loggers all through the samples without binding for it.