1

就简单性和正确性而言,注入具有不同作用域的同一类的对象的最佳方法是什么?

在一个 servlet 中,我想注入具有不同范围的同一类的对象。还不知道要不要用jsf。

  • 简单:Qualifier为每个作用域制作一个和一个生产者方法太多了;做一个接口,两个类,在里面添加替换beans.xml也太多了;有Address#isCurrent()方法没有意义。
  • 正确性:JSR299, 3.11 说:不推荐使用 @Named 作为注入点限定符。 还是不知道为什么。
    虽然@Named在注入点使用适用于@ApplicationScopedand @RequestScoped但不适用于@SessionScoped. 请参阅下面的命名片段

在春天很容易:
春天片段

<bean id="currentAddress" class="xxx.Address" scope="session" />
<bean id="newAddress" class="xxx.Address" scope="request" />
<bean id="servlet" class="xxx.MyServlet">
 <property name="currentAddress" ref="currentAddress" />
 <property name="newAddress" ref="newAddress" />
</bean>


命名片段

/* Address class */
@Produces @RequestScoped @Named(value="request")
 public Address getNewAddress(){
 return new Address();
}

@Produces @SessionScoped @Named(value="application")
 public Address getCurrentAddress(){
 return new Address();
}
/* Servlet */
@Inject @RequestScoped @Named("request")  private Address newAddress;
@Inject @ApplicationScoped @Named("application") private Address currentAddress;
4

2 回答 2

4

包含此建议的原因与人们更喜欢枚举而不是任意字符串作为常量的原因相同,因为它不是类型安全的。您可以很容易地输入错误的类名,它会编译得很好并且在运行时会失败。包含该建议是因为在大多数情况下,当您能够在编译时强制执行这些约束时,@named 会使您的应用程序变得不必要地脆弱。

这是一篇很好的文章,概述了原因:

处理这种情况的首选方法是使用带有枚举值的@Qualifiers。查看标题为“String Qualifiers are Legacy”和“The Right Way”的部分,了解处理此问题的步骤。

于 2012-04-29T17:37:24.823 回答
2

感谢@nsfyn55 指出这篇好文章,在阅读了“正确的方法”部分后,我想出了我认为在简单性和正确性方面实现它的最佳方法。

所以我只使用一个接口作为限定符注释。

/* Qualifier annotation */
@Qualifier
@Retention(RUNTIME)
@Target({FIELD,METHOD})
public @interface Scope {

 Type value();

 enum Type { REQUEST, SESSION, APPLICATION };
}


/* Address class */
@Produces @Scope(REQUEST) @RequestScoped
 public Address request() {
 return new Address();
}

@Produces @Scope(SESSION) @SessionScoped
 public Address session() {
 return new Address();
}

/* Servlet */
@Inject @Scope(REQUEST)
private Address newAddress;

@Inject @Scope(SESSION)
private Address currentAddress;
于 2012-05-04T18:14:49.233 回答