使用@Singleton 和@Stateless 加载和缓存应用程序范围的数据 [英] LOAD and CACHE application-scoped data with @Singleton and @Stateless

查看:22
本文介绍了使用@Singleton 和@Stateless 加载和缓存应用程序范围的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm looking for an elegant solutions to the old problem of loading and caching static, shared data at application startup (with an infinite lifetime).

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

My old way was a Spring Singleton Bean, but I'm trying now to achieve it with JAVA EE 6 (JPA2, EJB3.1, CDI).

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

I have an @Entity, and an @Stateless EJB lo load the entity from database. My thought was to add a @Singleton EJB to cache the data; I also decided to keep the original EJB separated, to prevent violating SRP (and because in the future it might be used bypassing the cache, by other actors).

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

Please take a look at this simplified Proof Of Concept:

实体

@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());
    }        
}

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

Can you see big problems, conceptual errors or something in this example ?

我主要关心的是

  1. 如果两者都是 @Singleton (mehh),我可以在缓存 bean 上添加 @DependsOn("Rooms"),以确保 Rooms 已经在使用之前加载,但是使用 @Singleton@Stateless 我不能......在 CDI 注入之前总是加载 @Stateless bean它变成 @Singleton ?

  1. If both were @Singleton (mehh), I could have added @DependsOn("Rooms") on the cacher bean, to ensure Rooms is already loaded before being used, but with @Singleton and @Stateless I can't... will @Stateless bean always be loaded before CDI injects it into @Singleton ?

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

@Singleton calling @Stateless seems weird (I've seen examples of the opposite); should I change design by putting the @Singleton instance inside the @Stateless EJB ?

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

Is it right to load and cache in the @PostConstruct method ?

推荐答案

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

Well, I've made some tests, and I've also tried the @Decorator way. This still seems to be the best one.

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

@Entity bean and @Stateless bean are the same of the question, while I've changed the @Singleton bean as follows, also adding the classic timed cache:

@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 没有同步问题.

No need to @PostConstruct, nor to @EJB, no sync issues with the underlying, @inject-ed @Stateless bean.

效果很好.

这篇关于使用@Singleton 和@Stateless 加载和缓存应用程序范围的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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