Spring源碼分析 Bean創建和獲取

Spring源碼分析 Bean創建和獲取

Spring獲取Bean源碼

public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}
	protected Object doGetBean(String name, Class requiredType, final Object args[], boolean typeCheckOnly)
        throws BeansException
    {
        final String beanName;
        Object bean;
        final RootBeanDefinition mbd;
        Object prototypeInstance;
        beanName = transformedBeanName(name);
        // 先嚐試從緩存中獲取bean,對於那些單例模式的Bean,緩存獲取
        Object sharedInstance = getSingleton(beanName);
        if(sharedInstance != null && args == null)
        {
            if(logger.isDebugEnabled())
                if(isSingletonCurrentlyInCreation(beanName))
                    logger.debug((new StringBuilder()).append("Returning eagerly cached instance of singleton bean '").append(beanName).append("' that is not fully initialized yet - a consequence of a circular reference").toString());
                else
                    logger.debug((new StringBuilder()).append("Returning cached instance of singleton bean '").append(beanName).append("'").toString());
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
            break MISSING_BLOCK_LABEL_544;
        }
        if(isPrototypeCurrentlyInCreation(beanName))
            throw new BeanCurrentlyInCreationException(beanName);
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if(parentBeanFactory != null && !containsBeanDefinition(beanName))
        {
            String nameToLookup = originalBeanName(name);
            if(args != null)
                return parentBeanFactory.getBean(nameToLookup, args);
            else
                return parentBeanFactory.getBean(nameToLookup, requiredType);
        }
        if(!typeCheckOnly)
            markBeanAsCreated(beanName);
        mbd = getMergedLocalBeanDefinition(beanName);
        checkMergedBeanDefinition(mbd, beanName, args);
        String dependsOn[] = mbd.getDependsOn();
        if(dependsOn != null)
        {
            String arr$[] = dependsOn;
            int len$ = arr$.length;
            for(int i$ = 0; i$ < len$; i$++)
            {
                String dependsOnBean = arr$[i$];
                getBean(dependsOnBean);
                registerDependentBean(dependsOnBean, beanName);
            }

        }
        if(mbd.isSingleton())
        {
            sharedInstance = getSingleton(beanName, new ObjectFactory() {

                public Object getObject()
                    throws BeansException
                {
                    try
                    {
                        return createBean(beanName, mbd, args);
                    }
                    catch(BeansException ex)
                    {
                        destroySingleton(beanName);
                        throw ex;
                    }
                }

                final String val$beanName;
                final RootBeanDefinition val$mbd;
                final Object val$args[];
                final AbstractBeanFactory this$0;

            
            {
                this$0 = AbstractBeanFactory.this;
                beanName = s;
                mbd = rootbeandefinition;
                args = aobj;
                super();
            }
            }
);
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            break MISSING_BLOCK_LABEL_544;
        }
        if(!mbd.isPrototype())
            break MISSING_BLOCK_LABEL_399;
        prototypeInstance = null;
        beforePrototypeCreation(beanName);
        prototypeInstance = createBean(beanName, mbd, args);
        afterPrototypeCreation(beanName);
        break MISSING_BLOCK_LABEL_383;
        Exception exception;
        exception;
        afterPrototypeCreation(beanName);
        throw exception;
        bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
        break MISSING_BLOCK_LABEL_544;
        String scopeName = mbd.getScope();
        Scope scope = (Scope)scopes.get(scopeName);
        if(scope == null)
            throw new IllegalStateException((new StringBuilder()).append("No Scope registered for scope '").append(scopeName).append("'").toString());
        try
        {
            Object scopedInstance = scope.get(beanName, new ObjectFactory() {

                public Object getObject()
                    throws BeansException
                {
                    beforePrototypeCreation(beanName);
                    Object obj = createBean(beanName, mbd, args);
                    afterPrototypeCreation(beanName);
                    return obj;
                    Exception exception1;
                    exception1;
                    afterPrototypeCreation(beanName);
                    throw exception1;
                }

                final String val$beanName;
                final RootBeanDefinition val$mbd;
                final Object val$args[];
                final AbstractBeanFactory this$0;

            
            {
                this$0 = AbstractBeanFactory.this;
                beanName = s;
                mbd = rootbeandefinition;
                args = aobj;
                super();
            }
            }
);
            bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
        }
        catch(IllegalStateException ex)
        {
            throw new BeanCreationException(beanName, (new StringBuilder()).append("Scope '").append(scopeName).append("' is not active for the current thread; ").append("consider defining a scoped proxy for this bean if you intend to refer to it from a singleton").toString(), ex);
        }
        if(requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass()))
        {
            try
            {
                return getTypeConverter().convertIfNecessary(bean, requiredType);
            }
            catch(TypeMismatchException ex)
            {
                if(logger.isDebugEnabled())
                    logger.debug((new StringBuilder()).append("Failed to convert bean '").append(name).append("' to required type [").append(ClassUtils.getQualifiedName(requiredType)).append("]").toString(), ex);
            }
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        } else
        {
            return bean;
        }
    }

如圖所示,源碼分析
首先獲取bean的名稱 beanName = transformedBeanName(name);
然後查看緩存中bean是否存在,如下圖

Object sharedInstance = getSingleton(beanName);
private final Map singletonObjects = new ConcurrentHashMap(64);
private final Map alreadyCreated;
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		
		/*1*/
		Object singletonObject = singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName))
			synchronized (singletonObjects) {
				singletonObject = earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory singletonFactory = (ObjectFactory) singletonFactories
							.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						earlySingletonObjects.put(beanName, singletonObject);
						singletonFactories.remove(beanName);
					}
				}
			}
		return singletonObject == NULL_OBJECT ? null : singletonObject;
	}
	
	/*2*/
	protected void markBeanAsCreated(String beanName) {
		alreadyCreated.put(beanName, Boolean.TRUE);
}
/*3*/
String dependsOn[] = mbd.getDependsOn();
    if(dependsOn != null)
    {
        String arr$[] = dependsOn;
        int len$ = arr$.length;
        for(int i$ = 0; i$ < len$; i$++)
        {
            String dependsOnBean = arr$[i$];
            getBean(dependsOnBean);
            registerDependentBean(dependsOnBean, beanName);
        }

    }

緊接着,如圖1 通過singletonObjects緩存對象去獲取對象,由於可見,Spring底層用的緩存大多數是緩存在Map結構中,緩存對象首次初始化的時候爲空,構建之前會先調用 如圖2-markBeanAsCreated()標明此處bean狀態爲構建中, 繼續分析如下
如圖3 後續會查看當前bean是否有依賴引用,如A依賴B,首先會把B創建成功後,然後注入到A中
下敘真實獲取bean對象源碼

public static transient Object instantiateClass(Constructor 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.getDeclaringClass(),
					"Is it an abstract class?", ex);
		} catch (IllegalAccessException ex) {
			throw new BeanInstantiationException(ctor.getDeclaringClass(),
					"Is the constructor accessible?", ex);
		} catch (IllegalArgumentException ex) {
			throw new BeanInstantiationException(ctor.getDeclaringClass(),
					"Illegal arguments for constructor", ex);
		} catch (InvocationTargetException ex) {
			throw new BeanInstantiationException(ctor.getDeclaringClass(),
					"Constructor threw exception", ex.getTargetException());
		}
	}
	public static void makeAccessible(Constructor ctor) {
	if ((!Modifier.isPublic(ctor.getModifiers()) || !Modifier.isPublic(ctor
			.getDeclaringClass().getModifiers())) && !ctor.isAccessible())
		ctor.setAccessible(true);
}

由此得出結論,bean創建實例是通過java反射來實現,創建之前會檢查訪問修飾類型,如果不是public可見的,調用setAccessible(true);得到私有構造方法來構建對象實例,接下來要把bean中默認設置的屬性值注入,創建出來的單例bean對象添加到緩存中,供下次直接使用,到此bean創建和獲取流程結束

protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (singletonObjects) {
			//Map緩存單例bean對象
			singletonObjects.put(beanName,
					singletonObject == null ? NULL_OBJECT : singletonObject);
			singletonFactories.remove(beanName);
			earlySingletonObjects.remove(beanName);
			registeredSingletons.add(beanName);
		}
	}

總結:

SpringBean創建和獲取

  • Spring的bean實際上是緩存在CurrentHashMap對象中
  • 創建bean之前,首先要將該bean的創建標識設定好,表示該bean已經即將被創建,其目的增強緩存效率
  • 根據bean的Scope屬性來確定是singleton還是prototype等範圍,然後創建相應bean對象
  • 通過java反射創建bean的實例
  • 接下來,尋找bean的屬性值,完成屬性注入
  • 將所創建出來的singleton對象添加到緩存中,供下次調用使用

作者簡介:張程 技術研究

更多文章請關注微信公衆號:zachary分解獅 (frankly0423)
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章