Saz*_*man 9 jsf dependency-injection seam java-ee cdi
首先,我要澄清一下,这篇文章并不是要批评CDI,而是要发现CDI设计背后的思路和假设,这对设计任何使用CDI的网络应用程序都有明显的影响.
CDI(Java EE 6)最显着的特征之一是类型安全.Jboss Seam在类型上并不安全.它使用name来限定要注入的任何实例.如下:
@Name("myBean")
public class MyBean implements Bean {
...
}
@Name("yourBean")
public class YourBean implements Bean {
...
}
Run Code Online (Sandbox Code Playgroud)
注入MyBean时,可以这样做:
@In
private Bean myBean; //myBean is injected
@In
private Bean yourBean; //yourBean is injected
Run Code Online (Sandbox Code Playgroud)
早期版本的Spring(3.0之前),这种类型的注入发生在下面:
只需在bean配置文件中定义bean:
<bean id="myBean" class="com.example.common.MyBean">
...
</bean>
<bean id="yourBean" class="com.example.common.YourBean">
...
</bean>
Run Code Online (Sandbox Code Playgroud)
并使用命名限定符,决定使用哪一个:
@Autowired
@Qualifier("myBean")
private Bean bean;
@Autowired
@Qualifier("yourBean")
private Bean bean;
Run Code Online (Sandbox Code Playgroud)
但现在在CDI中,首先需要Qualifier为任何特定类型的对象定义自定义注释.然后使用该注释来限定该对象.在一天结束时,当您查看源代码时,您会发现,您浪费了大量时间为依赖注入编写大量自定义注释.Java社区正朝着注释方向发展,将基于XML的配置(冗长的XML)留在后面.有没有什么可以说服任何人认为这(使用自定义注释键入安全性)不是冗长的注释,而是作为CDI的优秀和杰出特征?
编辑:
积分,推动突出显示
关于以上几点的简短讨论
@Name用作限定符.所以,是的,在大型应用程序中,在实际需要时使用类型安全是可行的.谢谢,快乐的编码!
rdc*_*rng 17
如果您有多个接口实现,那么问问自己 - 部署后是否需要区分它们?
如果答案是肯定的,那么你仍然不需要限定词.原因如下:
要使用您自己的示例:
public class MyBean implements Bean {
...
}
public class YourBean implements Bean {
...
}
Run Code Online (Sandbox Code Playgroud)
然后,你只需:
@Inject MyBean bean;
Run Code Online (Sandbox Code Playgroud)
要么
@Inject YourBean bean;
Run Code Online (Sandbox Code Playgroud)
如果你不喜欢你的实例变量是具体类型而宁愿看到一个接口,那么这样做:
private Bean bean;
@Inject
public void setBean(MyBean bean) {
this.bean = bean;
}
Run Code Online (Sandbox Code Playgroud)
要么
private Bean bean;
@Inject
public void setBean(YourBean bean) {
this.bean = bean;
}
Run Code Online (Sandbox Code Playgroud)
在上述所有情况下,它完全没有资格,绝对是类型安全的,绝对不是冗长的.
然后,详细说明最后一点 - 开发人员是否需要选择适当的实现,或者选择是否有问题?
如果选择可能有问题,那么使用生产者:
@Produces
public Bean obtainTheAppropriateBean(InjectionPoint ip) {
if (meetsConditionA(ip)) {
return getBeanImplA();
} else if (meetsConditionB(ip)) {
return getBeanImplB();
} else if (...) {
...
} else {
return getDefaultBeanImpl();
}
}
Run Code Online (Sandbox Code Playgroud)
仍然没有资格,类型安全,可能仍然没有冗长(自动化的贸易选择).
有关如何使用InjectionPoint API 的这一观点和想法,请参阅此文章.
在上面的例子之后,我可以看到这个问题.答案是肯定的,这里列出了您可能选择使用它们的非详尽清单:
想象一下,您有多个接口和多个实现的情况.特定实现可能具有共同的可区分特征,并且这些特征对于所有接口都是通用的.举个例子,让我们看看Java Colections Framework,特别是List,Set和Map接口.每个都有多个实现,但是所有或某些接口都有共同的特征.例如链接节点(快速迭代) - 想想LinkedList,LinkedHashSet,LinkedHashMap; 排序(排序) - 想想TreeSet,TreeMap; 基于哈希表(快速插入/删除/包含) - 想想HashSet,LinkedHashSet,HashMap,LinkedHashMap; concurent; 随机访问; 等等.现在,你可以定义的@Linked,@Sorted和@Hash注释.然后注入:
@Inject @Linked @Hash private Map map;
@Inject @Sorted private Map map;
@Inject @Hash private Set set;
@Inject @Hash private Set set;
Run Code Online (Sandbox Code Playgroud)
现在,是否值得为集合框架执行此操作?我不会这样做,但我有一个类似于我在当前工作项目中所描述的情况(抱歉,无法讨论).
最后,您可以使用限定符将参数传递给生成器@Nonbinding.继续上面的集合框架,定义:
@Qualifier
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Hash {
@Nonbinding int capacity() default 16;
@Nonbinding float loadFactor() default 0.75f;
}
Run Code Online (Sandbox Code Playgroud)
这样,您可以将所需的容量和加载因子传递给生成器,返回任何哈希表,如下所示:
@Inject @Hash(capacity = 256, loadFactor = 0.85f) private Set set;
@Inject @Hash private Set set;
@Inject @Hash(capacity = 8, loadFactor = 0.65f) private Map map;
Run Code Online (Sandbox Code Playgroud)我希望这回答了你的问题.这肯定是我爱CDI的部分原因.
| 归档时间: |
|
| 查看次数: |
2291 次 |
| 最近记录: |