spring中使用@DependsOn註解控制bean的加載順序

錯誤回溯

獲取spring的上下文,放到靜態變量applicationContext

@Component
public class ApplicationContextUtil implements ApplicationContextAware {
    public static ApplicationContext applicationContext = null;
    @Override
    public void setApplicationContext(ApplicationContext args){
        applicationContext = args;
    }
}

緩存組件,使用單例模式,沒有放到容器中

public class CacheComponent {
    List<IotOperatorTemplate> iotOperatorTemplates;
    private CacheComponent(){
    //注意,此處使用了上一步獲取的上下文屬性applicationContext
        IotOperatorTemplateMapper iotOperatorTemplateMapper = (IotOperatorTemplateMapper)ApplicationContextUtil.applicationContext.getBean("iotOperatorTemplateMapper");
        iotOperatorTemplates = iotOperatorTemplateMapper.selectList(null);
    }
    public static class CacheHolder{
       private static CacheComponent cacheComponent =  new CacheComponent();
    }
    public static CacheComponent getInstance(){
        return CacheHolder.cacheComponent;
    }
}

容器中的bean,項目啓動就獲取緩存組件中的緩存對象

@Component
public class ThirdHuClient implements InitializingBean {

    @Override
    public void afterPropertiesSet(){
        try{
            //從緩存組件獲取所有運營商模板
            IotOperatorTemplate iotOperatorTemplate = CacheComponent.getInstance().getIotOperatorTemplates()
                    .stream().filter(item -> item.getType().equals(TemplateConstants.THRID_HU.getMessage())).findFirst().get();
    }
   }
}     

然後有service自動注入了ThirdHuClient,項目啓動,報錯如下圖
在這裏插入圖片描述
分析上圖發現,當容器啓動時,首先調用了ThirdHuClientafterPropertiesSet()方法,該方法中CacheComponent.getInstance()觸發單例類加載
在這裏插入圖片描述
在這裏插入圖片描述

原因分析

CacheComponent類加載時,此時ApplicationContextUtil還沒有放入到容器,故獲取不到應用上下文,所以調用getBean()方法會拋出NPE。

解決

ThirdHuClient這個bean的初始化必須依賴ApplicationContextUtil這個bean,此時主角就出場了,@DependsOn,在ThirdHuClient類上加上這個註解,表示先初始化ApplicationContextUtil。如圖所示
在這裏插入圖片描述

結論

有很多場景需要bean B應該被先於bean A被初始化,從而避免各種負面影響。我們可以在bean A上使用@DependsOn註解,告訴容器bean B應該先被初始化

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章