爲了開發目的,我在單例bean中實現了一個虛擬數據存儲庫。單例bean的構造函數創建虛擬數據,並且有方法來檢索,插入,更新和刪除虛擬數據。Singleton EJB應該表現出與EJB容器相同的外部容器,但不是
當我單元測試它時,檢查插入和更新的對象是否可以在插入和更新的狀態(即屬性相等)中檢索,單元測試通過。在這個測試中,我只是將singleton bean實例化爲常規對象,即通過它的構造函數。當我實際使用單身bean時,通過將其注入到一個@RequestScoped
JSF輔助bean(將bean創建留給EJB容器)中,在更新數據項並隨後通過它的ID檢索它之後,更新似乎丟失了,舊字段值被使用。所以這個bean在進出容器中的行爲不一樣。然而,在構造函數中有一個System.out.println
只能執行一次,所以在這個意義上它似乎只實例化一次。
的單豆的結構是這樣的:
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
@Singleton
@LocalBean
public class DummyDataRepository {
public DummyDataRepository() {
// Initial dummy data created here.
}
public final synchronized Foo findFooById(int id) {
// Retreive a Foo by ID.
// ...
}
public final synchronized void addFoo(Foo foo) {
// Add the Foo.
// ...
}
public final synchronized void updateFoo(Foo foo) {
// Find the existing Foo by foo.id and replace it with foo.
// ...
}
public final synchronized void deleteFoo(int id) {
// Find the existing Foo by id and delete it.
// ...
}
}
似乎沒有任何理由的bean應當產生進出EJB容器的不同的結果。它不使用任何外部資源。同步是由bean管理的(所以在這方面應該是一樣的)。該bean被聲明爲單例。但是在容器中它似乎充當無狀態會話bean。
我正在使用GlassFish 3.1.2.2。
更新: 我改變了豆從@javax.ejb.Singleton
到@javax.enterprise.context.ApplicationScoped
(凡通過@javax.inject.Inject
,而不是@javax.ejb.EJB
需要注入的話),現在按預期工作。但兩者之間應該沒有區別。它認爲,雖然單例EJB只被實例化了一次,但它以某種方式恢復了它在方法調用之間的狀態。
那麼它的會話bean和參與交易模型,所以必須有一個代理。否則,它將是一個簡單的POJO。 – atamanroman
謝謝@atamanroman。人們會希望GlassFish拒絕部署它,就像'@ ApplicationScoped' bean的情況一樣。 –