在Java EE 7中,这里@Named注解的目的和用途是什么?即使没有它,容器也应该能够在运行时发现这个 bean,对吗?
另外,@Singleton 做什么呢?如果开发者不需要在应用程序中创建多个实例,那么这里就没有必要使用单例,对吧?
@Singleton
@Named
public class Counter {
private int a = 1;
private int b = 1;
public void incrementA() {
a++;
}
public void incrementB() {
b++;
}
public int getA() {
return a;
}
public int getB() {
return b;
}
}
我做了两项测试:
1)如果我删除@Singleton,当我单击incrementA()或incrementB()时,较近的增量增加1。该值保持为1。
2)如果去掉@Named注解,会报空指针异常。
我正在学习 Java EE,不太理解这种行为。
编辑(如何使用bean):
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<body>
<ui:composition template="/template.xhtml">
<ui:define name="title">
Helloworld EJB 3.1 Singleton Quickstart
</ui:define>
<ui:define name="body">
<p>
This example demonstrates a singleton session bean that maintains state for 2 variables: <code>a</code> and <code>b</code>.
</p>
<p>
A counter is incremented when you click on the
link to the variable name. If you close and restart your browser, or
if you have multiple browsers, you can see that the counter always
increments the last value. These values are maintained until you
restart the application. To test the singleton bean, click on either
"Increment" button below.
</p>
<table>
<tr>
<h:form>
<td><b>Counter A</b></td><td><h:commandButton value="Increment" action="#{counter.incrementA}" /></td><td>#{counter.a}</td>
</h:form>
</tr>
<tr>
<h:form>
<td><b>Counter B</b></td><td><h:commandButton value="Increment" action="#{counter.incrementB}" /></td><td>#{counter.b}</td>
</h:form>
</tr>
</table>
</ui:define>
</ui:composition>
〜
如果没有 @Named,Bean 将无法在 JSF 的 EL 中使用。
如果没有@Singleton,bean 就是一个普通的 CDI ManagedBean。 每个作用域都有一个托管 Bean,而不是只有一个单独的实例来计数。当您删除@Singleton时,最好添加@SessionScoped或@ApplicationScoped,具体取决于您是要对每个会话进行计数还是对所有会话进行计数(就像@Singleton一样)。
使用 CDI,您的 bean 需要一对范围和限定符。 Singleton 是范围的示例,Named 是限定符的示例。 Qualifier 是查找 bean 时如何派生的。 命名是在与表示层组合时专门使用的,以在视图或类似内容中引用它。 Singleton 允许它作为单个实例公开。 请注意,Singleton 来自 AtInject 规范,并且不被视为 bean 定义,它不是正常范围。 更以 CDI 为中心的方法是使用 ApplicationScoped。 无论哪种方式,都将创建您的类的单个实例。
限定符是可选的,因此如果您想使其在 UI 中可用,则仅需要命名。
单例注释使 EJB 在整个 EE 应用程序中独一无二(看起来在线程和请求之间共享),与其他类型的 EJB(例如会话 Bean)有很大不同,后者在会话中具有生命周期并在该会话中维护内部状态。请注意:在高并发环境中使用单例会影响性能。
@Named 怎么样,我不在 Java EE7 上工作,但我认为它更多地在 JSF 中使用,为所谓的 ManagedBean 提供不同的名称(托管 bean 在新版本的 Java EE 中已弃用)。简单地说,如果您创建一个名为 MyBean 的 bean,您可以在 JSF 页面中将该 bean 称为 myBean,如果您想使用不同的名称,您可以使用:
@Named(“myNewBeanName”)
您可以在 JSF 页面中使用 myNewBeanName。
如果您有不同的 bean 实现相同的接口,并且您想根据部署配置(例如
SELECTED_IMPLEMENTATION
环境变量)选择一个,您可以使用 @Name("MyImplementation")
对每个 bean 进行不同的命名,然后在注射如:
@Inject
@ConfigProperty(name = "SELECTED_IMPLEMENTATION", defaultValue = "MyImplementation")
String selectedImplementation;
@Inject @Any Instance<MyInterface> implementations;
...
implementations.select(new NamedQualifier(selectedImplementation));
(也许有更好的方法来做到这一点,就像您在 Spring 上找到的配置文件一样,但这是我所知道的仅使用 CDI 和 eclipse 微配置文件配置的最佳方法)