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}) |
可以在再被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); |
使用@Named來Inject: @Inject @Named(value="A") private IFoo foo; |
用@Named的好處可以不用自訂annotation,其作用和bind toInstance也有點異曲同工之妙。而且常用於常數初始化設定,可以讀properties檔作為@Named的賦值,其Module配置DI方式如下:
public class MyModule extends AbstractModule { private void loadProperties(Binder binder) { Names.bindProperties(binder, appProperties); } catch (IOException e) { |
其使用方式如下,value="LicenseKey"即是properties檔裡的key值:
@Inject @Named(value="LicenseKey") private String key; |