在启动 spring 引导服务之前等待依赖项加载
Wait for dependencies to load before starting spring boot service
我有一个 spring 引导应用程序,它有两个 bean - AppState
和 Users
。
AppState
取决于 bean Users
,因为它会自动装配它。两个bean的骨架代码如下
@Component
@EnableScheduling
public class Users {
@Getter // lombok
private List<String> users;
@PostConstruct
public void init(){
users = new ArrayList<>();
load(); // I removed this later
}
@Scheduled(fixedRate = 3600000)
public void load(){
// load list of users from (say) a file and populate ArrayList 'users'
// this method takes at least 3 mins to finish
}
}
AppState
是
@Component
public class AppState {
@Atowired
private Users users;
public List<String> getUsers(){
return users.getUsers();
}
}
我注意到 Users
中的方法 load()
被触发了两次 - 可能是在 init()
期间触发一次,另一次是在 Users
之后调度 load()
=] bean 已经创建。所以我在 init()
中删除了对 load()
的调用。这解决了冗余调用问题。
但是,现在我发现我的服务在 AppState
和 Users
bean 创建后立即启动,即使 Users
尚未填充数据。这对我来说是有风险的,因为在此期间,如果被查询,将有 return 0 个用户。
我需要以下任何方面的帮助。
我是否应该将 load()
移回 init()
以确保当 bean 使用 PostConstruct
完成时,它确实具有所有用户信息?如果我走这条路,我怎样才能防止 load()
的冗余 运行?
如果 load()
应该远离 init()
,我如何确保 AppState
没有准备好,除非 Users
已经执行 [=19] =]?我尝试在 AppState
中使用以下代码,但它只是挂起。
代码如下
@PostConstruct
public void appStateInit(){
while(users.getUsers().size()==0){
try{
Thread.sleep(10000); // sleep 10s
}catch(whatever){
}
}
}
我建议在 class 中设置一个 flag
,并在 init() 完成后将其设置为 true
。如果还没有设置flag
,可以跳过load()
的执行,例如:
private AtomicBoolean shouldExecute;
@PostConstruct
public void init(){
users = new ArrayList<>();
shouldExecute = true;
}
@Scheduled(fixedRate = 3600000)
public void load(){
if(shouldExecute){
// load list of users from (say) a file and populate ArrayList 'users'
// this method takes at least 3 mins to finish
}
}
此外,另一种解决方案是在 @Scheduled
注释(文档 here)中配置 initialDelay
,这将延迟第一次执行配置的毫秒数,例如:
@Scheduled(fixedRate = 3600000, initialDelay=180000)
public void load(){
// load list of users from (say) a file and populate ArrayList 'users'
// this method takes at least 3 mins to finish
}
我有一个 spring 引导应用程序,它有两个 bean - AppState
和 Users
。
AppState
取决于 bean Users
,因为它会自动装配它。两个bean的骨架代码如下
@Component
@EnableScheduling
public class Users {
@Getter // lombok
private List<String> users;
@PostConstruct
public void init(){
users = new ArrayList<>();
load(); // I removed this later
}
@Scheduled(fixedRate = 3600000)
public void load(){
// load list of users from (say) a file and populate ArrayList 'users'
// this method takes at least 3 mins to finish
}
}
AppState
是
@Component
public class AppState {
@Atowired
private Users users;
public List<String> getUsers(){
return users.getUsers();
}
}
我注意到 Users
中的方法 load()
被触发了两次 - 可能是在 init()
期间触发一次,另一次是在 Users
之后调度 load()
=] bean 已经创建。所以我在 init()
中删除了对 load()
的调用。这解决了冗余调用问题。
但是,现在我发现我的服务在 AppState
和 Users
bean 创建后立即启动,即使 Users
尚未填充数据。这对我来说是有风险的,因为在此期间,如果被查询,将有 return 0 个用户。
我需要以下任何方面的帮助。
我是否应该将
load()
移回init()
以确保当 bean 使用PostConstruct
完成时,它确实具有所有用户信息?如果我走这条路,我怎样才能防止load()
的冗余 运行?如果
load()
应该远离init()
,我如何确保AppState
没有准备好,除非Users
已经执行 [=19] =]?我尝试在AppState
中使用以下代码,但它只是挂起。
代码如下
@PostConstruct
public void appStateInit(){
while(users.getUsers().size()==0){
try{
Thread.sleep(10000); // sleep 10s
}catch(whatever){
}
}
}
我建议在 class 中设置一个 flag
,并在 init() 完成后将其设置为 true
。如果还没有设置flag
,可以跳过load()
的执行,例如:
private AtomicBoolean shouldExecute;
@PostConstruct
public void init(){
users = new ArrayList<>();
shouldExecute = true;
}
@Scheduled(fixedRate = 3600000)
public void load(){
if(shouldExecute){
// load list of users from (say) a file and populate ArrayList 'users'
// this method takes at least 3 mins to finish
}
}
此外,另一种解决方案是在 @Scheduled
注释(文档 here)中配置 initialDelay
,这将延迟第一次执行配置的毫秒数,例如:
@Scheduled(fixedRate = 3600000, initialDelay=180000)
public void load(){
// load list of users from (say) a file and populate ArrayList 'users'
// this method takes at least 3 mins to finish
}