如何使用不同的范围注入相同类的对象?

在简单性和正确性方面,注入具有不同范围的同一类对象的最佳方法是什么?

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

  • 简单性:为每个范围制作Qualifier和制作方法太多了; 在beans.xml创建一个接口,两个类以及添加和替换也是太多了; 使用Address#isCurrent()方法没有意义。
  • 正确性:JSR299,3.11说: 不建议使用@Named作为注入点限定符。 还是不知道为什么。
    虽然在注入点使用@Named可以与@ApplicationScoped@RequestScoped一起使用,但不能与@SessionScoped 。 请参阅下面的命名代码段

在spring,这很容易:
spring片段

       

名为代码段

 /* 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; 

包含此建议的原因与使用枚举相对于常量的任意字符串的原因相同,这是因为它不是类型安全的。 您可以轻松地输入类的名称,它将编译正常并在运行时失败。 包含该建议是因为在大多数情况下,当您具有在编译时强制这些约束的能力时,@ named会使您的应用程序不必要地变得脆弱。

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

处理这种情况的首选方法是使用带有枚举值的@Qualifiers。 查看标题为“字符串限定符是遗留的”和“正确的方法”的部分,以了解处理此问题的步骤。

感谢@ 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;