尽管有@ApplicationScoped批注,但仍重新初始化@Injected @ManagedBean [英] @Injected @ManagedBean gets reinitialized despite of @ApplicationScoped annotation
问题描述
我正在编写一个简单的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"));
}
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屋!