CDI(Weld)基础<3>依赖关系注入(DI)和编程查找
一.Inject点(三种方式)1.构造器依赖注入public class SomeBean { private final Service service; @Inject public SomeBean(Service service){ this.service = service; } } 说明:每个Bean只能有一个@Inject方式的构造方法. 2.字段注入(推荐)public class SomeBean { @Inject private Service service; }这种推荐定义为private.在这种情况下,当容器初始化一个SomeBean类型的bean将注入正确的Service bean,不需要任何setter方法。 3.初始化方法参数注入public class SomeBean { private Service service; @Inject public void setService(Service service) { this.service = service; } }一般我不喜欢这么用. bean可以有多个初始化方法。 4.注入说明,顺序说明依赖关系注入发生在容器第一次实例化bean 实例时。顺序如下:
构造器----字段----初始化方法---@PostConstruct方法 注意:
CDI还支持参数注入一些其他方法调用的容器。例如,参数注入是支持生产方法: @Produces Checkout createCheckout(ShoppingCart cart) { return new Checkout(cart); }这种情况,是不需要@inject的. 二:Qualifier Qualifier注解的作用在第一章已经说过. @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,PARAMETER}) public @interface Asynchronous {} @Asynchronous public class AsynchronousPaymentProcessor implements PaymentProcessor { public void process(Payment payment) { ... } } 1.构造器注入@Inject public Checkout(@Synchronous PaymentProcessor syncPaymentProcessor,@Asynchronous PaymentProcessor asyncPaymentProcessor) { this.syncPaymentProcessor = syncPaymentProcessor; this.asyncPaymentProcessor = asyncPaymentProcessor; } 2.字段注入(推荐)@Inject @Synchronous PaymentProcessor syncPaymentProcessor; @Inject @Asynchronous PaymentProcessor asyncPaymentProcessor; 3.初始化方法注入public void setPaymentProcessors(@Synchronous PaymentProcessor syncPaymentProcessor,@Asynchronous PaymentProcessor asyncPaymentProcessor) { this.syncPaymentProcessor = syncPaymentProcessor; this.asyncPaymentProcessor = asyncPaymentProcessor; } 三:内置的Qualifiers==>@Default @Any1.@Default如果没有指定具体的qualifiers,那么系统默认加一个@Defaule.2.@Any用法如果我们有多个Bean实现了某个接口,我们要注入所有的这个接口类型的托管Bean,如下面这种方式获取.public class SomeBean { @Inject public void listServiceImplementations( @Any Instance<Service> serviceList) { for(Service service : serviceList){ System.out.println(service.getClass().getCanonicalName()); } } } 四:Multiple qualifiersInject点可以指定多个限定符:@Synchronous @Reliable public class SynchronousReliablePaymentProcessor implements PaymentProcessor { public void process(Payment payment) { ... } }使用: @Inject @Synchronous @Reliable PaymentProcessor syncPaymentProcessor; 五:Qualifiers的会员概念,用法 你会看到一种用法@Qualifier数符可以有成员。 @Qualifier @Retention(RUNTIME) @Target({METHOD,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,TYPE}) public @interface Payment{ EnumMoneyType value(); //下面的comment将不起作用,被容器忽略 @Nonbinding String comment() default ""; } 四:通过编程获取上下文实例 在某些情况下,注入不是最方便的方式来获取上下文引用.
这种情况下,应该这样使用: @InjectInstance<PaymentProcessor>paymentProcessorSource;实例的get() 方法创建的bean的上下文实例。这样也会有个延迟加载的意思在里面. PaymentProcessorp=paymentProcessorSource.get();当然,按照我们在本章上面说的,也可以这样: @Inject@AsynchronousInstance<PaymentProcessor>paymentProcessorSource;现在,返回的PaymentProcessor get()将是限定符为@Asynchronous的实例。 @Any+Instance select()或者,我们可以动态地指定限定符。首先,我们将@Any限定符添加到注入点. import javax.enterprise.inject.Instance; ... @Inject @Any Instance<PaymentProcessor> paymentProcessorSource; 接下来,我们需要获得我们的限定符类型的一个实例。因为注释是接口,我们不能只写新的Asynchronous().这也是非常乏味的从头创建一个注释类型的具体实现。相反,CDI让我们过AnnotationLiteral helper类获得一个限定符实例通。 class AsynchronousQualifier extends AnnotationLiteral<Asynchronous> implements Asynchronous {}在某些情况下,我们可以使用一个匿名类: PaymentProcessor p = paymentProcessorSource.select(new AnnotationLiteral<Asynchronous>() {});然而,我们不能用一个匿名类实现一个限定符类型和成员。 所以我们可以通过qualifier of Instance select()方法。 Annotation qualifier = synchronously ? new SynchronousQualifier() : new AsynchronousQualifier(); PaymentProcessor p = anyPaymentProcessor.select(qualifier).get().process(payment); 五:InjectionPoint对象用法比如说我们使用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()); } } 在其他的类中,可以如下代码这样注入 @InjectLoggerlog;容器提供了一个内置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(); } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |