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

  

 

posted @   蜗牛之履  阅读(1504)  评论(0编辑  收藏  举报
编辑推荐:
· 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闭包
点击右上角即可分享
微信分享提示