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();
} (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
