zoukankan      html  css  js  c++  java
  • Spring Framework源代码解析之IOC容器(三)

         Spring Framework源代码解析之IOC容器(一)Spring Framework源代码解析之IOC容器(二),我们对Spring IOC做了简单介绍以及熟悉了一些支持IOC的关键类,本文将对IOC的依赖注入特性进行解析,欢迎指正。

    载入和注册

         在上文中,我们介绍到XmlBeanFactory对资源文件的载入,并最后引出了一个高帅富——ApplicationContext。接着上文来看,其实我们平时最常用的是Application,因为它不仅具备BeanFactory的全部能力,还为应用程序提供了很多的便利,上文已经说过了,它继承了很多父类,使它可以具备支持国际化、支持多方式定义资源,支持事件等。我们可以认为BeanFactory和Application是两个层面的IOC容器,而我们平时开发应用程序就是使用Application。Application有很多抽象子类,如AbstractApplicationContext,在该抽象子类下又有很多具体的实现类,如FileSystemXmlApplicationContext、ClassPathXmlApplicationContext等。我们以FileSystemXmlApplicationContext为例,来看看它载入和注册资源的过程。

        首先通过FileSystemXmlApplicationContext来建立IOC容器:

    ApplicationContext = new FileSystemXmlApplicationContext(xmlPath);

    调用构造函数:

    /**
    * Create a new FileSystemXmlApplicationContext, loading the definitions
    * from the given XML files and automatically refreshing the context.
    * @param configLocations array of file paths
    * @throws BeansException if context creation failed
     */
    public FileSystemXmlApplicationContext(String... configLocations) throws BeansException {
    		this(configLocations, true, null);
    	}

    实际调用:

    public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
    			throws BeansException {
    
    		super(parent);
    		setConfigLocations(configLocations);
    		if (refresh) {
    			refresh();
    		}
    	}

    注意方法refresh(),这里使用了一个“模板方法”的设计模式,refresh()是一个模板方法,具体实现在FileSystemXmlApplicationContext的若干级父类AbstractXmlApplicationContext中:

    public void refresh() throws BeansException, IllegalStateException {  
         synchronized (this.startupShutdownMonitor) {  
             synchronized (this.activeMonitor) {  
                 this.active = true;  
             }  
       
            // 这里需要子类来协助完成资源位置定义,bean 载入和向 IOC 容器注册的过程   
            refreshBeanFactory();  
             ............  
    }

    refresh()方法包含了整个IOC容器的初始化过程,资源的定位由refreshBeanFactory()来实现,而在AbstractXmlApplicationContext中定义了对资源的读取过程,默认由 XmlBeanDefinitionReader 来读取:

    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {  
         // 这里使用 XMLBeanDefinitionReader 来载入 bean 定义信息的 XML 文件   
         XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);   
        
         //这里配置 reader 的环境,其中 ResourceLoader 是我们用来定位 bean 定义信息资源位置的   
         ///因为上下文本身实现了 ResourceLoader 接口,所以可以直接把上下文作为 ResourceLoader 传递给 XmlBeanDefi
    nitionReader   
         beanDefinitionReader.setResourceLoader(this);  
         beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));  
       
         initBeanDefinitionReader(beanDefinitionReader);  
         //这里转到定义好的 XmlBeanDefinitionReader 中对载入 bean 信息进行处理  
         loadBeanDefinitions(beanDefinitionReader);  
    }

    转到beanDefinitionReader中进行处理:

    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOExcepti
    on {   
         Resource[] configResources = getConfigResources();  
         if (configResources != null) {  
             //调用 XmlBeanDefinitionReader 来载入 bean 定义信息。  
             reader.loadBeanDefinitions(configResources);  
         }  
         String[] configLocations = getConfigLocations();  
         if (configLocations != null) {  
             reader.loadBeanDefinitions(configLocations);  
         }  
    }

    完成了载入,我们来分析注册,来到DefaultListableBeanFactory中,它通过HashMap来持有载入的BeanDefinition:

    /** Map of bean definition objects, keyed by bean name */
    	private final Map beanDefinitionMap = new ConcurrentHashMap();

    跟踪代码,找到注册的具体实现类DefaultListableBeanFactoy:

    //---------------------------------------------------------------------
    	// Implementation of BeanDefinitionRegistry interface
    	//---------------------------------------------------------------------
    
    	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
    			throws BeanDefinitionStoreException {
    
    		Assert.hasText(beanName, "Bean name must not be empty");
    		Assert.notNull(beanDefinition, "BeanDefinition must not be null");
    
    		if (beanDefinition instanceof AbstractBeanDefinition) {
    			try {
    				((AbstractBeanDefinition) beanDefinition).validate();
    			}
    			catch (BeanDefinitionValidationException ex) {
    				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
    						"Validation of bean definition failed", ex);
    			}
    		}
    
    		synchronized (this.beanDefinitionMap) {
    			//这里检查是不是有名字相同的BeanDefinition已经在IOC容器中注册,如果有但不允许覆盖则抛出异常
    			Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
    			if (oldBeanDefinition != null) {
    				if (!this.allowBeanDefinitionOverriding) {
    					throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
    							"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
    							"': There is already [" + oldBeanDefinition + "] bound.");
    				}
    				else {
    					if (this.logger.isInfoEnabled()) {
    						this.logger.info("Overriding bean definition for bean '" + beanName +
    								"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
    					}
    				}
    			}
    			else {
    				this.beanDefinitionNames.add(beanName);
    				this.frozenBeanDefinitionNames = null;
    			}
    			this.beanDefinitionMap.put(beanName, beanDefinition);
    
    			resetBeanDefinition(beanName);
    		}
    	}

    完成了注册,此时我们就是从容器中使用对象了,万事具备只欠getBean了。

    依赖注入

        我们记得在BeanFactory中有一个getBean方法,它其实就是触发依赖注入的入口,getBean的实现我们具体看看DefaultListableBeanFactory的父类AbstractBeanFactory,看看其中getBean的是如何实现的:

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

    接着看doGetBean:

       1:  protected <T> T doGetBean(final String name, final Class<T> requiredType,
       2:              final Object[] args, boolean typeCheckOnly) throws BeansException {
       3:   
       4:          final String beanName = transformedBeanName(name);
       5:          Object bean;
       6:   
       7:          // Eagerly check singleton cache for manually registered singletons.
       8:          // 先从缓存里面取,处理已经被创建过的单件模式的bean,对这种bean的获取不需要重复的创建
       9:          Object sharedInstance = getSingleton(beanName);
      10:          if (sharedInstance != null && args == null) {
      11:              if (logger.isDebugEnabled()) {
      12:                  if (isSingletonCurrentlyInCreation(beanName)) {
      13:                      logger.debug("Returning eagerly cached instance of singleton bean '"
      14:                              + beanName
      15:                              + "' that is not fully initialized yet - a consequence of a circular reference");
      16:                  } else {
      17:                      logger.debug("Returning cached instance of singleton bean '"
      18:                              + beanName + "'");
      19:                  }
      20:              }
      21:              bean = getObjectForBeanInstance(sharedInstance, name, beanName,
      22:                      null);
      23:          }
      24:   
      25:          else {
      26:              // Fail if we're already creating this bean instance:
      27:              // We're assumably within a circular reference.
      28:              if (isPrototypeCurrentlyInCreation(beanName)) {
      29:                  throw new BeanCurrentlyInCreationException(beanName);
      30:              }
      31:   
      32:              // Check if bean definition exists in this factory.
      33:              BeanFactory parentBeanFactory = getParentBeanFactory();
      34:              if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
      35:                  // Not found -> check parent.
      36:                  String nameToLookup = originalBeanName(name);
      37:                  if (args != null) {
      38:                      // Delegation to parent with explicit args.
      39:                      return (T) parentBeanFactory.getBean(nameToLookup, args);
      40:                  } else {
      41:                      // No args -> delegate to standard getBean method.
      42:                      return parentBeanFactory
      43:                              .getBean(nameToLookup, requiredType);
      44:                  }
      45:              }
      46:   
      47:              if (!typeCheckOnly) {
      48:                  markBeanAsCreated(beanName);
      49:              }
      50:              // 这里根据bean的名字取得BeanDefinition
      51:              final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
      52:              checkMergedBeanDefinition(mbd, beanName, args);
      53:   
      54:              // Guarantee initialization of beans that the current bean depends
      55:              // on.
      56:              // 取当前bean的所有依赖的bean,这样会触发getBean的递归调用,直至取到一个没有任何依赖的bean为止
      57:              String[] dependsOn = mbd.getDependsOn();
      58:              if (dependsOn != null) {
      59:                  for (String dependsOnBean : dependsOn) {
      60:                      getBean(dependsOnBean);
      61:                      registerDependentBean(dependsOnBean, beanName);
      62:                  }
      63:              }
      64:   
      65:              // Create bean instance.
      66:              // 这里创建单例的实例,调用createBean方法
      67:              if (mbd.isSingleton()) {
      68:                  sharedInstance = getSingleton(beanName,
      69:                          new ObjectFactory<Object>() {
      70:                              public Object getObject() throws BeansException {
      71:                                  try {
      72:                                      return createBean(beanName, mbd, args);
      73:                                  } catch (BeansException ex) {
      74:                                      // Explicitly remove instance from singleton
      75:                                      // cache: It might have been put there
      76:                                      // eagerly by the creation process, to allow
      77:                                      // for circular reference resolution.
      78:                                      // Also remove any beans that received a
      79:                                      // temporary reference to the bean.
      80:                                      destroySingleton(beanName);
      81:                                      throw ex;
      82:                                  }
      83:                              }
      84:                          });
      85:                  bean = getObjectForBeanInstance(sharedInstance, name, beanName,
      86:                          mbd);
      87:              }
      88:              // 这里则是创建prototype bean的地方
      89:              else if (mbd.isPrototype()) {
      90:                  // It's a prototype -> create a new instance.
      91:                  Object prototypeInstance = null;
      92:                  try {
      93:                      beforePrototypeCreation(beanName);
      94:                      prototypeInstance = createBean(beanName, mbd, args);
      95:                  } finally {
      96:                      afterPrototypeCreation(beanName);
      97:                  }
      98:                  bean = getObjectForBeanInstance(prototypeInstance, name,
      99:                          beanName, mbd);
     100:              }
     101:   
     102:              else {
     103:                  String scopeName = mbd.getScope();
     104:                  final Scope scope = this.scopes.get(scopeName);
     105:                  if (scope == null) {
     106:                      throw new IllegalStateException(
     107:                              "No Scope registered for scope '" + scopeName + "'");
     108:                  }
     109:                  try {
     110:                      Object scopedInstance = scope.get(beanName,
     111:                              new ObjectFactory<Object>() {
     112:                                  public Object getObject() throws BeansException {
     113:                                      beforePrototypeCreation(beanName);
     114:                                      try {
     115:                                          return createBean(beanName, mbd, args);
     116:                                      } finally {
     117:                                          afterPrototypeCreation(beanName);
     118:                                      }
     119:                                  }
     120:                              });
     121:                      bean = getObjectForBeanInstance(scopedInstance, name,
     122:                              beanName, mbd);
     123:                  } catch (IllegalStateException ex) {
     124:                      throw new BeanCreationException(
     125:                              beanName,
     126:                              "Scope '"
     127:                                      + scopeName
     128:                                      + "' is not active for the current thread; "
     129:                                      + "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
     130:                              ex);
     131:                  }
     132:              }
     133:          }
     134:   
     135:          // Check if required type matches the type of the actual bean instance.
     136:          // 这里对创建出来bean进行类型的检查,如果没有问题,就返回这个新创建的bean
     137:          if (requiredType != null && bean != null
     138:                  && !requiredType.isAssignableFrom(bean.getClass())) {
     139:              try {
     140:                  return getTypeConverter()
     141:                          .convertIfNecessary(bean, requiredType);
     142:              } catch (TypeMismatchException ex) {
     143:                  if (logger.isDebugEnabled()) {
     144:                      logger.debug(
     145:                              "Failed to convert bean '" + name
     146:                                      + "' to required type ["
     147:                                      + ClassUtils.getQualifiedName(requiredType)
     148:                                      + "]", ex);
     149:                  }
     150:                  throw new BeanNotOfRequiredTypeException(name, requiredType,
     151:                          bean.getClass());
     152:              }
     153:          }
     154:          return (T) bean;
     155:      }

    具体创建对象在createBean里面,来看看createBean:

       1:  protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
       2:              throws BeanCreationException {
       3:   
       4:          if (logger.isDebugEnabled()) {
       5:              logger.debug("Creating instance of bean '" + beanName + "'");
       6:          }
       7:          // Make sure bean class is actually resolved at this point.
       8:          resolveBeanClass(mbd, beanName);
       9:   
      10:          // Prepare method overrides.
      11:          try {
      12:              mbd.prepareMethodOverrides();
      13:          }
      14:          catch (BeanDefinitionValidationException ex) {
      15:              throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
      16:                      beanName, "Validation of method overrides failed", ex);
      17:          }
      18:   
      19:          try {
      20:              // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
      21:              Object bean = resolveBeforeInstantiation(beanName, mbd);
      22:              if (bean != null) {
      23:                  return bean;
      24:              }
      25:          }
      26:          catch (Throwable ex) {
      27:              throw new BeanCreationException(mbd.getResourceDescription(), beanName,
      28:                      "BeanPostProcessor before instantiation of bean failed", ex);
      29:          }
      30:          //这里是创建bean的调用
      31:          Object beanInstance = doCreateBean(beanName, mbd, args);
      32:          if (logger.isDebugEnabled()) {
      33:              logger.debug("Finished creating instance of bean '" + beanName + "'");
      34:          }
      35:          return beanInstance;
      36:      }

    又看doCreateBean,^_^遭不住啊。。

       1:  protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
       2:          // Instantiate the bean.
       3:          BeanWrapper instanceWrapper = null;
       4:          if (mbd.isSingleton()) {
       5:              instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
       6:          }
       7:          if (instanceWrapper == null) {
       8:              instanceWrapper = createBeanInstance(beanName, mbd, args);
       9:          }
      10:          .........
      11:          
      12:      }

    具体创建对象的方法是createBeanInstance:

       1:  protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
       2:          // Make sure bean class is actually resolved at this point.
       3:          Class beanClass = resolveBeanClass(mbd, beanName);
       4:   
       5:          if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
       6:              throw new BeanCreationException(mbd.getResourceDescription(), beanName,
       7:                      "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
       8:          }
       9:          //这里使用工厂方法对bean进行实例化
      10:          if (mbd.getFactoryMethodName() != null)  {
      11:              return instantiateUsingFactoryMethod(beanName, mbd, args);
      12:          }
      13:   
      14:          // Shortcut when re-creating the same bean...
      15:          boolean resolved = false;
      16:          boolean autowireNecessary = false;
      17:          if (args == null) {
      18:              synchronized (mbd.constructorArgumentLock) {
      19:                  if (mbd.resolvedConstructorOrFactoryMethod != null) {
      20:                      resolved = true;
      21:                      autowireNecessary = mbd.constructorArgumentsResolved;
      22:                  }
      23:              }
      24:          }
      25:          if (resolved) {
      26:              if (autowireNecessary) {
      27:                  return autowireConstructor(beanName, mbd, null, null);
      28:              }
      29:              else {
      30:                  return instantiateBean(beanName, mbd);
      31:              }
      32:          }
      33:   
      34:          // Need to determine the constructor...
      35:          //使用构造函数进行实例化
      36:          Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
      37:          if (ctors != null ||
      38:                  mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
      39:                  mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
      40:              return autowireConstructor(beanName, mbd, ctors, args);
      41:          }
      42:   
      43:          // No special handling: simply use no-arg constructor.
      44:          //使用默认的构造函数对bean进行实例化
      45:          return instantiateBean(beanName, mbd);
      46:      }

    来看看使用默认的构造函数对bean进行实例化的代码instantiateBean:

       1:  protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
       2:          try {
       3:              //使用默认的实例化策略对bean进行实例化,默认的实例化策略是CglibSubclassingInstantiationStrategy,也就是用cglib来对bean进行实例化
       4:              Object beanInstance;
       5:              final BeanFactory parent = this;
       6:              if (System.getSecurityManager() != null) {
       7:                  beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
       8:                      public Object run() {
       9:                          return getInstantiationStrategy().instantiate(mbd, beanName, parent);
      10:                      }
      11:                  }, getAccessControlContext());
      12:              }
      13:              else {
      14:                  beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
      15:              }
      16:              BeanWrapper bw = new BeanWrapperImpl(beanInstance);
      17:              initBeanWrapper(bw);
      18:              return bw;
      19:          }
      20:          catch (Throwable ex) {
      21:              throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
      22:          }
      23:      }

        这里用cglib对bean进行实例化,cglib是一个常用的字节码生成器的类库,它提供了一系列的API来提供java字节码生成和转换的功能,如果有兴趣可以查看cglib的使用文档。另外生成bean的策略还有很多种,这里只是选了最常用的方法来介绍。至此,bean实例创建过程就算完成了,然后通过populateBean方法将创建好的实例的依赖关系设置好,最终完成依赖注入的过程,由于篇幅关系这里就不详细列举了,populateBean方法可以在AbstractAutowireCapableBeanFactory中找到。

    小结

        自己对Spring IOC代码的学习暂时就到这里,要搞懂一个特性,确实需要花费很大的功夫,Spring代码量比较大,而且各个特性之间又有交叉,要梳理清楚不是件容易的事,不过回头来看自己还是有收获的,希望对看它的朋友也有一点收获。

  • 相关阅读:
    中国大概能用的NTPserver地址
    在asp.net mvc中使用PartialView返回部分HTML段
    我的学习笔记_Windows_HOOK编程 2009-12-03 11:19
    素数推断算法(高效率)
    No matching code signing identity found
    Android Bundle类
    D3D 练习小框架
    Python标准库:内置函数dict(iterable, **kwarg)
    微凉大大,教你一步一步在linux中正确的安装Xcache加速php。
    背景图片定位
  • 原文地址:https://www.cnblogs.com/leefreeman/p/2557760.html
Copyright © 2011-2022 走看看