【问题标题】:Have all @PostConstruct called before getters在 getter 之前调用所有 @PostConstruct
【发布时间】:2023-03-26 06:22:01
【问题描述】:

在 JSF2 中,我需要在 PostConstruct 期间由 ClassB 更新 bean ClassA, 然后显示更新的值。 我的问题是 ClassA 的 getter 在 ClassB 是 PostConstructed 之前被调用。

我的输出:
ValX:
ValY: toto
价值:42

我想要的输出:
ValX:42
ValY: toto
价值:42

在构建视图ID之前没有创建所有bean是否正常?

在调用 getter 之前更新 ClassA 的正确解决方案是什么?

package test;

import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ManagedBean
@ViewScoped
public class ClassA implements Serializable {
    private String valX;

    @PostConstruct
    public void init() {
        System.out.println("init ClassA");
    }

    public String getValX() {
        System.out.println("get ValX");
        return valX;
    }

    public void setValX(String valX) {
        System.out.println("set ValX");
        this.valX = valX;
    }
}
package test;

import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;

@ManagedBean
@ViewScoped
public class ClassB implements Serializable {
    @ManagedProperty(value = "#{classA}")
    private ClassA classA;
    private String valY = "toto";

    @PostConstruct
    public void init() {
        System.out.println("init ClassB");
        classA.setValX("42");
    }

    public ClassA getClassA() {
        return classA;
    }

    public void setClassA(ClassA classA) {
        this.classA = classA;
    }

    public String getValY() {
        return valY;
    }

    public void setValY(String valY) {
        this.valY = valY;
    }
}
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
    </h:head>
    <h:body>
        ValX: #{classA.valX}<br/>
        ValY: #{classB.valY}<br/>
        ValX: #{classA.valX}<br/>
    </h:body>
</html>

【问题讨论】:

  • 这不是一个答案,但你到底为什么想要这个?如果您解释用例,有人可能会为您提供一个没有代码味道的替代方案。关于您的观点:JSF 解析您的 xhtml 并从中生成代表您的 EL 表达式的对象。他们在不同的时间得到评估,并且没有保证的顺序。
  • @mabi:事实上 ClassA 用于显示在其他 bean 初始化期间发生的错误。它是 ui:composition 使用的 xhtml 文件的一部分,因此它不了解其他 bean,但必须由它们更新。
  • classA 会做FacesMessage 未涵盖的任何事情吗?您可以使用omnifaces 的Messages 助手轻松地为前端添加新消息。如果有更多逻辑,我会添加 CDI 事件并让 classA 通过 @Observe 一个方法来监听它们。
  • 我尝试使用消息,但如果 o:messages 标记在 ValY: #{classB.valY} 之前,则消息被视为未处理(并且不会在生产环境中显示)。我没有用 CDI 进行测试,但我认为 bean 的更新将在调用 getter 之后,就好像 ClassB 调用了 classA.setValX()。
  • 你唯一需要做的就是在使用ClassA的属性之前绑定ClassB的任何属性

标签: java jsf jsf-2


【解决方案1】:

你可以从 ClassA 的构造函数中初始化 classB,这样 classB 的 post Constructor 将在 ClassA 之前调用 调用 post 构造函数。

首先创建一个类的对象。即构造函数被调用。

然后是与类固定的后构造函数,因为在创建对象后自动执行。

类中的任何其他函数,无论是getter、setter还是普通函数,都只能使用已经创建的对象调用。

如果你想在类的对象创建之前调用函数,那么你必须将函数声明为静态的。在所有其他方式中,都会调用 getter

【讨论】:

  • 在我的情况下,ClassA 不知道 ClassB,因为可能有多个类在做这件事,但不是在所有视图中。 (我刚刚添加了一条评论来解释我的用例)
猜你喜欢
  • 1970-01-01
  • 2016-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-04
  • 2015-07-19
  • 2021-06-06
相关资源
最近更新 更多