我有一个Spring boot应用程序,它有两个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();
}
}
我注意到load()
中的方法Users
被触发了两次 - 可能是init()
期间的一次,另一次是load()
之后的Users
bean已被创建。所以我删除了load()
中init()
的来电。这解决了冗余呼叫问题。
但是,现在我发现只要AppState
和Users
bean已创建,我的服务就会启动,即使Users
尚未填充数据。这对我来说是有风险的,因为在此期间,如果查询,服务将返回0个用户。
我需要以下任何一项帮助。
我应该将load()
移回init()
以确保当bean使用PostConstruct
完成时,它确实拥有所有用户信息吗?如果我走这条路线,我怎样才能防止load()
的多余运行?
如果load()
不在init()
之内,除非AppState
已执行Users
,否则如何确保load()
未就绪?我尝试在AppState
中使用以下代码,但它只是挂起。
代码如下。
@PostConstruct
public void appStateInit(){
while(users.getUsers().size()==0){
try{
Thread.sleep(10000); // sleep 10s
}catch(whatever){
}
}
}
答案 0 :(得分:2)
我建议在类中使用flag
并在init()完成后将其设置为true
。如果尚未设置load()
,则可以跳过flag
的执行,例如:
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
}
}
另外,另一个解决方案是在initialDelay
注释(文档here)中配置@Scheduled
,这将延迟第一次执行配置的毫秒数,例如:
@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
}