zoukankan      html  css  js  c++  java
  • spring源码 — 二、从容器中获取Bean

    getBean

    上一节中说明了容器的初始化,也就是把Bean的定义GenericBeanDefinition放到了容器中,但是并没有初始化这些Bean。那么Bean什么时候会初始化呢?

    • 在程序第一个主动在getBean的时候,
    • 在完成容器初始化的时候会初始化lazy-init配置为false或者未配置的Bean(默认是false)

    getBean初始化的时候主要做了哪些事?

    • 得到一个指定类的对象,先从缓存中get,如果没有则new 一个对象
    • 如果是new的对象,则需要装配——初始化对象的一些属性,包括简单属性,如:int,long等类型,包括引用属性,这个时候就会引起依赖注入

    整个获取过程如下:

    获取Bean的过程

    整个图片较大,看起来不清晰,可以右键-在新标签页中打开,就可以放大看了
    注意:以上的时序图是从spring容器初始化的时候会初始化配置为lazy-init=false的Bean,不过过程和我们通过getBean获取Bean的过程一样

    从上面的调用过程获取Bean是从AbstractAutowirecapableBeanFactory的doGetBean方法开始的

    protected <T> T doGetBean(
    		final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
    		throws BeansException {
    
    	// 因为获取的可能是以"&"开头的FactoryBean,所以要进行转化(关于BeanFactory和FactoryBean后面会进行区分)
    	final String beanName = transformedBeanName(name);
    	Object bean;
    
    	// Eagerly check singleton cache for manually registered singletons.
        // 先从缓存中获取,因为在容器初始化的时候或者其他地方调用过getBean,已经完成了初始化
    	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);
    	}
    
    	else {
    		// Fail if we're already creating this bean instance:
    		// We're assumably within a circular reference.
    		if (isPrototypeCurrentlyInCreation(beanName)) {
    			throw new BeanCurrentlyInCreationException(beanName);
    		}
    
    		// Check if bean definition exists in this factory.
    		BeanFactory parentBeanFactory = getParentBeanFactory();
    		if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    			// Not found -> check parent.
                // spring的容器机制:先检查本容器,如果没有再查找父容器
    			String nameToLookup = originalBeanName(name);
    			if (args != null) {
    				// Delegation to parent with explicit args.
    				return (T) parentBeanFactory.getBean(nameToLookup, args);
    			}
    			else {
    				// No args -> delegate to standard getBean method.
    				return parentBeanFactory.getBean(nameToLookup, requiredType);
    			}
    		}
    
    		if (!typeCheckOnly) {
    			markBeanAsCreated(beanName);
    		}
    
    		// 上一节初始化得到的Bean的BeanDefinition用上了
    		final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    		checkMergedBeanDefinition(mbd, beanName, args);
    
    		// Guarantee initialization of beans that the current bean depends on.
    		String[] dependsOn = mbd.getDependsOn();
    		if (dependsOn != null) {
            	// 触发了依赖注入,循环递归初始化依赖的bean
    			for (String dependsOnBean : dependsOn) {
    				getBean(dependsOnBean);
    				registerDependentBean(dependsOnBean, beanName);
    			}
    		}
    
    		// Create bean instance.
            // 创建bean,根据不同的scope进行创建,关于spring的scope介绍,文末有参考链接
    		if (mbd.isSingleton()) {
            	// 初始化Bean
    			sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
    				public Object getObject() throws BeansException {
    					try {
                        	// 在匿名类中调用AbstractAutowireCapableBeanFactory的createBean
    						return createBean(beanName, mbd, args);
    					}
    					catch (BeansException ex) {
    						// Explicitly remove instance from singleton cache: It might have been put there
    						// eagerly by the creation process, to allow for circular reference resolution.
    						// Also remove any beans that received a temporary reference to the bean.
    						destroySingleton(beanName);
    						throw ex;
    					}
    				}
    			});
    			bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    		}
    
    		else if (mbd.isPrototype()) {
    			// It's a prototype -> create a new instance.
    			Object prototypeInstance = null;
    			try {
    				beforePrototypeCreation(beanName);
    				prototypeInstance = createBean(beanName, mbd, args);
    			}
    			finally {
    				afterPrototypeCreation(beanName);
    			}
    			bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
    		}
    
    		else {
    			String scopeName = mbd.getScope();
    			final Scope scope = this.scopes.get(scopeName);
    			if (scope == null) {
    				throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
    			}
    			try {
    				Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
    					public Object getObject() throws BeansException {
    						beforePrototypeCreation(beanName);
    						try {
    							return createBean(beanName, mbd, args);
    						}
    						finally {
    							afterPrototypeCreation(beanName);
    						}
    					}
    				});
    				bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
    			}
    			catch (IllegalStateException ex) {
    				throw new BeanCreationException(beanName,
    						"Scope '" + scopeName + "' is not active for the current thread; " +
    						"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
    						ex);
    			}
    		}
    	}
    
    	// Check if required type matches the type of the actual bean instance.
    	if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
    		try {
    			return getTypeConverter().convertIfNecessary(bean, requiredType);
    		}
    		catch (TypeMismatchException ex) {
    			if (logger.isDebugEnabled()) {
    				logger.debug("Failed to convert bean '" + name + "' to required type [" +
    						ClassUtils.getQualifiedName(requiredType) + "]", ex);
    			}
    			throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    		}
    	}
    	return (T) bean;
    }
    

    上面createBean交给了doCreateBean来创建bean(上面还有一个重要的方法getObjectForBeanInstance,在后面分析)

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
    		// Instantiate the bean.
    		BeanWrapper instanceWrapper = null;
    		if (mbd.isSingleton()) {
    			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    		}
    		if (instanceWrapper == null) {
            	// 使用CglibSubclassingInstantiationStrategy调用BeanUtils的instantiateClass实例化类,在instanceClass方法中利用反射通过构造方法实例化bean
    			instanceWrapper = createBeanInstance(beanName, mbd, args);
    		}
    		final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
    		Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
    
    		// Allow post-processors to modify the merged bean definition.
            // bean初始化前调用post-processors,我们可以在bean实例化之前定制一些操作
    		synchronized (mbd.postProcessingLock) {
    			if (!mbd.postProcessed) {
    				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
    				mbd.postProcessed = true;
    			}
    		}
    
    		// Eagerly cache singletons to be able to resolve circular references
    		// even when triggered by lifecycle interfaces like BeanFactoryAware.
    		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
    				isSingletonCurrentlyInCreation(beanName));
    		if (earlySingletonExposure) {
    			if (logger.isDebugEnabled()) {
    				logger.debug("Eagerly caching bean '" + beanName +
    						"' to allow for resolving potential circular references");
    			}
    			addSingletonFactory(beanName, new ObjectFactory() {
    				public Object getObject() throws BeansException {
    					return getEarlyBeanReference(beanName, mbd, bean);
    				}
    			});
    		}
    
    		// Initialize the bean instance.
    		Object exposedObject = bean;
    		try {
            	// 在这个方法里面初始化对象,设置xml配置的各种属性
    			populateBean(beanName, mbd, instanceWrapper);
    			if (exposedObject != null) {
    				exposedObject = initializeBean(beanName, exposedObject, mbd);
    			}
    		}
    		catch (Throwable ex) {
    			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
    				throw (BeanCreationException) ex;
    			}
    			else {
    				throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
    			}
    		}
    
    		if (earlySingletonExposure) {
    			Object earlySingletonReference = getSingleton(beanName, false);
    			if (earlySingletonReference != null) {
    				if (exposedObject == bean) {
    					exposedObject = earlySingletonReference;
    				}
    				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
    					String[] dependentBeans = getDependentBeans(beanName);
    					Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
    					for (String dependentBean : dependentBeans) {
    						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
    							actualDependentBeans.add(dependentBean);
    						}
    					}
    					if (!actualDependentBeans.isEmpty()) {
    						throw new BeanCurrentlyInCreationException(beanName,
    								"Bean with name '" + beanName + "' has been injected into other beans [" +
    								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
    								"] in its raw version as part of a circular reference, but has eventually been " +
    								"wrapped. This means that said other beans do not use the final version of the " +
    								"bean. This is often the result of over-eager type matching - consider using " +
    								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
    					}
    				}
    			}
    		}
    
    		// Register bean as disposable.
    		try {
    			registerDisposableBeanIfNecessary(beanName, bean, mbd);
    		}
    		catch (BeanDefinitionValidationException ex) {
    			throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    		}
    
    		return exposedObject;
    	}
    

    上面这个方法里面完成了bean的实例化和初始化,已经具备一个普通bean的功能了,但是spring提供了一种增强的bean——FactoryBean,具备factory能力的Bean,这个能力主要在getObjectForBeanInstance得到

    protected Object getObjectForBeanInstance(
    		Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
    
    	// Don't let calling code try to dereference the factory if the bean isn't a factory.
    	if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
    		throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
    	}
    
    	// Now we have the bean instance, which may be a normal bean or a FactoryBean.
    	// If it's a FactoryBean, we use it to create a bean instance, unless the
    	// caller actually wants a reference to the factory.
        // 在这里判断是否时=是FactoryBean,如果不是则直接返回
    	if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
    		return beanInstance;
    	}
    
    	Object object = null;
    	if (mbd == null) {
    		object = getCachedObjectForFactoryBean(beanName);
    	}
    	if (object == null) {
    		// Return bean instance from factory.
    		FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
    		// Caches object obtained from FactoryBean if it is a singleton.
    		if (mbd == null && containsBeanDefinition(beanName)) {
    			mbd = getMergedLocalBeanDefinition(beanName);
    		}
    		boolean synthetic = (mbd != null && mbd.isSynthetic());
            // 在这里面获得最终的FactoryBean
    		object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    	}
    	return object;
    }
    

    关于BeanFactory和FactoryBean的区别:
    BeanFactory:容器的基本接口,是一个工厂,用来生产Bean
    FactoryBean:是一个特殊的Bean,可以当作工厂使用的Bean

    总结

    到这里就完成了bean的初始化,先通过反射实例化bean,然后通过配置的属性初始化bean,然后然会给用户。

    spring中的scope

  • 相关阅读:
    chrome视频播放加速
    centos磁盘空间重新分配
    mseed2sac的安装和使用
    查找台站信息得到台站数据的网站
    java install
    CMT learning
    hosts持续更新
    what is SVD and how to calculate it
    google 镜像
    z变换
  • 原文地址:https://www.cnblogs.com/sunshine-2015/p/5988368.html
Copyright © 2011-2022 走看看