尽管有@ApplicationScoped注释,但@Injected @ManagedBean仍会重新初始化

时间:2016-04-10 14:38:21

标签: jsf java-ee cdi managed-bean application-scope

我正在编写一个简单的JSF应用程序来转换货币。

有一个Rates类,用于保存数据,Currencies类用于管理请求,Manage类用于添加新货币。我的问题是:我希望将货币作为Rates类的属性保留,因此我使用@ApplicationScoped。但是我可以看到Rates 不断重新初始化每个请求。这是我的Rates代码:

@ManagedBean
@ApplicationScoped
public class Rates {

private Map<String, Double> rates = new HashMap<String, Double>();
private Set<String> currencies = new HashSet<String>(){
    {
        System.out.println("HashSet initializing");
    }
};
private List<String> list = new ArrayList<String>(Arrays.asList("Filip", "Kasia"));

public List<String> getList() {
    return list;
}

public void setList(List<String> list) {
    this.list = list;
}

public Rates() {
    rates.put("PLN_EUR", 0.25);
    rates.put("EUR_PLN", 4.0);
    currencies.add("PLN");
    currencies.add("EUR");
}

public Map<String, Double> getRates() {
    return rates;
}

public void setRates(Map<String, Double> rates) {
    this.rates = rates;
}

public Set<String> getCurrencies() {
    return currencies;
}

public void setCurrencies(Set<String> currencies) {
    this.currencies = currencies;
}

public void addRate(String firstCurrency, String secondCurrency){
    if(rates.containsKey(firstCurrency + "_" + secondCurrency))
        return;
    double rate = (double)(Math.random()*10);
    rates.put(firstCurrency + "_" + secondCurrency, rate);
    rates.put(secondCurrency + "_" + firstCurrency, 1 / rate);
    currencies.add(firstCurrency);
    currencies.add(secondCurrency);
    System.out.println(currencies);

}

public double getRate(String currencies){
    return rates.get(currencies);
}
}

以及它是如何注入的:

@ManagedBean
public class Manage {
private String firstCurrency;
private String secondCurrency;
private @Inject Rates rates;

public String getSecondCurrency() {
    return secondCurrency;
}

public void setSecondCurrency(String secondCurrency) {
    this.secondCurrency = secondCurrency;
}

public String getFirstCurrency() {
    return firstCurrency;
}

public void setFirstCurrency(String firstCurrency) {
    this.firstCurrency = firstCurrency;
}

public void addCurrencies(){
    rates.addRate(firstCurrency, secondCurrency);
}


}

如您所见,我为Rate属性添加了实例初始值设定项,设置currencies 和文本&#34; HashSet初始化&#34;每次请求都会打印出来。

1 个答案:

答案 0 :(得分:3)

@Inject仅注入CDI托管bean。

@ManagedBean声明一个JSF托管bean而不是CDI托管bean。

Rates类改为CDI托管bean。

import javax.inject.Named;
import javax.enterprise.context.ApplicationScoped;

@Named
@ApplicationScoped
public class Rates {}

注意应该是一般的建议是停止使用JSF托管bean工具并专门使用CDI托管bean工具。因此,如果您将所有其他JSF托管bean CDI托管bean也做得更好,那就更好了。这就是为什么我不建议用它的JSF等效@Inject替换@ManagedProperty(这也有效)。

对于托管bean初始化,您不应该在类/实例级别执行此操作,而是使用@PostConstruct带注释的方法执行该任务。

private Map<String, Double> rates;
private Set<String> currencies;
private List<String> list;

@PostConstruct
public void init() {
    rates = new HashMap<>();
    currencies = new HashSet<>();
    list = new ArrayList<>(Arrays.asList("Filip", "Kasia"));
}

这在CDI中尤其重要,因为它根据类创建并注入link,因此可以在您不期望的时候实例化类。

另见: