【问题标题】:LOAD and CACHE application-scoped data with @Singleton and @Stateless使用 @Singleton 和 @Stateless 加载和缓存应用程序范围的数据
【发布时间】:2014-12-31 05:23:47
【问题描述】:

我正在寻找一个优雅的解决方案来解决在应用程序启动时加载和缓存静态共享数据的老问题(具有无限的生命周期)。

我的旧方法是 Spring Singleton Bean,但我现在正尝试使用 JAVA EE 6(JPA2、EJB3.1、CDI)来实现它。

我有一个@Entity 和一个@Stateless EJB,用于从数据库加载实体。我的想法是添加一个@Singleton EJB 来缓存数据;我还决定将原始 EJB 分开,以防止违反 SRP(因为将来它可能会被其他参与者绕过缓存使用)。

请看一下这个简化的概念证明

实体

@NamedQuery(name="Room.findAll", query="SELECT r FROM Room r")
@Entity
public class Room {

    @Id 
    private Integer id;          // GETTER, SETTER
    private String description;  // GETTER, SETTER
}

加载器

@Stateless
public class Rooms {

    @PersistenceContext
    EntityManager em;

    public List<Room> findAll() {
        return em.createNamedQuery("Room.findAll",Room.class).getResultList();
    }
}

缓存器

@Singleton
public class RoomsCached {

    @EJB
    Rooms rooms;

    private List<Room> cachedRooms; // GETTER

    @PostConstruct
    public void initCache(){
        this.cachedRooms = Collections.unmodifiableList(rooms.findAll());
    }        
}

你能在这个例子中看到大问题、概念错误或其他什么吗?

我主要担心的是

  1. 如果两者都是 @Singleton (mehh),我可以在缓存 bean 上添加 @DependsOn("Rooms"),以确保在使用之前已加载房间,但使用 @Singleton@Stateless 我可以' t... 将始终在 CDI 将其注入 @Singleton 之前加载 @Stateless bean 吗?

  2. @Singleton 调用@Stateless 似乎很奇怪(我见过相反的例子);我应该通过将@Singleton 实例放在@Stateless EJB 中来更改设计吗?

  3. @PostConstruct方法中加载和缓存是否正确?

【问题讨论】:

    标签: java jakarta-ee jpa singleton ejb


    【解决方案1】:

    嗯,我做了一些测试,我也尝试了@Decorator 的方式。这似乎仍然是最好的。

    @Entity bean 和@Stateless bean 是同一个问题,而我将@Singleton bean 更改如下,还添加了经典的定时缓存:

    @Singleton
    public class RoomsCached {
    
        @Inject
        Rooms rooms;
    
        private List<Room> cachedRooms; 
        private long timeout = 86400000L; // reload once a day
        private long lastUpdate;    
    
    
        public List<Room> getCachedRooms() {
            initCache();
            return cachedRooms;
        }
    
        public void initCache() {
            if (cachedRooms == null || expired()) {
                cachedRooms = Collections.unmodifiableList(rooms.findAll());
                lastUpdate  = System.currentTimeMillis();
            }
        }        
    
        private boolean expired() { 
            return System.currentTimeMillis() > lastUpdate + timeout; 
        }
    
    }
    

    不需要@PostConstruct,也不需要@EJB,与底层@inject-ed @Stateless bean 没有同步问题。

    效果很好。

    【讨论】:

      猜你喜欢
      • 2018-09-30
      • 1970-01-01
      • 1970-01-01
      • 2015-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多