前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring获取Bean 源码浅析

Spring获取Bean 源码浅析

作者头像
用户2141593
发布2019-02-20 10:53:45
5400
发布2019-02-20 10:53:45
举报
文章被收录于专栏:Java进阶Java进阶

今天开门见山,直接亮代码~

代码语言:javascript
复制
MyTestBean bean = (MyTestBean)bf.getBean("myTestBean")

我想上面这行代码,第一次接触过spring这个框架时都应该接触过;读取xml中我们配置的bean;

spring分为7大部分组成,有一个部分叫做:SpringBean;

为了知道这句代码实现了什么样的功能,看官可以可以打开你的开发工具,找到下面这张图的几个包;

首先打开AbstractBeanFactory 这个类, 找到 getBean 这个方法:

代码语言:javascript
复制
public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}

进入doGetBean :

代码语言:javascript
复制
@SuppressWarnings("unchecked")
	protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
			throws BeansException {
		//把beanName 前面可能存在的 所有符号 全部取出;
		final String beanName = transformedBeanName(name);
		Object bean;

		/**
		 * spring会先检查缓存中或者实例工厂中是否有对应的实例,因为在创建单例bean的时候回存在医疗注入的情况;
	 	 * 而在创建以来的时候为了避免循环依赖,spring创建bean的原则是不等bean创建完成就会将创建bean的 objectfactory提前曝光,
		 * 也就是将objectFactory加入到缓存中,一旦下一个bean创建的时候需要依赖上个bean则直接使用objectfactory; 
		 */
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

循环依赖是什么意思呢?  如果存在 A中有B的属性,B中又有A的属性,那么当依赖注入的时候,就会产生A还未完成创建的时候又去创建B,又再次返回创建A;

进入   getSingleton(beanName) 方法 会跳到 DefaultSingletonBeanRegistry 这个类的

再次进入 getSingleton(beanName, true )这个方法;

进入这个方法之前,先了解一个概念,单例在spring的同一个容器中只会被创建一个,之后获取bean就可以直接冲单例的缓存中获取了;

下面介绍的就是从缓存中获取bean的情况;

这样就返回了单例的 singletonObject

看到这里,你可能不知道 singletonFactory怎么来的, 进入  singletonFactories 这个 引用去看看:

代码语言:javascript
复制
/** Cache of singleton objects: bean name --> bean instance */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);

	/** Cache of singleton factories: bean name --> ObjectFactory */
	private final Map<String, ObjectFactory> singletonFactories = new HashMap<String, ObjectFactory>(16);

	/** Cache of early singleton objects: bean name --> bean instance */
	private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);

	/** Set of registered singletons, containing the bean names in registration order */
	private final Set<String> registeredSingletons = new LinkedHashSet<String>(64);

1.singletonObjects : 用于保存beanName和创建bean实例之间的关系  2.singletonFactories : 用于保存beanName和创建bean的工厂之间的关系  3.earlySingletonObjects :也是保存beanName和bean实例之间的关系,与singletonObjects 的不同之处在于,当一个单例bean被放在这里后,那么当bean还在创建过程中,就可以通过getBean的方法获取了,其目的是用来检测循环引用。  4.registeredSingletons : 用于保存当前所有已注册的bean。

因为 singletonFactory实现了 ObjectFactory这个接口; spring全家桶 会根据 beanName去创建 一个singletonFactory;

上面是从缓冲中获取单例,那么缓冲中要是不存在已经加载好的单例bean,那就要重头开始执行加载bean了,spring重写了getSingleton,

public Object getSingleton ( String beanName, ObjectFactory singletonFactory) {  ......    }

从上面代码可以看到,spring依赖注入时,使用了双重判断加锁的单例模式,首先从缓存中获取bean实例,如果为null,对缓存map加锁,然后再从缓存中获取bean,如果继续为null,就创建一个bean。这样双重判断,能够避免在加锁的瞬间,有其他依赖注入引发bean实例的创建,从而造成重复创建的结果。

Spring并没有使用我们常见的私有构造方法来创建bean,而是通过singletonFactory.getObject()返回具体beanName对应的ObjectFactory来创建bean。

这就是spring获取bean的一个简单流程;创建了spring的bean对象,还没完,还没有实例化这个bean。 且听下回分解~

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017年06月02日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档