在哪个阶段构造托管bean,使用哪个构造函数 [英] At which phase is managed bean constructed and which constructor is used
问题描述
考虑官方教程中基于JSF的Web应用程序hello1
的示例,并在托管Bean中添加构造函数.跟随index.xhtml
小面
Consider example of JSF based web-app hello1
from official tutorial with addition constructor in managed bean. The follow index.xhtml
facelet
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
<title>Facelets Hello Greeting</title>
</h:head>
<h:body>
<h:form>
<h:graphicImage url="#{resource['images:duke.waving.gif']}"
alt="Duke waving his hand"/>
<h2>Hello hui, my name is Duke. What's yours?</h2>
<h:inputText id="username"
title="My name is: "
value="#{hello.name}"
required="true"
requiredMessage="Error: A name is required."
maxlength="25" />
<p></p>
<h:commandButton id="submit" value="Submit" action="response">
</h:commandButton>
<h:commandButton id="reset" value="Reset" type="reset">
</h:commandButton>
</h:form>
<div class="messagecolor">
<h:messages showSummary="true"
showDetail="false"
errorStyle="color: #d20005"
infoStyle="color: blue"/>
</div>
</h:body>
</html>
和修改后的托管bean Hello.java
and modidfied managed bean Hello.java
package javaeetutorial.hello1;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
@Named
@RequestScoped
public class Hello {
private String name;
public Hello() {
}
public Hello(String name){
this.name=name;
}
public String getName() {
return name;
}
public void setName(String user_name) {
this.name = user_name;
}
}
有两个公共构造函数.让我们将此应用程序部署到服务器上并发送初始请求,在inputText
中键入名称,然后单击submit
.单击submit
后,存在回发请求.因此,正如教程所写,我们具有执行阶段的以下子阶段:
There are two public constructors. Let we deploy this app on server and sent initial request, type the name in inputText
and click submit
. There is postback request after submit
click. Hence, as written in tutroial, we have the following subphase of execute phase:
- 已构建或还原了应用程序视图.
- 应用请求参数值.
- 对组件值进行转换和验证.
- 托管的Bean将使用组件值进行更新.
- 应用程序逻辑被调用.
将在哪个阶段创建托管bean实例?
At what phase instance of managed bean will be created?
此实例创建将调用什么构造函数,为什么?我不明白如何从index.xhtml
代码中观察到它.
What constructor will be invoked for this instance creation and why? I dont understand how it can be observe from the index.xhtml
code.
推荐答案
将在哪个阶段创建托管bean实例?
没有人专门.当bean实例不在其范围内时,当任意EL表达式需要首次引用托管bean时,将首次构造它.这不依赖于任何特定的面孔事件.这可以在还原视图阶段(第一个阶段)中进行,但是在渲染响应阶段(最后一个阶段)中或在此之间的任何其他阶段中也可以进行.
No one specifically. It's constructed for the first time when an arbitrary EL expression needs to reference the managed bean for the first time while the bean instance isn't present in its scope. This is not dependent on any particular faces event. This can be during restore view phase (the first phase), but this can also be as good during render response phase (the last phase), or any other phase in between.
这全部取决于在视图(或在模型中以编程方式)中通过#{bean.xxx}
在EL上下文中引用bean的方式和位置.您通常不必为此担心.为了正确地构建,处理或渲染视图,JSF(特别是EL)至少不会比必要的时间早构建它.
This all depends on how and where the bean is referenced in EL context via #{bean.xxx}
in the view (or programmatically in the model). You should generally not worry about this. JSF (specifically EL) will at least not construct it sooner than necessary in order to properly build or process or render the view.
此实例创建将调用什么构造函数,为什么?
当然是默认构造函数.因为Javabeans规范是这样说的. JSF/CDI管理的bean设施永远不会使用所有其他构造函数.
The default constructor, of course. Because the Javabeans specification says so. All other constructors are never used by JSF/CDI managed bean facility.
即使那样,您也不必担心构造函数.您最好在@PostConstruct
带注释的方法中而不是在构造函数中执行初始化.即,当由使用代理(例如CDI)的Bean管理框架管理Bean时,默认构造函数的调用频率可能会比期望的高.
Even then, you should not be worrying about constructors. You'd better perform initialization in a @PostConstruct
annotated method instead of in a constructor. Namely, when the bean is managed by a bean management framework which uses proxies, such as CDI, the default constructor may be called more often than desired.
我不明白如何从index.xhtml代码中观察到它.
只需在构造函数@PostConstruct
或任何相关的getter/setter方法中放置一个断点,然后以调试模式运行项目.一旦断点命中,请检查调用堆栈.所涉及的类和方法通常具有相当可自我记录的名称.这是一个使用@Named
Just put a breakpoint in constructor, @PostConstruct
, or whatever relevant getter/setter method and run the project in debug mode. Once the breakpoint hits, examine the call stack. The involved classes and methods have generally rather self-documenting names. Here's an example how the call stack can look like when you're using @Named
:
Daemon Thread [http-bio-8088-exec-6] (Suspended (entry into method <init> in TestBean))
owns: LocalCache$StrongEntry (id=503)
owns: SocketWrapper (id=504)
TestBean$Proxy$_$$_WeldClientProxy.<init>() line: not available [local variables unavailable]
NativeConstructorAccessorImpl.newInstance0(Constructor, Object[]) line: not available [native method]
NativeConstructorAccessorImpl.newInstance(Object[]) line: 57
DelegatingConstructorAccessorImpl.newInstance(Object[]) line: 45
Constructor.newInstance(Object...) line: 526
Class.newInstance() line: 374
NewInstanceAction.run() line: 33
AccessController.doPrivileged(PrivilegedExceptionAction<T>) line: not available [native method]
ClientProxyFactory(ProxyFactory).create(BeanInstance) line: 271
ClientProxyFactory.create(BeanInstance) line: 111
ClientProxyProvider.createClientProxy(Bean<T>, Set<Type>) line: 181
ClientProxyProvider.createClientProxy(Bean<T>) line: 171
ClientProxyProvider.access$100(ClientProxyProvider, Bean) line: 45
ClientProxyProvider$CreateClientProxy.load(Bean<Object>) line: 56
ClientProxyProvider$CreateClientProxy.load(Object) line: 52
LocalCache$LoadingValueReference.loadFuture(K, CacheLoader<? super K,V>) line: 3589
LocalCache$Segment.loadSync(K, int, LoadingValueReference<K,V>, CacheLoader<? super K,V>) line: 2374
LocalCache$Segment.lockedGetOrLoad(K, int, CacheLoader<? super K,V>) line: 2337
LocalCache$Segment.get(K, int, CacheLoader<? super K,V>) line: 2252
LocalCache.get(K, CacheLoader<? super K,V>) line: 3990
LocalCache.getOrLoad(K) line: 3994
LocalCache$LocalLoadingCache.get(K) line: 4878
LoadingCacheUtils.getCacheValue(LoadingCache<K,V>, K) line: 52
LoadingCacheUtils.getCastCacheValue(LoadingCache<K,V>, Object) line: 80
ClientProxyProvider.getClientProxy(Bean<T>) line: 187
WeldELResolver(AbstractWeldELResolver).lookup(BeanManagerImpl, ELContext, String) line: 110
WeldELResolver(AbstractWeldELResolver).getValue(ELContext, Object, Object) line: 91
WeldApplication$LazyBeanManagerIntegrationELResolver(ForwardingELResolver).getValue(ELContext, Object, Object) line: 49
CompositeELResolver.getValue(ELContext, Object, Object) line: 67
DemuxCompositeELResolver._getValue(int, ELResolver[], ELContext, Object, Object) line: 176
DemuxCompositeELResolver.getValue(ELContext, Object, Object) line: 203
AstIdentifier.getValue(EvaluationContext) line: 72
ValueExpressionImpl.getValue(ELContext) line: 185
WeldValueExpression.getValue(ELContext) line: 50
ELText$ELTextVariable.writeText(ResponseWriter, ELContext) line: 227
ELText$ELTextComposite.writeText(ResponseWriter, ELContext) line: 150
TextInstruction.write(FacesContext) line: 85
UIInstructions.encodeBegin(FacesContext) line: 82
UIInstructions(UILeaf).encodeAll(FacesContext) line: 207
HtmlBody(UIComponent).encodeAll(FacesContext) line: 1899
UIViewRoot(UIComponent).encodeAll(FacesContext) line: 1899
FaceletViewHandlingStrategy.renderView(FacesContext, UIViewRoot) line: 451
MultiViewHandler.renderView(FacesContext, UIViewRoot) line: 131
ConversationAwareViewHandler(ViewHandlerWrapper).renderView(FacesContext, UIViewRoot) line: 337
RenderResponsePhase.execute(FacesContext) line: 120
RenderResponsePhase(Phase).doPhase(FacesContext, Lifecycle, ListIterator<PhaseListener>) line: 101
LifecycleImpl.render(FacesContext) line: 219
FacesServlet.service(ServletRequest, ServletResponse) line: 647
...
从底部开始(我已经删除了FacesServlet.service
之后的所有行,因为它们通常是不相关的),并从下往上读取. RenderResponsePhase.execute
告诉它在渲染响应阶段执行. TextInstruction.write
表示它是在像<p>#{bean.something}</p>
这样的模板文本中写入EL结果时发生的.剩下的就是CDI实现Weld如何查找和实例化代理,以及如何实例化实际的bean引用.
Start at the bottom (I've stripped all lines after FacesServlet.service
as those are generally irrelevant) and read from bottom to top. The RenderResponsePhase.execute
tells that it's executed during render response phase. The TextInstruction.write
tells that it occurred during writing the outcome of EL in template text like so <p>#{bean.something}</p>
. The remainder is just how the CDI implementation Weld is finding and instantiating the proxy and how it is in turn instantiating the actual bean reference.
如果它发生在另一个阶段,那么您会看到例如UpdateModelValuesPhase.execute
而不是RenderResponsePhase.execute
等等.
If it happened during a different phase, you'd instead of RenderResponsePhase.execute
have seen for example UpdateModelValuesPhase.execute
and so on.
这篇关于在哪个阶段构造托管bean,使用哪个构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!