SpringIoC依赖注入的过程(一)

来源:互联网 发布:淘宝怎么避免同款 编辑:程序博客网 时间:2024/05/13 14:11

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接口的回调是怎么被调用的?。下一篇文章详细整理。
   


0 0
原创粉丝点击