【问题标题】:Reference Data Pattern参考数据模式
【发布时间】:2025-12-25 18:40:16
【问题描述】:

与此线程类似,但不完全是:How To Cache Information In A Threadsafe Manner

处理“参考数据”的通常模式是什么——应用程序经常读取的数据,通常在数据库或属性文件中外部化,但很少更新(几天、几周、几个月)?当数据更新时,它会在外部更新。

这通常是一个单例,我可以用 DAO 注入,从而能够管理它自己的内容吗?我喜欢在该服务上公开一个 refresh() 方法来强制刷新(即,通过 MBean - 所以我不必反弹应用程序)的想法。

从另一个 SO 线程来看,听起来人们可能只是在必要时实例化 DAO 并在该级别透明地缓存。

我有点喜欢将单例服务注入从数据库加载数据的真实 DAO 或返回硬编码响应的模拟/测试替身的想法。但是,如果我要通过 java 枚举将服务实现为单例,这会使通过 Spring 将其连接起来有点问题。

那么,其他人通常如何处理参考数据?随意查询但在后台进行缓存?还是单独的内存服务?

【问题讨论】:

    标签: java spring design-patterns static-data


    【解决方案1】:

    我通常使用 Spring 将 DAO 实现注入到我的服务层中,并且正如您提到的,除了基于 SQL 的实现之外,我通常还有一个测试实现(XMLDaoFlatFileDao)。对于小型数据集,我通常会编写自己的缓存并将所有从基础表加载的数据存储在内存中。

    话虽如此,我的优势在于使用相当小的数据集。如果我正在处理更大的数据集,我可能会考虑现成的缓存解决方案,可能分布在多个 JVM 上(例如 Terracotta)。

    正如我在上一篇文章中提到的,我还公开了一个 refresh() 方法。在不需要及时传播数据更新的情况下,我只需通过 MBean 手动调用它。在我希望自动执行此操作的情况下,我使用 Tibrv 来监听来自数据库的更新并刷新缓存的数据(使用 MS-SQL 触发器生成 Tibrv 消息)。

    我不太明白您提到使用 Java 枚举来实现服务 - 这将如何工作?

    【讨论】:

    • 我可能用那部分弄混了水。主要是,我想知道将依赖项注入单例。现在我想起来了,这可能是一个单独的问题。无论如何,根据 Bloch 的说法,当前在 java 中实现单例的最佳实践是使用具有单个成员(实例)的 Enum:即 public enum Elvis { INSTANCE; }
    • 如果你要走这条路,难道你还不能通过 Spring 使用 MethodInvokingFactoryBean 调用枚举类的相关设置器来注入任何依赖项吗?
    • 是的,这就是我可能最终会做的事情 - 但它不够优雅,我想我会回到第一原则,看看我是否做错了。
    • Terracotta 是一种集群解决方案,而不是缓存解决方案