guice30.docx

上传人:b****1 文档编号:20190121 上传时间:2023-04-25 格式:DOCX 页数:34 大小:27.87KB
下载 相关 举报
guice30.docx_第1页
第1页 / 共34页
guice30.docx_第2页
第2页 / 共34页
guice30.docx_第3页
第3页 / 共34页
guice30.docx_第4页
第4页 / 共34页
guice30.docx_第5页
第5页 / 共34页
点击查看更多>>
下载资源
资源描述

guice30.docx

《guice30.docx》由会员分享,可在线阅读,更多相关《guice30.docx(34页珍藏版)》请在冰豆网上搜索。

guice30.docx

guice30

一.概述

Guice是一个轻量级的DI框架。

本文对Guice的基本用法作以介绍。

本文的所有例子基于Guice3.0

本文的很多代码来源于Guice主页:

考虑到是入门介绍,本文中并未涉及到AOP相关内容,如有需要还请参考上面链接。

二.举例说明Guice的用法

Guice本身只是一个轻量级的DI框架,首先我们通过一个例子来看看怎么使用Guice。

首先有一个需要被实现的接口:

[java]viewplaincopyprint?

1.public interface BillingService {  

2.  

3.    /** 

4.     * Attempts to charge the order to the credit card. Both successful and 

5.     * failed transactions will be recorded. 

6.     *  

7.     * @return a receipt of the transaction. If the charge was successful, the 

8.     *         receipt will be successful. Otherwise, the receipt will contain a 

9.     *         decline note describing why the charge failed. 

10.     */  

11.    Receipt chargeOrder(PizzaOrder order, CreditCard creditCard);  

12.}  

publicinterfaceBillingService{

/**

*Attemptstochargetheordertothecreditcard.Bothsuccessfuland

*failedtransactionswillberecorded.

*

*@returnareceiptofthetransaction.Ifthechargewassuccessful,the

*receiptwillbesuccessful.Otherwise,thereceiptwillcontaina

*declinenotedescribingwhythechargefailed.

*/

ReceiptchargeOrder(PizzaOrderorder,CreditCardcreditCard);

}

然后,有一个实现该接口的实现类:

[java]viewplaincopyprint?

1.class RealBillingService implements BillingService {  

2.    private final CreditCardProcessor processor;  

3.    private final TransactionLog transactionLog;  

4.  

5.    @Inject  

6.    RealBillingService(CreditCardProcessor processor,  

7.            TransactionLog transactionLog) {  

8.        this.processor = processor;  

9.        this.transactionLog = transactionLog;  

10.    }  

11.  

12.    @Override  

13.    public Receipt chargeOrder(PizzaOrder order, CreditCard creditCard) {  

14.  

15.    }  

16.}  

classRealBillingServiceimplementsBillingService{

privatefinalCreditCardProcessorprocessor;

privatefinalTransactionLogtransactionLog;

@Inject

RealBillingService(CreditCardProcessorprocessor,

TransactionLogtransactionLog){

this.processor=processor;

this.transactionLog=transactionLog;

}

@Override

publicReceiptchargeOrder(PizzaOrderorder,CreditCardcreditCard){

}

}

现在接口有了,实现类也有了,接下来就是如何将接口和实现类关联的问题了,在Guice中需要定义Module来进行关联

[java]viewplaincopyprint?

1.public class BillingModule extends AbstractModule {  

2.    @Override  

3.    protected void configure() {  

4.  

5.        /* 

6.         * This tells Guice that whenever it sees a dependency on a 

7.         * TransactionLog, it should satisfy the dependency using a 

8.         * DatabaseTransactionLog. 

9.         */  

10.        bind(TransactionLog.class).to(DatabaseTransactionLog.class);  

11.  

12.        /* 

13.         * Similarly, this binding tells Guice that when CreditCardProcessor is 

14.         * used in a dependency, that should be satisfied with a 

15.         * PaypalCreditCardProcessor. 

16.         */  

17.        bind(CreditCardProcessor.class).to(PaypalCreditCardProcessor.class);  

18.    }  

19.}  

publicclassBillingModuleextendsAbstractModule{

@Override

protectedvoidconfigure(){

/*

*ThistellsGuicethatwheneveritseesadependencyona

*TransactionLog,itshouldsatisfythedependencyusinga

*DatabaseTransactionLog.

*/

bind(TransactionLog.class).to(DatabaseTransactionLog.class);

/*

*Similarly,thisbindingtellsGuicethatwhenCreditCardProcessoris

*usedinadependency,thatshouldbesatisfiedwitha

*PaypalCreditCardProcessor.

*/

bind(CreditCardProcessor.class).to(PaypalCreditCardProcessor.class);

}

}

好了,现在万事俱备,就让我们一起看看怎么使用Guice进行依赖注入吧:

[java]viewplaincopyprint?

1.public static void main(String[] args) {  

2.      

3.    /*  

4.     * Guice.createInjector() takes your Modules, and returns a new Injector  

5.     * instance. Most applications will call this method exactly once, in their  

6.     * main() method.  

7.     */    

8.    Injector injector = Guice.createInjector(new BillingModule());    

9.    

10.    /*  

11.     * Now that we've got the injector, we can build objects.  

12.     */    

13.    RealBillingService billingService = injector.getInstance(RealBillingService.class);  

14.}  

publicstaticvoidmain(String[]args){

/*

*Guice.createInjector()takesyourModules,andreturnsanewInjector

*instance.Mostapplicationswillcallthismethodexactlyonce,intheir

*main()method.

*/

Injectorinjector=Guice.createInjector(newBillingModule());

/*

*Nowthatwe'vegottheinjector,wecanbuildobjects.

*/

RealBillingServicebillingService=injector.getInstance(RealBillingService.class);

}

以上就是使用Guice的一个完整的例子,很简单吧,不需要繁琐的配置,只需要定义一个Module来表述接口和实现类,以及父类和子类之间的关联关系的绑定。

本文不对比guice和spring,只是单纯介绍Guice的用法。

三.绑定方式的介绍

从上面我们可以看出,其实对于Guice而言,程序员所要做的,只是创建一个代表关联关系的Module,然后使用这个Module即可得到对应关联的对象。

因此,主要的问题其实就是在如何关联实现类和接口(子类和父类)。

1.在自定义的Module类中进行绑定

1.1在configure方法中绑定

1.1.1链式绑定

链式绑定是最简单,最直接,也是使用最多的绑定方式。

[java]viewplaincopyprint?

1.protected void configure() {    

2.    bind(TransactionLog.class).to(DatabaseTransactionLog.class);    

3.}  

protectedvoidconfigure(){

bind(TransactionLog.class).to(DatabaseTransactionLog.class);

}

就是直接把一种类型的class对象绑定到另外一种类型的class对象,这样,当外界获取TransactionLog时,其实返回的就是一个DatabaseTransactionLog对象。

当然,链式绑定也可以串起来,如:

[java]viewplaincopyprint?

1.protected void configure() {    

2.    bind(TransactionLog.class).to(DatabaseTransactionLog.class);    

3.    bind(DatabaseTransactionLog.class).to(MySqlDatabaseTransactionLog.class);    

4.}  

protectedvoidconfigure(){

bind(TransactionLog.class).to(DatabaseTransactionLog.class);

bind(DatabaseTransactionLog.class).to(MySqlDatabaseTransactionLog.class);

}

这样,当外界请求TransactionLog时,其实返回的就会是一个MySqlDatabaseTransactionLog对象。

1.1.2注解(Annotations)绑定

链式绑定针对于同样的类型都绑定到同一种目标类型时,非常好用,但是对于一个接口有多种实现的时候,链式绑定就不好区分该用哪种实现了。

可以把Annotations绑定方式看作是链式绑定的一种扩展,专门用来解决这种同一个接口有多种实现的问题。

Annotations绑定又可以分为两种,一种是需要自己写Annotations,另外一种则简化了一些。

1.1.2.1自己写Annotations的方式

首先,写一个注解

[java]viewplaincopyprint?

1.import com.google.inject.BindingAnnotation;  

2.import java.lang.annotation.Target;  

3.import java.lang.annotation.Retention;  

4.import static java.lang.annotation.RetentionPolicy.RUNTIME;  

5.import static java.lang.annotation.ElementType.PARAMETER;  

6.import static java.lang.annotation.ElementType.FIELD;  

7.import static java.lang.annotation.ElementType.METHOD;  

8.  

9.@BindingAnnotation  

10.@Target({ FIELD, PARAMETER, METHOD })  

11.@Retention(RUNTIME)  

12.public @interface PayPal {  

13.}  

importcom.google.inject.BindingAnnotation;

importjava.lang.annotation.Target;

importjava.lang.annotation.Retention;

importstaticjava.lang.annotation.RetentionPolicy.RUNTIME;

importstaticjava.lang.annotation.ElementType.PARAMETER;

importstaticjava.lang.annotation.ElementType.FIELD;

importstaticjava.lang.annotation.ElementType.METHOD;

@BindingAnnotation

@Target({FIELD,PARAMETER,METHOD})

@Retention(RUNTIME)

public@interfacePayPal{

}

然后,使用这个注解去修饰目标字段或参数,如:

[java]viewplaincopyprint?

1.public class RealBillingService implements BillingService {  

2.  

3.    @Inject  

4.    public RealBillingService(@PayPal CreditCardProcessor processor,  

5.            TransactionLog transactionLog) {  

6.    }  

7.}  

publicclassRealBillingServiceimplementsBillingService{

@Inject

publicRealBillingService(@PayPalCreditCardProcessorprocessor,

TransactionLogtransactionLog){

}

}

[java]viewplaincopyprint?

1.public class RealBillingService implements BillingService {  

2.    @Inject  

3.    @Www  

4.    private CreditCardProcessor processor;  

5.}  

publicclassRealBillingServiceimplementsBillingService{

@Inject

@Www

privateCreditCardProcessorprocessor;

}

最后,在我们进行链式绑定时,就可以区分一个接口的不同实现了,如:

[java]viewplaincopyprint?

1.bind(CreditCardProcessor.class)    

2.    .annotatedWith(PayPal.class)    

3.    .to(PayPalCreditCardProcessor.class);  

bind(CreditCardProcessor.class)

.annotatedWith(PayPal.class)

.to(PayPalCreditCardProcessor.class);

这样,被Annotations PayPal?

修饰的CreditCardProcessor就会被绑定到目标实现类PayPalCreditCardProcessor。

如果有其他的实现类,则可把用不同Annotations修饰的CreditCardProcessor绑定到不同的实现类

1.1.2.2使用@Named的方式

使用@Named的方式和上面自己写Annotation的方式很类似,只不过做了相应的简化,不再需要自己去写Annotation了。

[java]viewplaincopyprint?

1.public class RealBillingService implements BillingService {  

2.  

3.    @Inject  

4.    public RealBillingService(@Named("Checkout") CreditCardProcessor processor,  

5.            TransactionLog transactionLog) {  

6.    }  

7.}  

publicclassRealBillingServiceimplementsBillingService{

@Inject

publicRealBillingService(@Named("Checkout")CreditCardProcessorprocessor,

TransactionLogtransactionLog){

}

}

直接使用@Named修饰要注入的目标,并起个名字,下面就可以把用这个名字的注解修饰的接口绑定到目标实现类了

[java]viewplaincopyprint?

1.bind(CreditCardProcessor.class)    

2.    .annotatedWith(Names.named("Checkout"))    

3.    .to(CheckoutCreditCardProcessor.class);   

bind(CreditCardProcessor.class)

.annotatedWith(Names.named("Checkout"))

.to(CheckoutCreditCardProcessor.class);

1.1.3实例绑定

上面介绍的链式绑定是把接口的class对象绑定到实现类的class对象,而实例绑定则可以看作是链式绑定的一种特例,它直接把一个实例对象绑定到它的class对象上。

[java]viewplaincopyprint?

1.bind(String.class)    

2.    .annotatedWith(Names.named("JDBC URL"))    

3.    .toInstance("jdbc:

mysql:

//localhost/pizza");    

4.bind(Integer.class)    

5.    .annotatedWith(Names.named("login timeout seconds"))    

6.    .toInstance(10);  

bind(String.class)

.annotatedWith(Names.named("JDBCURL"))

.toInstance("jdbc:

mysql:

//localhost/pizza");

bind(Integer.class)

.annotatedWith(Names.named("logintimeoutseconds"))

.toInstance(10);

需要注意的是,实例绑定要求对象不能包含对自己的引用。

并且,尽量不要对那种创建实例比较复杂的类使用

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 法律文书 > 判决书

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1