spring boot启动初始化数据的多种方式
场景
在日常的项目中,经常会有一些需求,是在项目启动过程中,启动后,或者满足特定条件,初始化一些数据,或者从数据库读取一些配置初始化,又或从数据库读取一些热点数据到redis进行初始化缓存。
本文提供一些常见的实现,以及在项目启动的不同阶段加载的实现方式。
项目启动中
方式一:实现说明:本实例是初始化一个Word的词库,使用的static静态代码块,实现原理为@Component + static代码块, spring boot项目在启动过程中,会扫描@Component 并初始化相应的类,类的初始化过程会运行静态代码块。
1 2 3 4 5 6 | @Component public class WordInitConfig { static { WordSegmenter.segWithStopWords( "初始化分词" ); } } |
方式二:实现说明:本实例实现项目启动过程中加载配置信息,并缓存到redis, 这里使用的是 @PostConstruct(),该注解会在类调用构造函数之前调用,但是初始化当前配置类的时候,MallSettingMapper.class, RedisService.class, SettingRefreshService.class这些类可能还未加载或实例化,所以这里需要配合@ConditionalOnBean注解实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @Component @ConditionalOnBean ({MallSettingMapper. class , RedisService. class , SettingRefreshService. class }) public class SettingInitConfig { @Autowired private SettingRefreshService settingRefreshService; @PostConstruct () private void refresh(){ settingRefreshService.refreshRedis(); } } |
项目启动后
实现说明:这里还是以上面加载配置到redis缓存为例子,这里我们需要准确知道项目启动的时间,所以我们要借助spring内置的监听器,监听事件ApplicationReadyEvent,这里还有其他事件比如ApplicationFailedEvent、ApplicationStartingEvent等,对应application context加载的各阶段,如果需要自定义事件,也可以参考《基于Redis队列实现《二》——点对点模式》。
1 2 3 4 5 6 7 8 9 10 11 12 13 | @Component public class SettingInitConfig implements ApplicationListener<ApplicationReadyEvent> { @Autowired private SettingRefreshService settingRefreshService; @Override public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { settingRefreshService.refreshRedis(); } } |
特定条件或者配置
实现说明:这里实现的场景比较复杂一些,本例子实现的类似starter的机制,在集成第三方插件时,比较常见。这里做的是一个ES全文搜索集成方案,由于整个方案改动比较大,持续时间比较长,而中途又需要发布生产,这里希望达到目标是即使生产读取不到相关ES配置,或者通过配置动态开关。这里主要基于 @ConditionalOnProperty实现
1. 增加配置 elasticsearch.active 开关
1 2 3 4 5 | #开启elasticsearch elasticsearch: hostname: 192.168 . 9.79 port: 9200 active: false |
2. 增加配置类 EsConfig
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | @Configuration @ConditionalOnProperty (prefix= "elasticsearch" ,name = "active" , havingValue = "true" ) public class EsRestClientConfig { @Value ( "${elasticsearch.hostname}" ) private String hostname; @Value ( "${elasticsearch.port}" ) private int port; private String schema = "http" ; private int connectTimeOut = 1000 ; private int socketTimeOut = 30000 ; private int connectionRequestTimeOut = 500 ; private int maxConnectNum = 100 ; private int maxConnectPerRoute = 100 ; private HttpHost httpHost; private boolean uniqueConnectTimeConfig = true ; private boolean uniqueConnectNumConfig = true ; private RestClientBuilder builder; private RestClient client; @Lazy @Bean (autowire = Autowire.BY_NAME, name = "restClient" ) public RestClient client() { httpHost = new HttpHost(hostname, port, schema); builder = RestClient.builder(httpHost); if (uniqueConnectTimeConfig) { setConnectTimeOutConfig(); } if (uniqueConnectNumConfig) { setMutiConnectConfig(); } return builder.build(); } /** * 异步httpclient的连接延时配置 */ public void setConnectTimeOutConfig() { builder.setRequestConfigCallback( new RestClientBuilder.RequestConfigCallback() { @Override public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) { requestConfigBuilder.setConnectTimeout(connectTimeOut); requestConfigBuilder.setSocketTimeout(socketTimeOut); requestConfigBuilder.setConnectionRequestTimeout(connectionRequestTimeOut); return requestConfigBuilder; } }); } /** * 异步httpclient的连接数配置 */ public void setMutiConnectConfig() { builder.setHttpClientConfigCallback( new RestClientBuilder.HttpClientConfigCallback() { @Override public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) { httpClientBuilder.setMaxConnTotal(maxConnectNum); httpClientBuilder.setMaxConnPerRoute(maxConnectPerRoute); return httpClientBuilder; } }); } /** * 关闭连接 */ public void close() { if (client != null ) { try { client.close(); } catch (IOException e) { e.printStackTrace(); } } } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
2014-07-15 javascript深入理解js闭包