Google Guice Combined mode

Source: Internet
Author: User

For Guice, injector assembly Work is an object graph, when the request type instance, the injector is based on how the inferred object maps to the created instance and resolves the dependency. To determine how to resolve dependencies, you need to configure the way injectors are combined.

To create a bound (binding) object, you can inherit from the Abstractmodule class, and then overwrite its configure method, in the method call bind () method to refer to each binding. These methods have type checking, assuming that you are using the wrong type compiler to report compilation errors. Assuming you have already written the module class, create a module class object that is passed as a parameter to the Guice.createinjector () method to create an injector.

The module object enables you to create link bindings (linked bindings), instance bindings (instance bindings), @Provides methods, provider bindings (provider bindings), build method Bindings ( constructor bindings) with no target binding (untargetted bindings).

These binding methods are collectively known as built-in bindings, which are also tied in a timely manner. Assume that a dependency cannot be found in a built-in binding if it is parsed. Then Guice will create a timely binding.

First, link binding (linkdedbindings)

A link binding maps a type to its implementation class, such as mapping the TransactionLog interface to the implementation class Databasetransactionlog:

public class Billingmodule extends Abstractmodule {  @Override   protected void Configure () {    bind ( Transactionlog.class). to (Databasetransactionlog.class);}  }

this way, when you call the Injector.getinstance (Transactionlog.class) method, or when the injector encounters TransactionLog dependencies, the Databasetransactionlog object is used. A link is a subclass from one type to another, which contains an interface implementation class, a subclass of a class, so for example the following mappings are also possible: Bind (Databasetransactionlog.class). to ( Mysqldatabasetransactionlog.class);
and link binding supports chained notation:


public class Billingmodule extends Abstractmodule {  @Override   protected void Configure () {    bind ( Transactionlog.class). to (Databasetransactionlog.class);    Bind (Databasetransactionlog.class). to (Mysqldatabasetransactionlog.class);}  }

In such a case, when a TransactionLog type object is requested, the injector returns a Mysqldatabasetransactionlog object.



Second, binding annotations
In some cases you may want to set multiple bindings for the same type. This can be achieved by binding annotations, which are used to uniquely meet a binding with the type of binding,
Together, it's called Key. Demo Sample:

Package Example.pizza;import Com.google.inject.bindingannotation;import Java.lang.annotation.target;import Java.lang.annotation.retention;import static Java.lang.annotation.retentionpolicy.runtime;import Static Java.lang.annotation.elementtype.parameter;import static Java.lang.annotation.elementtype.field;import Static Java.lang.annotation.ElementType.METHOD, @BindingAnnotation @Target ({FIELD, PARAMETER, METHOD}) @Retention (RUNTIME) Public @interface PayPal {}

The key here is the @bindingannotation meta annotation, which is used as a binding annotation when Guice describes the annotation.


Then use the Annotatedwith statement in the module's configure method, such as the following:
Bind (Creditcardprocessor.class). Annotatedwith (Paypal.class). to (Paypalcreditcardprocessor.class);
This maps the creditcardprocessor to the paypalcreditcardprocessor.

How to use:


public class Realbillingservice implements BillingService {@Injectpublic Realbillingservice (@PayPal Creditcardprocessor processor,transactionlog transactionlog) {...}}

In another case, we can use @named annotations that are already defined by Guice. For example:


public class Realbillingservice implements BillingService {  @Inject  the public Realbillingservice (@Named (" Checkout ") creditcardprocessor Processor,transactionlog transactionlog) {...  }}

To bind a verbose name, use Names.named () to create an implementation passed to the Annotatedwith method:

Bind (Creditcardprocessor.class)        . Annotatedwith (names.named ("Checkout"))        . to ( Checkoutcreditcardprocessor.class);

because the compiler does not check the string, Guice recommends that we use less @named annotations, but I personally think that just write your own code only to write the name not wrong,
The easiest way to do this is to map multiple bindings for the same type. This is very similar to how spring is implemented, Spring @service, @Controller, @Repository not be able to specify the name?

Third, instance binding (Instance Bindings)
With instance binding we are able to bind a detailed instance of a type, which only applies to cases where these instance types have no other dependencies, such as value objects:

Bind (String.class)        . Annotatedwith (names.named ("JDBC URL"))        . ToInstance ("Jdbc:mysql://localhost/pizza");    Bind (Integer.class)        . Annotatedwith (names.named ("Login timeout Seconds")        . ToInstance (10);

How to use:

@Inject @Named ("JDBC URL") Private String URL
Guice recommends that we avoid using. toinstance to create complex objects. Because this delays the app startup. Similarly, it can be implemented using the @provides method.


Iv. Methods of @Provides
When you create an object by using the @provides method. The method must be defined in the module class. And it has to be @provides annotated. The return value type of the method is the object being bound.

When an injector needs an instance of that type, it calls 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 (+);    return transactionlog;}  }

assume that there are @paypal or @named ("Checkout") binding annotations on the @provides method. Guice with binding annotations takes precedence. guice resolves the dependency of the method before calling the @provides method:


@Provides @PayPalCreditCardProcessor providepaypalcreditcardprocessor (@Named ("PayPal API key") String ApiKey) { Paypalcreditcardprocessor processor = new Paypalcreditcardprocessor ();p Rocessor.setapikey (ApiKey); return processor;}

About Exceptions:
Guice differs in that it is intended to throw an exception in the @provides method.

Suppose there is an exception thrown. Then the exception will be wrapped in the Provisionexception object.

V. Provider bindings (Provider Bindings)
Assume that the @provides approach is becoming more complex. We might want to move them into a separate class. A provider class implements the provider interface. It is a
A simple generic interface for providing values.


Public interface Provider<t> {  T get ();}

Assuming that the provider implementation class has its own dependencies, it can be injected by adding @inject annotations on its construction method to ensure that the values return safely.


public class Databasetransactionlogprovider implements provider<transactionlog> {  private final Connection Connection;  @Inject public  Databasetransactionlogprovider (Connection Connection) {    this.connection = Connection;  }  Public TransactionLog get () {    Databasetransactionlog transactionlog = new Databasetransactionlog ();    Transactionlog.setconnection (connection);    return transactionlog;}  }

Finally, use the. Toprovider statement to bind to the provider:

public class Billingmodule extends Abstractmodule {  @Override  protected void Configure () {    bind ( Transactionlog.class)        . Toprovider (Databasetransactionlogprovider.class);  }}

VI. No target binding

Guice agreed that we did not specify the target class when we created the binding. That is, there is no to statement, which is useful for detailed classes or for using @implementedby or @providedby annotation types. Like what:
Bind (Myconcreteclass.class);
Bind (Anotherconcreteclass.class). in (Singleton.class);
However, when binding annotations are used, we rely on having to specify the binding target. That is, it is a detailed class, such as:

Bind (Myconcreteclass.class). Annotatedwith (names.named ("foo"))    . to (Myconcreteclass.class); Bind ( Anotherconcreteclass.class). Annotatedwith (names.named ("foo")). to    (Anotherconcreteclass.class)    . In ( Singleton.class);

Vii. Structuring method bindings
There are times when you might need to bind a type to any of the build methods, such as when the @inject annotation cannot be added to the target class constructor, perhaps because the class is
provided by third parties. Alternatively, the class has multiple build methods to participate in dependency injection. At this point the @provides method is the best solution to the problem, because it can understand the specified
Which constructor method is called. And there is no need to use a reflection mechanism.

However, the use of the @provides method is limited in some places, such as: Manually created objects cannot be used in AOP.
It is for this reason that Guice uses toconstructor () to bind. This requires that we use reflection to select the construction method and handle the exception.

public class Billingmodule extends Abstractmodule {  @Override   protected void Configure () {    try {      bind ( Transactionlog.class). Toconstructor (          DatabaseTransactionLog.class.getConstructor (Databaseconnection.class) );    } catch (Nosuchmethodexception e) {      adderror (e);}}  }

In this example, the Databasetransactionlog class must have a constructor with a databaseconnection parameter that does not need to use @inject annotations Guice itself to invoke the constructor on its own initiative. Each toconstructor () statement creates a binding. Its scope is independent, assuming you create multiple singleton bindings and use the same constructor method of the target class, each binding has its own instance.



Eight, timely binding
When an injector needs an instance of a type. It needs to get a binding. The bindings in the module class are called display bindings, which can be used by the injector only if they are available. Suppose you need an instance of a type, but it is not a display binding. Then the injector will attempt to create a time-bound (just-in-time bindings), which is also known as JIT binding and implicit binding.
The situations that can be used to create a timely binding include the following:
A. There is an appropriate method of construction, that is, non-private. A construction method with no parameters or @inject annotations, such as:


public class Paypalcreditcardprocessor implements Creditcardprocessor {  private final String ApiKey;  @Inject public  paypalcreditcardprocessor (@Named ("PayPal API key") String ApiKey) {    this.apikey = ApiKey;  }}

Guice does not create an inner class instance unless it has a static modifier, because the inner class contains an implicit reference to the outer-class, and the implicit reference cannot be injected.

B. @ImplementedBy
@ImplementedBy annotations are used to tell the injector what the default implementation type of a type is, which is very similar to a link binding.

Binds a subtype for a type such as the following:


@ImplementedBy (paypalcreditcardprocessor.class) public interface Creditcardprocessor {  chargeresult charge ( String amount, CreditCard CreditCard)      throws unreachableexception;}

the @ImplementedBy (Paypalcreditcardprocessor.class) is equivalent to the following bind () statement:

Bind (Creditcardprocessor.class) to (Paypalcreditcardprocessor.class);


c. @ProvidedBy
@ Providedby annotations are used to tell the injector. What is the implementation of the provider class, for example:

 @ProvidedBy ( Databasetransactionlogprovider.class) public interface TransactionLog {void Logconnectexception (  Unreachableexception e); void Logchargeresult (chargeresult result);} 
This is equivalent to bind (Transactionlog.class). Toprovider ( Databasetransactionlogprovider.class);
Similar to @implementedby annotations, it is assumed that a type uses both the bind () statement and the @providedby annotation. Then, the bind () declaration takes precedence.

copyright notice: This article Bo Master original articles, blogs, without consent may not be reproduced.

Google guice associative mode

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.