close

  Guice使用annotation進行DI,在和使用XML配置相較之下,就每次變動都要改Java程式再編譯,而XML也許不需要。用於商業版,這個缺點也許反而是優點。Guice還提annotation與Provider來進行DI,這裡講用annotation。

第一例:用annotation來配置DI,即自訂一個annotation,姑名為@Blue。怎麼自訂請參考上一篇:annotation usage

所以@Blue的內容如下:

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention ( RetentionPolicy.RUNTIME )
@Documented
@BindingAnnotation  // import com.google.inject.BindingAnnotation
public @interface Blue {}

可以在再被Inject的目標這麼設定,如下:

@Inject @Blue private IFoo foo;

感覺像Spring對field變數做@Autowired,而使用它(IFoo)的method的類別不能在建構函數裡使用,看來尚未被注入。

最後在繼承或實作Guice Module,做如下的bind :

bind(IFoo.class).annotatedWith(Blue.class).to(FooImpl.class);

  當然每次都要自訂annotation也煩,何況可能有同annotation但賦值不同的需求。所以可以用@Named:

第二例:用annotation賦值來配置DI。這時不用再自訂annotation,而是用@Named,有點像Spring的@Value。

在Module的設定:

bind(IFoo.class).annotatedWith(Names.named("A")).to(FooImpl.class);
bind(IFoo.class).annotatedWith(Names.named("B")).to(BarImpl.class);

使用@Named來Inject:

@Inject @Named(value="A") private IFoo foo;
@Inject @Named(value="B") private IFoo bar;

用@Named的好處可以不用自訂annotation,其作用和bind toInstance也有點異曲同工之妙。而且常用於常數初始化設定,可以讀properties檔作為@Named的賦值,其Module配置DI方式如下:

public class MyModule  extends AbstractModule {
    @Override
    protected void configure() {
        this.loadProperties(super.binder());
    }

    private void loadProperties(Binder binder) {
        InputStream stream =
            MyModule.class.getResourceAsStream("./app.properties");   
        Properties appProperties = new Properties();
        try {
            appProperties.load(stream);

            Names.bindProperties(binder, appProperties);

        } catch (IOException e) {
            binder.addError(e);
        }
    }
}

  其使用方式如下,value="LicenseKey"即是properties檔裡的key值:

@Inject @Named(value="LicenseKey") private String key;
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 Jemmy 的頭像
    Jemmy

    Jemmy Walker

    Jemmy 發表在 痞客邦 留言(0) 人氣()