Spring IoC 中的(Singleton)单例对象创建过程探索

前言

  之前将spring framework 源码导入了idea,后来折腾调试了一下,于是研究了一下最简单的singleton对象在spring中是如何创建的。这里所谓的简单,就是指无属性注入,无复杂构造函数的对象。

测试代码

  spring配置:

  <bean id="userService" class="UserService" scope="singleton"></bean>
  测试类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class UserService {
 
   private final Log logger = LogFactory.getLog(getClass());
 
    public UserService(){
        logger.info("UserService created");
        id = UUID.randomUUID().toString();
    }
 
    private String id;
    public String getId(){
        return id;
    }
    public String getUserName(){
        return "xiaopanzi";
    }
}

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void main(String[] args) {
       ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
       context.start();
       testNormalSingleton(context);
   }
 
   private static void testCircleSingleton(ClassPathXmlApplicationContext context){
       SingletonAService aService = context.getBean("aService",SingletonAService.class);
       SingletonBService bService = context.getBean("bService",SingletonBService.class);
 
       aService.getbService().print();
 
       bService.getaService().print();
   }

调试详情

  首先在ApplicationContext 初始化过程,在 refresh 方法中会调用  finishBeanFactoryInitialization 方法,注释上也写的很明白:Instantiate all remaining (not-lazy-init) signletons。(初始化剩余的非懒加载的单例对象)。那么这里就是入口点。

  然后在调用 beanFactory.preInstantiateSingletons().

  后续调用链如下:

  DefaultListBeanFactory.getBean(beanName)

  AbstractBeanFactory.doGetBean(name,requiredType,args,typeCheckOnly)

  AbstractAutowireCapableBeanFactory.createBean(String beanName,RootBeanDefinition mbd,Object[] args)

       AbstractAutowireCapableBeanFactory.doCreateBean(String beanName,RootBeanDefinition mbd,Object[] args)

       AbstractAutowireCapableBeanFactory.instantiateBean(final String beanName, final RootBeanDefinition mbd)

       getInstantiationStrategy().instantiate(mbd, beanName, parent); (this.instantiationStrategy=CglibSubclassingInstantiationStrategy)

 

    SimpleInstantiationStrategy.instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) 

  BeanUtils.instantiateClass(Constructor<T> ctor, Object... args)

 

  通过上述代码调用链我们可以看出,最终的示例创建是由 BeanUtils.instantiateClass 方法完成的,也就是这个方法:

   

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
        Assert.notNull(ctor, "Constructor must not be null");
        try {
            ReflectionUtils.makeAccessible(ctor);
            return ctor.newInstance(args);
        }
        catch (InstantiationException ex) {
            throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
        }
        catch (IllegalAccessException ex) {
            throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
        }
        catch (IllegalArgumentException ex) {
            throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
        }
        catch (InvocationTargetException ex) {
            throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());
        }
    }

  到此为止单例就创建完毕了。但是创建完成之后,还有后续的处理。

   DefaultSingletonBeanRegistry.addSingletonFactory(String beanName,ObjectFactory<?> singletonFactory);

  也就是将该示例放入到  singletonObjects 中,作为缓存方便后续取值。

  this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));

  当我们在次调用getBean的时候,那么在 DefaultSingletonBeanRegistry.getSingleton 方法中直接从 singletonObjects 中获取即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }

  

总结

  上述内容记录的很少,基本就是一个轮廓的记录,要真正理解详情内容,还得自己去慢慢调试啊!!!

  

 

  


  

posted @   丶Pz  阅读(3428)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示

目录

目录

X
+

"大爷常来玩呀"

微信支付