前言

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

测试代码

  spring配置:

  <bean id="userService" class="UserService" scope="singleton"></bean>
  测试类:
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";
}
}

  

 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 方法完成的,也就是这个方法:

   

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 中获取即可。

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);
}

  

总结

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

  

  


  

Spring IoC 中的(Singleton)单例对象创建过程探索的更多相关文章

  1. Spring IOC(三)单例 bean 的注册管理

    Spring IOC(三)单例 bean 的注册管理 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 在 Spring 中 ...

  2. Singleton单例对象的使用

    namespace www{ public abstract class SingletonManager<T> : ISingletonManager where T : class, ...

  3. Spring IOC 容器源码分析 - 创建单例 bean 的过程

    1. 简介 在上一篇文章中,我比较详细的分析了获取 bean 的方法,也就是getBean(String)的实现逻辑.对于已实例化好的单例 bean,getBean(String) 方法并不会再一次去 ...

  4. 不允许在单例对象中创建Srping容器

    spring.net在使用的时候,不允许在单例对象中创建Srping容器 需要将实例化模式转为单例singleton=“false”

  5. 从别人写的 Object-C 中 Singleton (单例) 模式 中的一些理解--备

    关于 面向对象的设计模式 对于面向对象的设计模式,想必大家并不陌生吧. 纵观23种设计模式中,数单例模式(Singleton)和工厂模式(Factory Method)最为熟悉和基础吧.当然,本文总结 ...

  6. 【cocos2d-js官方文档】二十五、Cocos2d-JS v3.0中的单例对象

    为何将单例模式移除 在Cocos2d-JS v3.0之前.全部API差点儿都是从Cocos2d-x中移植过来的,这是Cocos2d生态圈统一性的重要一环.可惜的是,这样的统一性也在非常大程度上限制了C ...

  7. atitit.guice3 绑定方式打总结生成非单例对象toInstance toProvider区别 v2 pb29

    atitit.guice3 绑定方式打总结生成非单例对象toInstance toProvider区别 v2 pb29 1. 三 绑定方式的介绍1 2. To接口,链式绑定,用的最多的1 3. toC ...

  8. OC中两种单例实现方式

    OC中两种单例实现方式 写在前面 前两天探索了一下C++ 的单例,领悟深刻了许多.今天来看看OC中的单例又是怎么回事.查看相关资料,发现在OC中一般有两种实现单例的方式,一种方式是跟C++ 中类似的常 ...

  9. 【Cocos2d-X游戏实战开发】捕鱼达人之单例对象的设计(二)

    本系列学习教程使用的是cocos2d-x-2.1.4(最新版为cocos2d-x-2.1.5)    博主发现前两个系列的学习教程被严重抄袭,在这里呼吁大家请尊重开发者的劳动成果, 转载的时候请务必注 ...

随机推荐

  1. C#实体对象序列化成Json,格式化,并让字段的首字母小写

    解决办法有两种:第一种:使用对象的字段属性设置JsonProperty来实现(不推荐,因为需要手动的修改每个字段的属性) public class UserInfo { [JsonProperty(& ...

  2. 记录日志好习惯——Log4net入门(WCF篇)

    本篇是在学习了“编码之道”的Log4net入门(WCF篇)http://www.cnblogs.com/yonghuacui/p/6181864.html之后,总结了一些自认为比较重要的细节.顺便把创 ...

  3. .net core 第一篇选择开发工具和环境

    .net core 已经发布三年了,社区也逐步成熟.作为微软阵营的一员,忙了一年年底抽点时间系统学习下.学习资料主要为以下为主: 1. https://docs.microsoft.com/zh-cn ...

  4. 数据结构--ADT

    好吧,这个没什么好讲的,写过java代码的人估计一直都在用ADT, ADT,其实就是abstract data type,抽象数据类型,额,其实他丫就是,java 的class...... 不过关于A ...

  5. js 表格合并单元格

    5列  根据需要可添加 或 删除 strOneTemp  strTwoTemp  strThreeTemp  strFourTemp  strFiveTemp //合并单元格  this.mergeC ...

  6. RabbitMQ如何解决各种情况下丢数据的问题

    1.生产者丢数据 生产者的消息没有投递到MQ中怎么办?从生产者弄丢数据这个角度来看,RabbitMQ提供transaction和confirm模式来确保生产者不丢消息. transaction机制就是 ...

  7. 微信公众号开发《三》微信JS-SDK之地理位置的获取与在线导航,集成百度地图实现在线地图搜索

    本次讲解微信开发第三篇:获取用户地址位置信息,是非常常用的功能,特别是服务行业公众号,尤为需要该功能,本次讲解的就是如何调用微信JS-SDK接口,获取用户位置信息,并结合百度地铁,实现在线地图搜索,与 ...

  8. Luogu4234:最小差值生成树

    题面 luogu Sol 好久没写\(LCT\) 然而写跪了\(TAT\) 把边从小到大加入森林 如果形成环,就替换最小的边 如果已经是树,更新答案 \(LCT\)维护 # include <b ...

  9. org.apache.ibatis.binding.BindingException

    1.异常提示: org.apache.ibatis.binding.BindingException: Mapper method 'com.artup.dao.WorksDao.selectWork ...

  10. webapi datetime类型序列化成json带T且时间不对问题的解决

    在global.asax.cs里加入如下代码: protected void Application_Start() { GlobalConfiguration.Configuration.Forma ...