码迷,mamicode.com
首页 > 编程语言 > 详细

一次Spring Bean初始化顺序问题排查记录

时间:2018-12-10 15:41:12      阅读:433      评论:0      收藏:0      [点我收藏+]

标签:res   依赖   override   异常   return   one   问题排查   操作   容器   

最近在使用Springboot的时候需要通过静态的方法获取到Spring容器托管的bean对象,参照一些博文里写的,新建了个类,并实现ApplicationContextAware接口。代码大致如下: 

@Component
public class SpringUtils implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if(SpringUtils.applicationContext == null) {
            SpringUtils.applicationContext = applicationContext;
        }
    }
   public static <T> T getBean(String name,Class<T> clazz){
        return getApplicationContext().getBean(name, clazz);
    }  
}

然后另外一个bean需要依赖这个静态获取bean的方法,代码大致如下:

@Component
public class TestBean{

   private Object dependencyBean = SpringUtils.getBean(OtherBean.class);  
    
}

(注: 忽略代码逻辑是否合理~~ 这些代码是为演示所用简化的逻辑,肯定有同学会说:既然都是bean了为什么不注入,而是要用静态的获取呢?这个暂时不考虑,暂认为就必须要这样搞)

这两个类的层次结构和包名大致如下: 

utils

> notice

  > TestBean

> SpringUtils


就是TestBean在SpringUtils的下一级,TestBean所在包名为notice(这这个名字很重要! 直接影响到这两个bean的加载顺序,具体原理往下看

代码就这么多,从以上代码来静态分析看,确实有些漏洞,因为没有考虑到Spring bean的加载顺序,可能导致的SpringUtils报空指针异常(在TestBean先于SpringUtils初始化的场景下),不管怎么样先执行一下看下效果,效果如下: 

macOS操作系统下代码正常

windows平台下代码空指针异常

为什么这还跟平台有关了呢?难道Spring bean的初始化顺序还跟平台有关?事实证明这个猜想是正确的。下面从Spring源代码里找原因。

普通的(什么样的bean算是普通?这里暂定用@Component注解的bean)Spring bean的加载包括两个部分,第一部分是加载bean的定义,第二部分是实例化bean。这个可以在AbstractApplicationContext.refresh方法里找到对应:

 

一次Spring Bean初始化顺序问题排查记录

标签:res   依赖   override   异常   return   one   问题排查   操作   容器   

原文地址:https://www.cnblogs.com/caiyao/p/10096263.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!