如何让已加载的JSON数据在Spring Boot应用全运行周期内对所有服务可用
Spring Boot 全局共享单次加载JSON数据的可行方案
以下几种方案都可以实现JSON数据启动时单次加载、全应用生命周期内可访问的需求:
方案1:Spring 单例Bean存储(常规场景最推荐)
Spring默认创建的Bean都是单例模式,整个应用生命周期内仅存在一个实例,天然适合存储全局共享数据。
- 实现逻辑:
- 定义和JSON结构对应的POJO类
- 自定义一个数据持有类,标注
@Component注解注册为Spring Bean - 在
@PostConstruct修饰的方法或者afterPropertiesSet接口实现中执行JSON文件读取、解析逻辑,将结果存入Bean的私有属性 - 提供公共get方法对外暴露数据
- 代码示例:
// 数据持有Bean @Component public class JsonDataHolder { private MyJsonPojo jsonData; @Autowired private ResourceLoader resourceLoader; @PostConstruct public void loadJson() throws IOException { Resource jsonResource = resourceLoader.getResource("classpath:your_data.json"); ObjectMapper objectMapper = new ObjectMapper(); // 解析JSON为对应的POJO对象 this.jsonData = objectMapper.readValue(jsonResource.getInputStream(), MyJsonPojo.class); } // 对外提供只读方法,避免外部修改全局数据 public MyJsonPojo getJsonData() { return jsonData; } } // 其他服务直接注入使用 @Service public class DemoService { @Autowired private JsonDataHolder jsonDataHolder; public void doBiz() { MyJsonPojo data = jsonDataHolder.getJsonData(); // 执行业务逻辑 } }
- 优势:可以复用Spring生命周期管理,加载失败会直接阻止应用启动,提前暴露问题,所有Spring管理的组件都可以直接注入使用,适配所有类型的Spring Boot应用(包括Web、非Web应用)。
方案2:静态常量存储
适合非Spring管理的类也需要访问JSON数据的场景,不需要依赖Spring容器。
- 实现逻辑:
写一个公共工具类,用静态代码块在类加载时读取解析JSON文件,将结果存入静态常量。 - 代码示例:
public class JsonDataUtils { // 用final修饰避免外部修改引用 public static final MyJsonPojo JSON_DATA; static { try { ObjectMapper objectMapper = new ObjectMapper(); InputStream inputStream = JsonDataUtils.class.getClassLoader() .getResourceAsStream("your_data.json"); JSON_DATA = objectMapper.readValue(inputStream, MyJsonPojo.class); } catch (IOException e) { throw new ExceptionInInitializerError("JSON数据加载失败,应用启动终止"); } } }
- 优势:不需要依赖Spring容器,用法简单,直接
JsonDataUtils.JSON_DATA即可访问;缺点是加载逻辑不受Spring管控,大文件会延长类加载时间,排查启动问题不如Spring Bean方便。
方案3:缓存组件存储
适合后续可能需要热更新JSON数据的场景。
- 实现逻辑:
引入Guava Cache、Caffeine等轻量缓存组件,启动时将解析后的JSON数据存入缓存,过期时间设为永久。如果需要热更新,只需要新增定时任务定期重读JSON文件刷新缓存,或者提供一个管理接口手动触发刷新。 - 优势:支持热更新无需重启应用,可配置访问统计、权限控制等附加能力;缺点是需要额外引入缓存组件依赖,适合有动态更新需求的场景。
方案4:ServletContext 存储(仅适用于Web应用)
如果是Spring Boot Web应用,可以将解析后的JSON数据存入ServletContext全局上下文属性中。
- 优势:无需额外自定义Bean;缺点是仅支持Web应用,获取数据需要依赖ServletContext对象,不如注入Bean方便,非特殊需求不推荐使用。
通用注意事项
- 如果不允许外部修改全局JSON数据,建议将POJO定义为不可变类,或者get方法返回深拷贝副本,避免业务代码误修改全局数据。
- 体积过大的JSON文件不建议用上述方案加载,避免占用过多内存,建议按需读取或者存入本地缓存/数据库。
- 多线程场景下如果需要修改全局数据,要做好并发控制,避免数据不一致。
内容的提问来源于stack exchange,提问作者moonberry
相关产品推荐
相关产品推荐

