在启动Spring引导服务之前等待依赖项加载

时间:2016-04-13 21:21:21

标签: java spring-boot autowired postconstruct spring-scheduled

我有一个Spring boot应用程序,它有两个bean - AppStateUsersAppState取决于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()的来电。这解决了冗余呼叫问题。

但是,现在我发现只要AppStateUsers 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){
        }
    }
}

1 个答案:

答案 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
    }