SpringIoC依赖注入的过程(一)

      对spring稍有些了解的人都知道,依赖注入的发生是在第一次向容器索要bean时触发的。BeanFanctory为我们提供了一系列的getBean接口,它的实现大部分都在AbstractBeanFactory中,最终都会调用到doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)这个方法。不管各种getBean方法需要什么样的参数,都得必须组合成上面的四个参数提供给doGetBean,并且bean的名字是必须的。虽然BeanFactory中有直接根据类型获取的方法getBean(Class<T> requiredType),但是AbstractBeanFactory并没有实现。
     doGetBean的第一步先检查是否有已经缓存好的单例bean,如果有则取出这个bean对象。没有取到缓存的单例,第二步尝试到双亲BeanFactory中去寻找,若找到则直接返回。接下来会取出当前bean的所有依赖bean,并且递归的调用getBean以先创建当前bean依赖的bean(这里说的依赖bean不包括声明的Autowire域,也不包括xml配置文件中通过ref引用的bean)。下面是doGetBean的这部分代码:
			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) {
				for (String dependsOnBean : dependsOn) {
					getBean(dependsOnBean);
					registerDependentBean(dependsOnBean, beanName);
				}
			}
     处理完上面所说的依赖bean,下面会判断bean的scope是什么,然后根据不同的scope采用不同的方法来获取bean。不管怎样,如果bean还没有创建的话,它们都会通过createBean方法来创建一个全新的bean。在spring的应用中,大部分的bean都是单例的,所以以单例bean为例子,看看怎么来获取想要的bean。
        if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                public Object getObject() throws BeansException {
                    try {
                        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);
        }
    上面的getSingleton方法定义在DefaultSingletonBeanRegistry中,它是 AbstractBeanFactory的父类,它会返回一个创建好的bean,代码如下:
	public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
		Assert.notNull(beanName, "'beanName' must not be null");
		synchronized (this.singletonObjects) {
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while the singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}
				beforeSingletonCreation(beanName);
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<Exception>();
				}
				try {
					singletonObject = singletonFactory.getObject();
				}
				catch (BeanCreationException ex) {
					if (recordSuppressedExceptions) {
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					afterSingletonCreation(beanName);
				}
				addSingleton(beanName, singletonObject);
			}
			return (singletonObject != NULL_OBJECT ? singletonObject : null);
		}
	}
 
	/** Cache of singleton objects: bean name --> bean instance */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>();
    getSingleton方法首先锁住了singletonObjects对象,这个 singletonObjects是DefaultSingletonBeanRegistry中注册的所有单例bean。然后再次判断是否已经有创建好的单例bean,这样做的目的是为了在高并发的情况下产生创建多个bean实例的情况。类似于经典的双重检查的单例模式,但是是线程安全的,因为singletonObjects是一个线程安全的ConcurrentHashMap,当程序进入同步块从singletonObjects获取缓存的单例的时候,要么获取不到,要么获取到创建好的单例,绝对不会得到未创建好的中间状态的单例实例。略过线程安全的问题,进入到同步块内仍然取不到缓存好的单例怎么办呢?通过singletonFactory.getObject()创建一个,这个singletonFactory就是刚刚调用getSingleton方法传入的ObjectFactory类型的匿名类,通过他回调了AbstractAutowireCapableBeanFactory中的createBean方法。createBean最主要的工作就是调用doCreateBean方法来创建一个全新的bean。
	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) {
			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.
		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 {
			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;
	}
   上面就是doCreateBean得全部代码。它的首先第一步通过createBeanInstance创建bean实例,并且放到BeanWrapper中返回。可以看到这个方法返回的 BeanWrapper赋值到了instanceWrapper中,然后用它的getWrappedInstance()取出了创建出来的bean。注意,这时候的bean相当于刚刚执行完构造方法的Java对象,关于这个bean的依赖关系以及其他的一些初始化操作都还没有执行。 创建好bean实例之后,接下来就是通过一系列的后置处理器来注入当前bean依赖的其他bean,并且进行相应的初始化操作。依赖的bean是怎样注入进来的,bean的PostConstructor、afterPropertiesSet以及各种*aware接口的回调是怎么被调用的?。下一篇文章详细整理。
   


Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐