public class SomeBean { private final Service service; @Inject public SomeBean(Service service){ this.service = service; } }
說明:每一個Bean只能有一個@Inject方式的構造方法. java
public class SomeBean { @Inject private Service service; }這種推薦定義爲private.在這種狀況下,當容器初始化一個SomeBean類型的bean將注入正確的Service bean,不須要任何setter方法。
public class SomeBean { private Service service; @Inject public void setService(Service service) { this.service = service; } }通常我不喜歡這麼用. bean能夠有多個初始化方法。
依賴關係注入發生在容器第一次實例化bean 實例時。順序以下: 編程
構造器----字段----初始化方法---@PostConstruct方法 async
注意:CDI還支持參數注入一些其餘方法調用的容器。例如,參數注入是支持生產方法: 函數
@Produces Checkout createCheckout(ShoppingCart cart) { return new Checkout(cart); }這種狀況,是不須要@inject的.
Qualifier註解的做用在第一章已經說過.
好比咱們有多個bean實現特定的bean類型,注入某個bean就必須應該使用限定符註釋注入.
下面是第一個PaymentProcessor的Qualifier this
@Qualifier @Retention(RUNTIME) @Target({TYPE, METHOD, FIELD, PARAMETER}) public @interface Synchronous {}
@Synchronous public class SynchronousPaymentProcessor implements PaymentProcessor { public void process(Payment payment) { ... } }第二個:
@Qualifier @Retention(RUNTIME) @Target({TYPE, METHOD, FIELD, PARAMETER}) public @interface Asynchronous {}
@Asynchronous public class AsynchronousPaymentProcessor implements PaymentProcessor { public void process(Payment payment) { ... } }
@Inject public Checkout(@Synchronous PaymentProcessor syncPaymentProcessor, @Asynchronous PaymentProcessor asyncPaymentProcessor) { this.syncPaymentProcessor = syncPaymentProcessor; this.asyncPaymentProcessor = asyncPaymentProcessor; }
@Inject @Synchronous PaymentProcessor syncPaymentProcessor; @Inject @Asynchronous PaymentProcessor asyncPaymentProcessor;
public void setPaymentProcessors(@Synchronous PaymentProcessor syncPaymentProcessor, @Asynchronous PaymentProcessor asyncPaymentProcessor) { this.syncPaymentProcessor = syncPaymentProcessor; this.asyncPaymentProcessor = asyncPaymentProcessor; }
public class SomeBean { @Inject public void listServiceImplementations( @Any Instance<Service> serviceList) { for(Service service : serviceList){ System.out.println(service.getClass().getCanonicalName()); } } }
@Synchronous @Reliable public class SynchronousReliablePaymentProcessor implements PaymentProcessor { public void process(Payment payment) { ... } }使用:
@Inject @Synchronous @Reliable PaymentProcessor syncPaymentProcessor;
你會看到一種用法@Qualifier數符能夠有成員。
這種方法將避免在單個應用程序中編寫的@Qualifier數量太多形成爆炸. spa
@Qualifier @Retention(RUNTIME) @Target({METHOD, FIELD, PARAMETER, TYPE}) public @interface Payment{ EnumMoneyType value(); }
//USD--美圓 CNY--人民幣 public enum EnumMoneyType{ USD,CNY; }咱們在Qualifiers中加入了一個屬性,爲一個枚舉,上面這個就是枚舉.固然你可使用默認值.這裏我沒寫.下面就是使用這個Qualifier的2個示例:
@Payment(EnumMoneyType.USD) public class PRacquet implements RacquetType{ ..... }
@Payment(EnumMoneyType.CNY) public class FRacquet implements RacquetType{ ..... }咱們也可讓容器忽視成員,用@Nonbinding限定符註釋類型的成員容器就是忽略。
@Qualifier @Retention(RUNTIME) @Target({METHOD, FIELD, PARAMETER, TYPE}) public @interface Payment{ EnumMoneyType value(); //下面的comment將不起做用,被容器忽略 @Nonbinding String comment() default ""; }
在某些狀況下,注入不是最方便的方式來獲取上下文引用.
例如, code
這種狀況下,應該這樣使用: 對象
@Inject Instance<PaymentProcessor> paymentProcessorSource;實例的get() 方法建立的bean的上下文實例。這樣也會有個延遲加載的意思在裏面.
PaymentProcessor p = paymentProcessorSource.get();固然, 按照咱們在本章上面說的,也能夠這樣:
@Inject @Asynchronous Instance<PaymentProcessor> paymentProcessorSource;如今,返回的PaymentProcessor get()將是限定符爲@Asynchronous的實例。
或者,咱們能夠動態地指定限定符。首先,咱們將@Any限定符添加到注入點. 接口
import javax.enterprise.inject.Instance; ... @Inject @Any Instance<PaymentProcessor> paymentProcessorSource;
接下來,咱們須要得到咱們的限定符類型的一個實例。由於註釋是接口,咱們不能只寫新的Asynchronous().這也是很是乏味的從頭建立一個註釋類型的具體實現。相反,CDI讓咱們過AnnotationLiteral helper類得到一個限定符實例通。 ip
class AsynchronousQualifier extends AnnotationLiteral<Asynchronous> implements Asynchronous {}在某些狀況下,咱們可使用一個匿名類:
PaymentProcessor p = paymentProcessorSource.select(new AnnotationLiteral<Asynchronous>() {});然而,咱們不能用一個匿名類實現一個限定符類型和成員。
Annotation qualifier = synchronously ? new SynchronousQualifier() : new AsynchronousQualifier(); PaymentProcessor p = anyPaymentProcessor.select(qualifier).get().process(payment);
好比說咱們使用logger,是這樣寫
Logger log = Logger.getLogger(MyClass.class.getName());
但經過CDI InjectionPoint對象
import javax.enterprise.inject.spi.InjectionPoint; import javax.enterprise.inject.Produces; class LogFactory { @Produces Logger createLogger(InjectionPoint injectionPoint) { return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName()); } }
在其餘的類中,能夠以下代碼這樣注入
@Inject Logger log;容器提供了一個內置bean實現InjectionPoint接口:
public interface InjectionPoint { public Type getType(); public Set<Annotation> getQualifiers(); public Bean<?> getBean(); public Member getMember(); public Annotated getAnnotated(); public boolean isDelegate(); public boolean isTransient(); }