Inject
標記可注入的構(gòu)造函數(shù)捐川、方法和字段钻洒》茏耍可以應(yīng)用于靜態(tài)成員和實例成員∷乇辏可注入成員可以具有任何訪問修飾符(private
称诗、package-private
、protected
头遭、public
)寓免。首先注入構(gòu)造函數(shù),然后是字段计维,最后是方法袜香。超類中的字段和方法在子類中的字段和方法之前被注入。沒有指定同一類中的字段和方法之間的注入順序鲫惶。
可注入的構(gòu)造函數(shù)用@Inject
注釋蜈首,并且接受零個或多個依賴項作為參數(shù)。每個類最多只能應(yīng)用@Inject
在一個構(gòu)造函數(shù)上欠母。
@Inject
對于沒有其他構(gòu)造函數(shù)的公共無參數(shù)構(gòu)造函數(shù)是可選的欢策。這使得注入器能夠調(diào)用默認構(gòu)造函數(shù)。
@Inject
ConstructorModifiers opt
SimpleTypeName(FormalParameterList opt)
Throws opt
ConstructorBody opt
可注入字段:
?-- 使用@Inject注釋赏淌。
?-- 不是final的踩寇。
?-- 可以有任何其他有效的名稱。
可注入方法:
?-- 使用@Inject注釋六水。
?-- 不是抽象的姑荷。
?-- 不要聲明自己的類型參數(shù)。
?-- 可以返回一個結(jié)果缩擂。
?-- 可以有任何其他有效的名稱。
?-- 接受零個或多個依賴項作為參數(shù)添寺。
@Inject
MethodModifiers opt
ResultType
Identifier(FormalParameterList opt)
Throws opt
MethodBody
注入器忽略注入方法的結(jié)果胯盯,但是允許空void
返回類型支持在其他上下文中使用該方法(例如,構(gòu)建器風格的方法鏈接)计露。
例如:
public class Car {
//可注入的構(gòu)造函數(shù)
@Inject
public Car(Engine) {...}
//可注入的字段
@Inject
private Provider<Seat> seatProvider;
//可注入包級私有方法
@Inject
void install(Windshield windshield, Trunk trunk) {...}
}
用@Inject
注解的方法覆蓋了用@Inject
注解的方法博脑,對于每個實例的每個注入請求只注入一次。如果一個方法沒有@Inject
注解票罐,但是覆蓋了一個@Inject
注解的方法叉趣,那么這個方法將不會被注入。
需要注入帶有@Inject
注解的成員该押。雖然可注入成員可以使用任何可訪問性修飾符(包括private
)疗杉,但平臺或注入器限制(如安全性限制或缺少反射支持)可能會阻止非公共成員的注入。
Qualifiers(限定符)
@Qualifier
可以注解可注入的字段或參數(shù)蚕礼,并結(jié)合類型標識要注入的實現(xiàn)烟具。限定符是可選的梢什,當在獨立于注入器的類中與@Inject
一起使用時,不應(yīng)該有多個限定符注解單個字段或參數(shù)朝聋。在下面的例子中嗡午,限定符是粗體的:
public class Car {
@Inject
private @Leather Provider<Seat> seatProvider;
@Inject
void install(@Tinted Windshield windshield, @Big Trunk trunk) {...}
}
如果一個可注入方法覆蓋另一個方法,則覆蓋方法的參數(shù)不會自動從覆蓋方法的參數(shù)繼承限定符冀痕。
Injectable Values(可注入值)
對于給定類型T和可選限定符荔睹,注入器必須能夠注入用戶指定的類:
?-- 賦值是否與T和相容.
?-- 具有可注入構(gòu)造函數(shù)。
例如言蛇,用戶可以使用外部配置來選擇T的實現(xiàn)僻他,除此之外,注入的值取決于注入器實現(xiàn)及其配置猜极。
Circular Dependencies(循環(huán)依賴)
檢測和解析循環(huán)依賴關(guān)系是留給注入器實現(xiàn)的練習中姜。兩個構(gòu)造函數(shù)之間的循環(huán)依賴關(guān)系是一個明顯的問題,但是您也可以在可注入字段或方法之間有循環(huán)依賴關(guān)系:
class A {
@Inject B b;
}
class B {
@Inject A a;
}
構(gòu)造A
的一個實例時,不明智的注入器實現(xiàn)可能會進入一個無限循環(huán)構(gòu)造的實例跟伏,B
引用A
,A
的第二個實例引用B
,B
的第二個實例上引用第二個實例的A
,等等丢胚。
保守的注入器可能在構(gòu)建時檢測到循環(huán)依賴項并生成錯誤,此時程序員可以通過注入Provider<A>
或Provider<B>
來打破循環(huán)依賴項受扳,而不是分別注入A
或B
携龟。直接從注入的構(gòu)造函數(shù)或方法調(diào)用提供程序上的get()
,會破壞提供程序跳出循環(huán)依賴項的能力。在方法或字段注入的情況下勘高,確定依賴項的作用域(例如使用Singleton
作用域)也可以啟用有效的循環(huán)關(guān)系峡蟋。
Provider
提供T
的實例。通常由注入器實現(xiàn)华望。對于可以注入的任何類型T
蕊蝗,您也可以注入Provider<T>
。與直接注入T
相比赖舟,注入Provider<T>
可以:
?-- 獲取多個實例蓬戚。
?-- 延后或者可選地獲取一個實例。
?-- 跳出循環(huán)依賴宾抓。
?-- 抽象作用域子漩,以便您可以從包含作用域中的實例查找較小作用域中的實例。
例如:
public class Car {
public Car(Provider<Seat> seatProvider) {
Seat driver = seatProvider.get();
Seat passenger = seatProvider.get();
...
}
}
Qualifier
限定符標記注解石洗。任何人都可以定義一個新的限定符幢泼。一個限定符注釋:
?-- 是用@Qualifier、@Retention(RUNTIME)和@Documentation注解的讲衫。
?-- 可以包含屬性
?-- 可能是公共API的一部分缕棵,很像依賴項類型,但不像實現(xiàn)類型不需要是公共API的一部分。
?-- 如果使用@Target注解挥吵,可能會限制使用重父。雖然該規(guī)范只涉及對字段和參數(shù)應(yīng)用限定符,但一些注入器配置可能會在其他地方(例如在方法或類上)使用限定符注解忽匈。
例如:
@java.lang.annotation.Documented
@java.lang.annotation.Retention(RUNTIME)
@javax.inject.Qualifier
public @interface Leather {
Color color() default Color.TAN;
public enum Color {RED, BLACK, TAN}
}
Named
基于字符串的Qualifier
房午。
使用實例:
public class Car {
@Inject @Named("driver") Seat driverSeat;
@Inject @Named("passenger") Seat passengerSeat;
...
}
Scope
標記作用域注解。作用域注解應(yīng)用于包含可注入構(gòu)造函數(shù)的類丹允,并控制注入器如何重用該類型的實例郭厌。默認情況下,如果沒有作用域注解雕蔽,注入器將創(chuàng)建一個實例(通過注入類型的構(gòu)造函數(shù))折柠,使用該實例進行一次注入,然后忘記它批狐。如果存在作用域注解扇售,則注入器可以保留實例,以便在以后的注入中重用嚣艇。如果多個線程可以訪問一個作用域?qū)嵗斜敲此膶崿F(xiàn)應(yīng)該是線程安全的。作用域本身的實現(xiàn)由注入器決定食零。
接下來的例子中困乒,作用域注解@Singleton
確保我們只有一個Log實例:
@Singleton
class Log {
void log(String message) { ... }
}
如果注入器在同一類上遇到多個作用域注解或不支持的作用域注解,則會生成錯誤贰谣。
一個作用域注解:
?-- 是用@Scope娜搂、@Retention(RUNTIME)和@Documentation注釋的。
?-- 沒有屬性吱抚。
?-- 通常不是@inheritance百宇,所以作用域與實現(xiàn)繼承是正交的。
?-- 如果使用@Target注釋秘豹,可能會限制使用恳谎。雖然該規(guī)范只涵蓋將作用域應(yīng)用于類,但一些注入器配置可能會在其他地方(例如工廠方法結(jié)果)使用作用域注解憋肖。
例如:
@java.lang.annotation.Documented
@java.lang.annotation.Retention(RUNTIME)
@javax.inject.Scope
public @interface RequestScoped {}
使用@Scope
注解于作用域注解,可以幫助注入器檢測:程序員在類上使用作用域注解但忘記在注入器中配置作用域的情況婚苹。保守的注入器將生成錯誤岸更,而不是不應(yīng)用于作用域。
Singleton
標識注入器只實例化一次的類型膊升。不繼承怎炊。