Spring IoC 中的(Singleton)单例对象创建过程探索
前言
之前将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)单例对象创建过程探索的更多相关文章
- Spring IOC(三)单例 bean 的注册管理
Spring IOC(三)单例 bean 的注册管理 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 在 Spring 中 ...
- Singleton单例对象的使用
namespace www{ public abstract class SingletonManager<T> : ISingletonManager where T : class, ...
- Spring IOC 容器源码分析 - 创建单例 bean 的过程
1. 简介 在上一篇文章中,我比较详细的分析了获取 bean 的方法,也就是getBean(String)的实现逻辑.对于已实例化好的单例 bean,getBean(String) 方法并不会再一次去 ...
- 不允许在单例对象中创建Srping容器
spring.net在使用的时候,不允许在单例对象中创建Srping容器 需要将实例化模式转为单例singleton=“false”
- 从别人写的 Object-C 中 Singleton (单例) 模式 中的一些理解--备
关于 面向对象的设计模式 对于面向对象的设计模式,想必大家并不陌生吧. 纵观23种设计模式中,数单例模式(Singleton)和工厂模式(Factory Method)最为熟悉和基础吧.当然,本文总结 ...
- 【cocos2d-js官方文档】二十五、Cocos2d-JS v3.0中的单例对象
为何将单例模式移除 在Cocos2d-JS v3.0之前.全部API差点儿都是从Cocos2d-x中移植过来的,这是Cocos2d生态圈统一性的重要一环.可惜的是,这样的统一性也在非常大程度上限制了C ...
- atitit.guice3 绑定方式打总结生成非单例对象toInstance toProvider区别 v2 pb29
atitit.guice3 绑定方式打总结生成非单例对象toInstance toProvider区别 v2 pb29 1. 三 绑定方式的介绍1 2. To接口,链式绑定,用的最多的1 3. toC ...
- OC中两种单例实现方式
OC中两种单例实现方式 写在前面 前两天探索了一下C++ 的单例,领悟深刻了许多.今天来看看OC中的单例又是怎么回事.查看相关资料,发现在OC中一般有两种实现单例的方式,一种方式是跟C++ 中类似的常 ...
- 【Cocos2d-X游戏实战开发】捕鱼达人之单例对象的设计(二)
本系列学习教程使用的是cocos2d-x-2.1.4(最新版为cocos2d-x-2.1.5) 博主发现前两个系列的学习教程被严重抄袭,在这里呼吁大家请尊重开发者的劳动成果, 转载的时候请务必注 ...
随机推荐
- crontab 设置服务器定期执行备份工作
基本格式 : * * * * * command 分 时 日 月 周 命令 第1列表示分钟1-59 每分钟用*或者 */1表示 第2列表示小时1-23(0表示0点) 第3列表示日期1-31 第4列表示 ...
- Oracle 数据库字典 sys.obj$ 表中关于type#的解释
sys.obj$ 表是oracle 数据库字典表中的对象基础表,所有对象都在该表中有记录,其中type#字段表明对象类型,比如有一个表 test ,则该对象在sys.obj$ 中存在一条记录,name ...
- Service的启动流程源码跟踪
前言: 当我们在一个Activity里面startService的时候,具体的执行逻辑是怎么样的?需要我们一步步根据源码阅读. 在阅读源码的时候,要关注思路,不要陷在具体的实现细节中,一步步整理代码的 ...
- 微信公众号开发《三》微信JS-SDK之地理位置的获取与在线导航,集成百度地图实现在线地图搜索
本次讲解微信开发第三篇:获取用户地址位置信息,是非常常用的功能,特别是服务行业公众号,尤为需要该功能,本次讲解的就是如何调用微信JS-SDK接口,获取用户位置信息,并结合百度地铁,实现在线地图搜索,与 ...
- Redis(MySQL和redis怎么分工合作的?)
新手: redis也是服务器,主要部署在服务器上缓解服务器的压力,对于访问量交大的数据可以先缓存到redis,用户访问时直接访问redis,不用再直接访问数据库,缓解数据库的压力.mysql主要存储数 ...
- 如何去除vue项目中的 # — vue路由的History模式
前言 在创建的 router 对象中,如果不配置 mode,就会使用默认的 hash 模式,该模式下会将路径格式化为 #! 开头. 添加 mode: 'history' 之后将使用 HTML5 his ...
- 移动前端开发之viewport,devicePixelRatio的深入理解
移动前端开发之viewport的深入理解 在移动设备上进行网页的重构或开发,首先得搞明白的就是移动设备上的viewport了,只有明白了viewport的概念以及弄清楚了跟viewport有关的met ...
- [小北De编程手记] : Lesson 02 - Selenium For C# 之 核心对象
从这一篇开始,开始正式的介绍Selenium 以及相关的组件,本文的将讨论如下问题: Selenium基本的概念以及在企业化测试框架中的位置 Selenium核心对象(浏览器驱动) Web Drive ...
- Apache服务器运维笔记(2)----使用<IfDefine>容器实现不同的配置
还有一种方法用来实现不同配置的Apache服务器启动,就是在一个配置文件中使用<IfDefine name> ... </IfDefine> 容器来定义,在<IfDefi ...
- 轻松看懂机器学习十大常用算法 (Machine Learning Top 10 Commonly Used Algorithms)
原文出处: 不会停的蜗牛 通过本篇文章可以对ML的常用算法有个常识性的认识,没有代码,没有复杂的理论推导,就是图解一下,知道这些算法是什么,它们是怎么应用的,例子主要是分类问题. 每个算法都看了 ...