На каком этапе создается управляемый компонент и какой конструктор используется

StackOverflow https://stackoverflow.com//questions/20035681

  •  21-12-2019
  •  | 
  •  

Вопрос

Рассмотрим пример веб-приложения на основе JSF. hello1 из официального руководства с дополнительным конструктором в управляемом компоненте.Следующее index.xhtml фейслет

<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>

и модифицированный управляемый компонент 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 щелкните.Следовательно, как написано в руководстве, у нас есть следующая подфаза фазы выполнения:

  1. Представление приложения создается или восстанавливается.
  2. Значения параметров запроса применяются.
  3. Преобразования и проверки выполняются для значений компонентов.
  4. Управляемые bean-компоненты обновляются значениями компонентов.
  5. Вызывается логика приложения.

На каком этапе будет создан экземпляр управляемого компонента?

Какой конструктор будет вызван для создания этого экземпляра и почему?Я не понимаю, как это можно наблюдать со стороны index.xhtml код.

Это было полезно?

Решение

На каком этапе будет создан экземпляр управляемого компонента?

Никого конкретно.Он создается впервые, когда произвольному EL-выражению необходимо впервые ссылаться на управляемый компонент, в то время как экземпляр компонента отсутствует в его области действия.Это не зависит от какого-либо конкретного события с лицами.Это может быть на этапе восстановления представления (первый этап), но это также может быть полезно на этапе ответа на рендеринг (последний этап) или на любом другом промежуточном этапе.

Все зависит от того, как и где на бин ссылаются в контексте EL через #{bean.xxx} в представлении (или программно в модели).Обычно вам не следует беспокоиться об этом.JSF (в частности, EL), по крайней мере, не будет создавать его раньше, чем это необходимо, чтобы правильно построить, обработать или отобразить представление.


Какой конструктор будет вызван для создания этого экземпляра и почему?

Конструктор по умолчанию, конечно.Потому что так гласит спецификация Javabeans.Все остальные конструкторы никогда не используются объектом управляемых компонентов JSF/CDI.

Даже в этом случае вам не следует беспокоиться о конструкторах.Вам лучше выполнить инициализацию в @PostConstruct аннотированный метод вместо конструктора.А именно, когда bean-компонент управляется структурой управления bean-компонентами, которая использует прокси-серверы, такие как CDI, конструктор по умолчанию может вызываться чаще, чем хотелось бы.


Я не понимаю, как это можно увидеть из кода index.xhtml.

Просто поставьте точку останова в конструкторе, @PostConstruct, или любой другой соответствующий метод получения/установки и запустите проект в режиме отладки.Как только точка останова достигнет точки останова, проверьте стек вызовов.Задействованные классы и методы обычно имеют довольно самодокументируемые имена.Вот пример того, как может выглядеть стек вызовов при использовании @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 сообщает, что это произошло во время записи результата EL в текст шаблона, например <p>#{bean.something}</p>.Остальное — это то, как реализация CDI Weld находит и создает экземпляр прокси-сервера и как он, в свою очередь, создает экземпляр фактической ссылки на компонент.

Если бы это произошло на другом этапе, вы бы вместо RenderResponsePhase.execute видел, например UpdateModelValuesPhase.execute и так далее.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top