2

我有两个托管 bean,它们都有一个@ApplicationScope注释:

存储.java:

@ManagedBean(eager = true)
@ApplicationScoped
public class Storage {

    private static final Logger LOGGER = LoggerFactory.getLogger(Storage.class);

    private List<Sheet> sheets = new ArrayList<Sheet>();

    public List<Sheet> getSheets() {
        return sheets;
    }

    public Sheet load(String id) {
        // ...
    }

    public void storeSheet(Sheet sheet) {
        sheets.add(sheet);
        LOGGER.trace(""+this.hashCode()+" Stored sheet: "+sheet);
    }

    public void delete(Sheet s) {
        sheets.remove(s);
        LOGGER.trace(""+this.hashCode()+" Removed sheet: "+s);
    }

}

StorageInitializer.java:

@ManagedBean(eager = true)
@ApplicationScoped
public class StorageInitializer {

    @ManagedProperty(value = "#{storage}")
    private Storage storage;

    @PostConstruct
    public void init() {
        int nofSheets = 10;
        int min = 20;
        int max = 200;
        for (int i=0; i<nofSheets; i++) {
            storage.storeSheet(new Sheet(
                    "Sheet "+i,
                    ThreadLocalRandom.current().nextInt(min, max),
                    ThreadLocalRandom.current().nextInt(min, max)));
        }
    }

    public void setStorage(Storage storage) {
        this.storage = storage;
    }

}

应用程序启动时,StorageInitializer应将 10 个实例写入存储。其他 bean@RequestScoped可以访问存储并使工作表可见。他们都有一个

    @ManagedProperty(value = "#{storage}")
    private Storage storage;

访问Storagebean。

通过记录哈希,我可以看到有时会得到两个Storagebean 实例。第一个由 初始化StorageInitializer。第二个被@RequestScopedbean 使用并且是空的。

为了解决这个问题,这看起来像是一个竞争条件或计时问题。StorageInitializer.ini()如果我在一切工作中设置一个断点就可以了。

有任何想法吗?

4

1 回答 1

0

我对两个带有“eager = true”的@ApplicationScoped bean 有同样的问题。复制的 bean 位于另一个 @ApplicationScoped bean 的 @ManagedProperty 中。我通过在拥有@ManagedProperty 的bean 上将eager 值更改为false 解决了这个问题。在我的情况下,热切的价值并不是绝对必要的。

于 2017-09-17T18:27:09.697 回答