尽管有@ApplicationScoped批注,但仍重新初始化@Injected @ManagedBean [英] @Injected @ManagedBean gets reinitialized despite of @ApplicationScoped annotation

查看:261
本文介绍了尽管有@ApplicationScoped批注,但仍重新初始化@Injected @ManagedBean的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am writing a simple JSF application for converting currencies.

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

There is a Rates class which holds the data, Currencies class for managing requests and Manage class for adding new currencies. My problem is: I want the currencies to be persisted as a property of Rates class hence my use of @ApplicationScoped. However I can see that Rates keeps getting reinitialized with every single request. Here's my code of 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);
}


}

如您所见,我为Rates属性添加了实例初始化程序,设置为currencies ,随每个请求打印出文本"HashSet Initializing".

As you can see I added instance initializer for a property of Rates, set currencies and the text "HashSet initializing" is printed out with every request.

推荐答案

@Inject仅注入CDI管理的bean.

@Inject only injects CDI managed beans.

@ManagedBean声明了JSF托管bean而不是CDI托管bean.

@ManagedBean declares a JSF managed bean not a CDI managed bean.

Rates类改为CDI托管Bean.

Make the Rates class a CDI managed bean instead.

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

@Named
@ApplicationScoped
public class Rates {}

应注意,一般建议是停止使用JSF托管Bean工具,而仅使用CDI托管Bean工具.因此,如果您还使所有其他JSF托管Bean也成为CDI托管Bean,那就更好了.这就是为什么我不建议用等效于JSF的@ManagedProperty代替@Inject的原因(也可以).

Noted should be that the general recommendation is to stop using JSF managed bean facility and exclusively use CDI managed bean facility. So it'd be better if you make all your other JSF managed beans CDI managed beans too. That's exactly why I wouldn't recommend to replace @Inject by its JSF equivalent @ManagedProperty (which would also have worked).

对于托管Bean初始化,您不应在类/实例级别执行此操作,而应在带有@PostConstruct注释的方法中执行任务.

As to managed bean initialization, you should not do it at class/instance level, but perform the task in a @PostConstruct annotated method.

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中尤其重要,因为它创建并注入

This is particularly important in CDI because it creates and injects proxies based on the class, so the class may be instantiated at times you don't expect.

这篇关于尽管有@ApplicationScoped批注,但仍重新初始化@Injected @ManagedBean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆