Spring获取Bean 源码浅析

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

MyTestBean bean = (MyTestBean)bf.getBean("myTestBean")
我想上面这行代码,第一次接触过spring这个框架时都应该接触过;读取xml中我们配置的bean;

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

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


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

public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}
进入doGetBean :

@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 这个 引用去看看:

/** 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。 且听下回分解~



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值