首页 > 代码库 > Spring 源码学习(二)

Spring 源码学习(二)

容器概述

        IoC也被称作依赖注入(DI)。它是一个处理对象依赖项的过程,也就是将他们一起工作的其他的对象,只有通过构造参数、工厂方法参数或者(属性注入)通过构造参数实例化或通过工厂方法返回对象后再设置属性。当创建bean后,IoC容器再将这些依赖项注入进去。这个过程基本上是反转的,因此得名控制反转(IoC)。

下图是 IoC 的高级别视图

技术分享IoC容器利用Java的POJO类和配置元数据来生成 完全配置和可执行 的系统或应用程序。而Bean在Spring中就是POJO,也可以认为Bean就是对象。


设计实现

    接口设计

        Spring作为面向对象编程的集大成之作,我们直接从接口入手可以帮助我们更直观的了解Ioc容器的设计原理。

       注1:笔者未能找到最新的Spring 4.0 接口体系图片,所以接口体系用都是Spring-3.1 接口体系,而分析的Sping 源码版本为:Spring-4.3。其实本来打算重新绘制新的接口体系,但分析过程中也发现两者鲜有差异,所以为了节省时间,固延用了老的版本。

       注2:主要参考了《Spring技术内幕》第二版,但他的思维太过跳跃,所以我重新做了编排,还有就是很多细节部分参考了《Spring源码深度解析》,当然因为源码版本的不同,也会有些许差异。

下图描述了Ioc容器中的主要接口设计

技术分享这里主要是接口体系,而具体实现体系,比如DefaultListableBeanFactory就是为了实现ConfigurableBeanFactory,从而成为一个简单Ioc容器实现。与其他Ioc容器类似,XmlBeanFactory就是为了实现BeanFactory,但都是基于DefaultListableBeanFactory的基础做了扩展。同样的,ApplicationContext也一样。        

        从图中我们可以简要的做出以下分析:

            1.从接口BeanFactory到HierarchicalBeanFactory,再到ConfigurableBeanFactory,这是一条主要的BeanFactory设计路径。在这条接口设计路径中,BeanFactory,是一条主要的BeanFactory设计路径。在这条接口设计路径中,BeanFactory接口定义了基本的Ioc容器的规范。在这个接口定义中,包括了getBean()这样的Ioc容器的基本方法(通过这个方法可以从容器中取得Bean)。而HierarchicalBeanFactory接口在继承了BeanFactory的基本接口后,增加了getParentBeanFactory()的接口功能,使BeanFactory具备了双亲Ioc容器的管理功能。在接下来的ConfigurableBeanFactory接口中,主要定义了一些对BeanFactory的配置功能,比如通过setParentBeanFactory()设置双亲Ioc容器,通过addBeanPostProcessor()配置Bean后置处理器,等等。通过这些接口设计的叠加,定义了BeanFactory就是最简单的Ioc容器的基本功能。

            2.第二条接口设计主线是,以ApplicationContext作为核心的接口设计,这里涉及的主要接口设计有,从BeanFactory到ListableBeanFactory,再到ApplicationContext,再到我们常用的WebApplicationContext或者ConfigurableApplicationContext接口。我们常用的应用基本都是org.framework.context 包里的WebApplicationContext或者ConfigurableApplicationContext实现。在这个接口体现中,ListableBeanFactory和HierarchicalBeanFactory两个接口,连接BeanFactory接口定义和ApplicationContext应用的接口定义。在ListableBeanFactory接口中,细化了许多BeanFactory的接口功能,比如定义了getBeanDefinitionNames()接口方法;对于ApplicationContext接口,它通过继承MessageSource、ResourceLoader、ApplicationEventPublisher接口,在BeanFactory简单Ioc容器的基础上添加了许多对高级容器的特性支持。

            3.这个接口系统是以BeanFactoryApplicationContext为核心设计的,而BeanFactory是Ioc容器中最基本的接口,在ApplicationContext的设计中,一方面,可以看到它继承了BeanFactory接口体系中的ListableBeanFactory、AutowireCapableBeanFactory、HierarchicalBeanFactory等BeanFactory的接口,具备了BeanFactory Ioc容器的基本功能;另一方面,通过继承MessageSource、ResourceLoadr、ApplicationEventPublisher这些接口,BeanFactory为ApplicationContext赋予了更高级的Ioc容器特性。对于ApplicationContext而言,为了在Web环境中使用它,还设计了WebApplicationContext接口,而这个接口通过继承ThemeSource接口来扩充功能。

    BeanFactory容器的设计

        恩,我们与其写繁琐的文字,不如直接阅读代码来的直接的多。

最原始的容器:BeanFactory

package org.springframework.beans.factory;  import org.springframework.beans.BeansException; import org.springframework.core.ResolvableType;  /**  * BeanFactory作为最原始同时也最重要的Ioc容器,它主要的功能是为依赖注入 (DI) 提供支持, BeanFactory 和相关的接口,比如,BeanFactoryAware、   * DisposableBean、InitializingBean,仍旧保留在 Spring 中,主要目的是向后兼容已经存在的和那些 Spring 整合在一起的第三方框架。在 Spring 中  * ,有大量对 BeanFactory 接口的实现。其中,最常被使用的是 XmlBeanFactory 类。这个容器从一个 XML 文件中读取配置元数据,由这些元数据来生成一  * 个被配置化的系统或者应用。在资源宝贵的移动设备或者基于applet的应用当中, BeanFactory 会被优先选择。否则,一般使用的是 ApplicationContext  *   * 这里定义的只是一系列的接口方法,通过这一系列的BeanFactory接口,可以使用不同的Bean的检索方法很方便地从Ioc容器中得到需要的Bean,从而忽略具体  * 的Ioc容器的实现,从这个角度上看,这些检索方法代表的是最为基本的容器入口。  *  * @author Rod Johnson  * @author Juergen Hoeller  * @author Chris Beams  * @since 13 April 2001  */ public interface BeanFactory {  	/** 	 * 转定义符"&" 用来引用实例,或把它和工厂产生的Bean区分开,就是说,如果一个FactoryBean的名字为a,那么,&a会得到那个Factory 	 * 	 * FactoryBean和BeanFactory 是在Spring中使用最为频繁的类,它们在拼写上很相似。一个是Factory,也就是Ioc容器或对象工厂;一个 	 * 是Bean。在Spring中,所有的Bean都是由BeanFactory(也就是Ioc容器)来进行管理的。但对FactoryBean而言,这个Bean不是简单的Be 	 * an,而是一个能产生或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似。 	 */ 	String FACTORY_BEAN_PREFIX = "&";  	/** 	 * 五个不同形式的getBean方法,获取实例 	 * @param name 检索所用的Bean名 	 * @return Object(<T> T) 实例对象 	 * @throws BeansException 如果Bean不能取得 	 */ 	Object getBean(String name) throws BeansException; 	<T> getBean(String name, Class<T> requiredType) throws BeansException; 	<T> getBean(Class<T> requiredType) throws BeansException; 	Object getBean(String name, Object... args) throws BeansException; 	<T> getBean(Class<T> requiredType, Object... args) throws BeansException;  	/** 	 * 让用户判断容器是否含有指定名字的Bean. 	 * @param name 搜索所用的Bean名 	 * @return boolean 是否包含其中 	 */ 	boolean containsBean(String name);  	/** 	 * 查询指定名字的Bean是否是Singleton类型的Bean. 	 * 对于Singleton属性,可以在BeanDefinition指定. 	 * @param name 搜索所用的Bean名 	 * @return boolean 是否包是Singleton 	 * @throws NoSuchBeanDefinitionException 没有找到Bean 	 */ 	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;  	/** 	 * 查询指定名字的Bean是否是Prototype类型的。 	 * 与Singleton属性一样,可以在BeanDefinition指定. 	 * @param name 搜索所用的Bean名 	 * @return boolean 是否包是Prototype 	 * @throws NoSuchBeanDefinitionException 没有找到Bean 	 */ 	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;  	/** 	 * 查询指定了名字的Bean的Class类型是否是特定的Class类型. 	 * @param name 搜索所用的Bean名 	 * @param typeToMatch 匹配类型 	 * @return boolean 是否是特定类型 	 * @throws NoSuchBeanDefinitionException 没有找到Bean 	 */ 	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException; 	boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;  	/** 	 * 查询指定名字的Bean的Class类型. 	 * @param name 搜索所用的Bean名 	 * @return 指定的Bean或者null(没有找到合适的Bean) 	 * @throws NoSuchBeanDefinitionException 没有找到Bean 	 */ 	Class<?> getType(String name) throws NoSuchBeanDefinitionException;  	/** 	 * 查询指定了名字的Bean的所有别名,这些都是在BeanDefinition中定义的 	 * @param name 搜索所用的Bean名 	 * @return 指定名字的Bean的所有别名 或者一个空的数组 	 */ 	String[] getAliases(String name); }

容器的基础:XmlBeanFactory

package org.springframework.beans.factory.xml;  import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.core.io.Resource;  /**  * XmlBeanFactory是BeanFactory的最简单实现类  *   * XmlBeanFactory的功能是建立在DefaultListableBeanFactory这个基本容器的基础上的,并在这个基本容器的基础上实行了其他诸如  * XML读取的附加功能。XmlBeanFactory使用了DefaultListableBeanFactory作为基础类,DefaultListableBeanFactory是一个很重  * 要的Ioc实现,会在下一章进行重点论述。  *  * @author Rod Johnson  * @author Juergen Hoeller  * @author Chris Beams  * @since 15 April 2001  */ public class XmlBeanFactory extends DefaultListableBeanFactory { 	 	private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);  	/** 	 * 根据给定来源,创建一个XmlBeanFactory 	 * @param resource  Spring中对与外部资源的抽象,最常见的是对文件的抽象,特别是XML文件。而且Resource里面通常 	 * 是保存了Spring使用者的Bean定义,比如applicationContext.xml在被加载时,就会被抽象为Resource来处理。 	 * @throws BeansException 载入或者解析中发生错误 	 */ 	public XmlBeanFactory(Resource resource) throws BeansException { 		this(resource, null); 	}  	/** 	 * 根据给定来源和BeanFactory,创建一个XmlBeanFactory 	 * @param resource  Spring中对与外部资源的抽象,最常见的是对文件的抽象,特别是XML文件。而且Resource里面通常 	 * 是保存了Spring使用者的Bean定义,比如applicationContext.xml在被加载时,就会被抽象为Resource来处理。 	 * @param parentBeanFactory 父类的BeanFactory 	 * @throws BeansException 载入或者解析中发生错误 	 */ 	public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException { 		super(parentBeanFactory); 		this.reader.loadBeanDefinitions(resource); 	} }

最原始Ioc容器的使用

import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.ClassPathResource;  /**  * 最原始的Ioc容器使用,当然这也是Spring容器中效率最高的用法,比起繁琐的文字,阅读源码来得直观得多。  * 只需要写两行代码就行了,当然前提是要准备好Spring的配置文件  *  * @author  kay  * @since   1.0  */ @SuppressWarnings("deprecation") public class SimpleBeanFactory { 	public static void main(String[] args) { 		ClassPathResource resource = new ClassPathResource("applicationContext.xml"); 		BeanFactory beanFactory = new XmlBeanFactory(resource);		 		Message message = beanFactory.getBean("message", Message.class);    //Message是自己写的测试类 		message.printMessage(); 	} }

下面是XmlBeanFactory在使用过程中涉及到的类的关系图

 技术分享图中空心三角加实线代表继承、空心三角加虚线代表实现、实线箭头加虚线代表依赖、实心菱形加实线代表组合。这里用下划线代表接口,没有下划线的代表类。

        看着非常复杂是吧,不要紧,我们以代码来做简要说明

import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.core.io.ClassPathResource;  /**  * 这是与SimpleBeanFactory等效的编程式使用Ioc容器  *   * 从中我也可以看到一些Ioc的基本原理,同时也揭示了Ioc实现中的一些关键类:如Resource、DefaultListableBeanFactory  * 以及BeanDefinitionReader等等  *  * @author  kay  * @since   1.0  */ public class ProgramBeanFactory{ 	public static void main(String[] args) { 		ClassPathResource resource = new ClassPathResource("applicationContext.xml"); 		DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); 		XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory); 		reader.loadBeanDefinitions(resource); 		Message message = factory.getBean("message", Message.class);	//Message是自己写的测试类 		message.printMessage(); 	} }

        以上,可以简单说明我们在使用Ioc容器时,需要如下几个步骤:

            1,创建Ioc配置文件的抽象资源,这个抽象资源包含了BeanDefinition的定义信息。

            2,创建一个BeanFactory,这里使用了DefaultListableBeanFactory。

            3,创建一个载入BeanDefinition的读取器,这里使用XmlBeanDefinitionReader来载入XML文件形式的BeanDefinition,通过一个回调配置给BeanFactory。

            4,从定义好的资源位置读入配置信息,具体的解析过程由XmlBeanDefinitionReader来完成。完成整个载入和注册Bean定义之后,需要的Ioc容器就建立起来了。这个时候我们就可以直接使用Ioc容器了。

        恩,以下是Bean在使用过程中的解析、注册时效图,我们来一步一步分析,它是怎么在源码中实现的。

Bean的解析、注册详细过程分析

技术分享


配置文件封装类:ClassPathResource

        在Java中,将不同来源的资源抽象成URL,通过注册不同的handler(URLStreamHandler)来处理不同来源间的资源读取逻辑。而URL中却没有提供一些基本方法来实现自己的抽象结构。因而Spring对其内部资源,使用了自己的抽象结构:Resource接口来封装。而ClassPathResource实现类即是对Resource的实现。

技术分享

Resource接口体系

技术分享资源的原始接口为Resource,它继承自InputStreamResource,实现了其getInstream方法,这样所有的资源就是通过该方法来获取输入流的。对于资源的加载,也实现了统一,定义了一个资源加载顶级接口ResourceLoader,它默认的加载就是DefaultResourceLoader。

InputStreamSource接口

package org.springframework.core.io;  import java.io.IOException; import java.io.InputStream;  /**  * InputStreamSource 封装任何能返回InputStream的类,比如File、Classpath下的资源和Byte Array等  *  * @author Juergen Hoeller  * @since 20.01.2004  */ public interface InputStreamSource { 	 	/** 	 * 返回InputStream的类,比如File、Classpath下的资源和Byte Array等 	 * @return InputStream 返回一个新的InputStream的对象 	 * @throws IOException 如果资源不能打开则抛出异常 	 */ 	InputStream getInputStream() throws IOException; }

Resource接口

package org.springframework.core.io;  import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URL;  /**  * Resource接口抽象了所有Spring内部使用到的底层资源:File、URL、Classpath等。  * 同时,对于来源不同的资源文件,Resource也有不同实现:文件(FileSystemResource)、Classpath资源(ClassPathResource)、  * URL资源(UrlResource)、InputStream资源(InputStreamResource)、Byte数组(ByteArrayResource)等等。  *  * @author Juergen Hoeller  * @since 28.12.2003  */ public interface Resource extends InputStreamSource {  	/** 	 * 判断资源是否存在 	 * @return boolean 是否存在 	 */ 	boolean exists();  	/** 	 * 判断资源是否可读 	 * @return boolean 是否可读 	 */ 	boolean isReadable();  	/** 	 * 是否处于开启状态 	 * @return boolean 是否开启 	 */ 	boolean isOpen();  	/** 	 * 得到URL类型资源,用于资源转换 	 * @return URL 得到URL类型 	 * @throws IOException 如果资源不能打开则抛出异常 	 */ 	URL getURL() throws IOException;  	/** 	 * 得到URI类型资源,用于资源转换 	 * @return URI 得到URI类型 	 * @throws IOException 如果资源不能打开则抛出异常 	 */ 	URI getURI() throws IOException;  	/** 	 * 得到File类型资源,用于资源转换 	 * @return File 得到File类型 	 * @throws IOException 如果资源不能打开则抛出异常 	 */ 	File getFile() throws IOException;  	/** 	 * 获取资源长度 	 * @return long 资源长度 	 * @throws IOException 如果资源不能打开则抛出异常 	 */ 	long contentLength() throws IOException;  	/** 	 * 获取lastModified属性 	 * @return long 获取lastModified 	 * @throws IOException 如果资源不能打开则抛出异常 	 */ 	long lastModified() throws IOException;  	/** 	 * 创建一个相对的资源方法 	 * @param relativePath 相对路径 	 * @return Resource 返回一个新的资源 	 * @throws IOException 如果资源不能打开则抛出异常 	 */ 	Resource createRelative(String relativePath) throws IOException;  	/** 	 * 获取文件名称 	 * @return String 文件名称或者null 	 */ 	String getFilename();  	/** 	 * 得到错误处理信息,主要用于错误处理的信息打印 	 * @return String 错误资源信息 	 */ 	String getDescription(); }

根据上面的推论,我们可以理解为这两段代码,在某种程度来说是完全等效的

ClassPathResource resource = new ClassPathResource("applicationContext.xml"); InputStream inputStream = resource.getInputStream();
Resource resource = new ClassPathResource("applicationContext.xml"); InputStream inputStream = resource.getInputStream();

这样得到InputStream以后,我们可以拿来用了。值得一提是,不同的实现有不同的调用方法,这里就不展开了。下面是ClassPathResource的具体实现:

ClassPathResource.java

private final String path;  private ClassLoader classLoader;  public ClassPathResource(String path) {         this(path, (ClassLoader) null);    //这里是入口,直接跳入下面的ClassPathResource(String path, ClassLoader classLoader) 中 }  public ClassPathResource(String path, ClassLoader classLoader) {         Assert.notNull(path, "Path must not be null");         String pathToUse = StringUtils.cleanPath(path);         if (pathToUse.startsWith("/")) {                 pathToUse = pathToUse.substring(1);         }         this.path = pathToUse;         this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader()); }

忽略给定接口:DefaultListableBeanFactory

        这里 DefaultListableBeanFactory 所起到的是忽略给定接口自动装配功能。简单来说,一般 bean 中的功能 A 如果没有初始化,那么Spring会自动初始化A,这是Spring的一个特性。但当某些特殊情况时,B不会初始化,比如:B已经实现了 BeanNameAware接口。可以说,就是通过其他方式来解析依赖,类似于 BeanFactory 的 BeanFactoryAware。下面是具体实现:

技术分享

DefaultListableBeanFactory.java

public DefaultListableBeanFactory() {         super();    //直接指向下面 AbstractAutowireCapableBeanFactory() }

AbstractAutowireCapableBeanFactory.java

private final Set<Class<?>> ignoredDependencyInterfaces = new HashSet<Class<?>>();  public AbstractAutowireCapableBeanFactory() {         super();         ignoreDependencyInterface(BeanNameAware.class);    //忽略给定接口自动装配功能的主要实现处         ignoreDependencyInterface(BeanFactoryAware.class);         ignoreDependencyInterface(BeanClassLoaderAware.class); }  public void ignoreDependencyInterface(Class<?> ifc) {         this.ignoredDependencyInterfaces.add(ifc); }

BeanDefinition的载入、解析和注册:XmlBeanDefinitionReader

        这里是BeanDefinition真正被载入的地方。这个载入过程就是把用户定义好的Bean表示成Ioc容器内部的数据结构,当然这个数据结构就是BeanDefinition。而BeanDefinition实际上就是POJO对象在Ioc容器中的抽象,通过这个BeanDefinition定义的数据结构,让Ioc容器能够对POJO对象也就是Bean进行管理。

技术分享

XmlBeanDefinitionReader.java

public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {         //loadBeanDefinitions的具体实现,而EncodedResource主要用于对资源文件的处理,而其主要实现方法getReader()在下面有所介绍         return loadBeanDefinitions(new EncodedResource(resource));     }  public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {         Assert.notNull(encodedResource, "EncodedResource must not be null");         if (logger.isInfoEnabled()) {                 logger.info("Loading XML bean definitions from " + encodedResource.getResource());         }          //通过属性来记录已经加载的资源         Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();         if (currentResources == null) {                 currentResources = new HashSet<EncodedResource>(4);                 this.resourcesCurrentlyBeingLoaded.set(currentResources);         }         if (!currentResources.add(encodedResource)) {                 throw new BeanDefinitionStoreException(                         "Detected cyclic loading of " + encodedResource + " - check your import definitions!");         } 	         // 调用DefaultResourceLoader的getResources方法完成具体的Resource定位          try {                 //从EncodedResource中获取已经封装的Resource对象并再次从Resource中获取inputStream                  InputStream inputStream = encodedResource.getResource().getInputStream();                 try {                         InputSource inputSource = new InputSource(inputStream);                         if (encodedResource.getEncoding() != null) {                                 inputSource.setEncoding(encodedResource.getEncoding());                         }                         return doLoadBeanDefinitions(inputSource, encodedResource.getResource());    //真正的逻辑核心                 }                 finally {                         inputStream.close();    //关闭inputStream                 }         }         catch (IOException ex) {                 throw new BeanDefinitionStoreException(                                 "IOException parsing XML document from " + encodedResource.getResource(), ex);         }         finally {                 currentResources.remove(encodedResource);                 if (currentResources.isEmpty()) {                         this.resourcesCurrentlyBeingLoaded.remove();                 }         } }  /**  * 真正的核心处理部分  * 如果不考虑冗余的代码,其实只做三件事:  *  1.获取XML文件的验证模式  *  2.加载XML,并获取Document.  *  3.返回的Document,注册Bean  */ protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)             throws BeanDefinitionStoreException {         try {                 // 取得XML文件的Document对象, 这个解析过程由DefaultDocumentLoader完成                   Document doc = doLoadDocument(inputSource, resource);                     // 启动对BeanDefinition解析的详细过程, 解析过程中会使用到Spring的Bean配置规则                 return registerBeanDefinitions(doc, resource);         }         catch (BeanDefinitionStoreException ex) {                 throw ex;         }         catch (SAXParseException ex) {                 throw new XmlBeanDefinitionStoreException(resource.getDescription(),                                 "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);         }         catch (SAXException ex) {                 throw new XmlBeanDefinitionStoreException(resource.getDescription(),                                 "XML document from " + resource + " is invalid", ex);         }         catch (ParserConfigurationException ex) {                 throw new BeanDefinitionStoreException(resource.getDescription(),                                 "Parser configuration exception parsing XML from " + resource, ex);         }         catch (IOException ex) {                 throw new BeanDefinitionStoreException(resource.getDescription(),                                 "IOException parsing XML document from " + resource, ex);         }         catch (Throwable ex) {                 throw new BeanDefinitionStoreException(resource.getDescription(),                                 "Unexpected exception parsing XML document from " + resource, ex);         } }  protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {         //loadDocument直接用于注册Document,getValidationModeForResource方法作用于XML的加载         return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,                 getValidationModeForResource(resource), isNamespaceAware()); }

EncodedResource.java

public Reader getReader() throws IOException {         if (this.charset != null) {                 return new InputStreamReader(this.resource.getInputStream(), this.charset);         }         else if (this.encoding != null) {                 return new InputStreamReader(this.resource.getInputStream(), this.encoding);         }         else {                 return new InputStreamReader(this.resource.getInputStream());         } }

XML文件验证

        获取XML文件的验证模式,一般分为两步:首先,是XML文件验证,然后,就是验证模式的读取。

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?> <beans 	xmlns="http://www.springframework.org/schema/beans" 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 	xmlns:p="http://www.springframework.org/schema/p" 	xsi:schemaLocation="http://www.springframework.org/schema/beans  		http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">    //XSD方式,用于验证XML文件的正确性  	<bean id="..">...</bean> </beans>

        常用的XML文件验证方法有两种:DTD和XSD,DTD现在基本不用了,而上图中的spring-beans-4.0.xsd对应在源码中的org.springframework.beans.factory.xml.spring-beans-4.0.xsd。这里就不具体介绍了,有兴趣可以自己去研究。

加载XML

        Spring中通过getValidationModeForResource方法来获取上面讲的DTD和XSD验证方法,不过就编程而言,还是非常简单的。只是要特别需要注意的是自动检测验证模式的实现。

技术分享

XmlBeanDefinitionReader.java

public static final int VALIDATION_AUTO = XmlValidationModeDetector.VALIDATION_AUTO;  public static final int VALIDATION_XSD = XmlValidationModeDetector.VALIDATION_XSD;  protected int getValidationModeForResource(Resource resource) {         int validationModeToUse = getValidationMode();         //如果手动指定了验证模式则使用指定的验证模式         if (validationModeToUse != VALIDATION_AUTO) {                 return validationModeToUse;         }         //如果没有指定,则自动检测         int detectedMode = detectValidationMode(resource);    //自动检测主要是在detectValidationMode(Resource resource)完成的         if (detectedMode != VALIDATION_AUTO) {                 return detectedMode;         }         return VALIDATION_XSD; }  protected int detectValidationMode(Resource resource) {         if (resource.isOpen()) {                 throw new BeanDefinitionStoreException(                         "Passed-in Resource [" + resource + "] contains an open stream: " +                         "cannot determine validation mode automatically. Either pass in a Resource " +                         "that is able to create fresh streams, or explicitly specify the validationMode " +                         "on your XmlBeanDefinitionReader instance.");         }          InputStream inputStream;         try {                 inputStream = resource.getInputStream();         }         catch (IOException ex) {                 throw new BeanDefinitionStoreException(                         "Unable to determine validation mode for [" + resource + "]: cannot open InputStream. " +                         "Did you attempt to load directly from a SAX InputSource without specifying the " +                         "validationMode on your XmlBeanDefinitionReader instance?", ex);         }          try {                 return this.validationModeDetector.detectValidationMode(inputStream);    //自动检测则是给detectValidationMode完成的         }         catch (IOException ex) {                 throw new BeanDefinitionStoreException("Unable to determine validation mode for [" +                         resource + "]: an error occurred whilst reading from the InputStream.", ex);         } }

XmlValidationModeDetector.java

public static final int VALIDATION_NONE = 0;  public static final int VALIDATION_AUTO = 1;  public static final int VALIDATION_DTD = 2;  public static final int VALIDATION_XSD = 3;  private static final String DOCTYPE = "DOCTYPE";  public int detectValidationMode(InputStream inputStream) throws IOException {         BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));         try {                 boolean isDtdValidated = false;                 String content;                 while ((content = reader.readLine()) != null) {                         content = consumeCommentTokens(content);                         //空或注释略过                         if (this.inComment || !StringUtils.hasText(content)) {                                 continue;                         }                         if (hasDoctype(content)) {                                 isDtdValidated = true;                                 break;                         }                         //读取<前的信息                         if (hasOpeningTag(content)) {                                 break;                         }                 }                 return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);         }         catch (CharConversionException ex) {                 return VALIDATION_AUTO;         }         finally {                 reader.close();         } }  private boolean hasDoctype(String content) {         return content.contains(DOCTYPE); }  private boolean hasOpeningTag(String content) {         if (this.inComment) {                 return false;         }         int openTagIndex = content.indexOf(‘<‘);         return (openTagIndex > -1 && (content.length() > openTagIndex + 1) &&                 Character.isLetter(content.charAt(openTagIndex + 1))); }

获取Document

        通过以上的验证准备,就可以进行加载了,而XmlBeanDefinitionReader并没有自己去完成,而是给了DocumentLoader接口去完成的,而他调用的是DefaultDocumentLoader.loadDocument方法。loadDocument没有太多可描述的。所以。。。

技术分享

XmlBeanDefinitionReader.java

private DocumentLoader documentLoader = new DefaultDocumentLoader();  //EntityResolver主要用于处理前面提到的DTD方法的处理 protected EntityResolver getEntityResolver() {         if (this.entityResolver == null) {                 ResourceLoader resourceLoader = getResourceLoader();                 if (resourceLoader != null) {                         this.entityResolver = new ResourceEntityResolver(resourceLoader);                 }                 else {                         this.entityResolver = new DelegatingEntityResolver(getBeanClassLoader());                 }         }         return this.entityResolver; }

DefaultDocumentLoader.java

public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,                 ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {          DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);         if (logger.isDebugEnabled()) {                 logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");         }         DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);         return builder.parse(inputSource); }

BeanDefinition的解析

        BeanDefinition载入过程其实就是把定义的BeanDefinition在IoC容器中转化为一个Spring内部表示的数据结构的过程。IoC容器对Bean的管理和依赖注入的实现,都是通过对其持有的BeanDefinition进行各种相关的操作来完成的。这些BeanDefinition数据在IoC容器中通过一个HashMap来维护。

技术分享

XmlBeanDefinitionReader.java

private Class<?> documentReaderClass = DefaultBeanDefinitionDocumentReader.class;     public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {         // 得到BeanDefinitionDocumentReader来对XML的BeanDefinition进行解析          BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();         int countBefore = getRegistry().getBeanDefinitionCount();                  // 具体的解析过程在BeanDefinitionDocumentReader的registerBeanDefinitions方法中完成         documentReader.registerBeanDefinitions(doc, createReaderContext(resource));         return getRegistry().getBeanDefinitionCount() - countBefore;     }  protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {         return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));     }

DefaultBeanDefinitionDocumentReader.java

public static final String BEAN_ELEMENT = BeanDefinitionParserDelegate.BEAN_ELEMENT;  public static final String NESTED_BEANS_ELEMENT = "beans";  public static final String ALIAS_ELEMENT = "alias";  public static final String ALIAS_ATTRIBUTE = "alias";  public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext{         this.readerContext = readerContext;         logger.debug("Loading bean definitions");         Element root = doc.getDocumentElement();    // 获得Document的根元素         doRegisterBeanDefinitions(root); }  protected void doRegisterBeanDefinitions(Element root{         BeanDefinitionParserDelegate parent = this.delegate;         this.delegate = createDelegate(getReaderContext(), root, parent);          if (this.delegate.isDefaultNamespace(root)) {                 String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);                 if (StringUtils.hasText(profileSpec)) {                         String[] specifiedProfiles = StringUtils.tokenizeToStringArray(                                 profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);                         if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {                                 return;                         }                 }         }          preProcessXml(root);    // 解析Bean定义之前, 增强解析过程的可扩展性          parseBeanDefinitions(root, this.delegate);    // 从Document的根元素开始进行Bean定义的Document对象           postProcessXml(root);    // 解析Bean定义之前, 增强解析过程的可扩展性            this.delegate = parent; }  protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate{         if (delegate.isDefaultNamespace(root)) {                 NodeList nl = root.getChildNodes();    // 获取Document对象根元素的所有子节点并循环解析                   for (int i = 0; i < nl.getLength(); i++) {                         Node node = nl.item(i);                         if (node instanceof Element) {                                 Element ele = (Element) node;                                 if (delegate.isDefaultNamespace(ele)) {                                         parseDefaultElement(ele, delegate);    // 解析Spring的Bean规则默认元素节点                                  }                                 else {                                         delegate.parseCustomElement(ele);    // 解析自定义元素节点                                  }                         }                 }         }         else {                 delegate.parseCustomElement(root);    // 解析自定义元素根节点           } }  private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate{         if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {    // 解析import元素                 importBeanDefinitionResource(ele);         }         else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {    // 解析alias元素                 processAliasRegistration(ele);         }         else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {    // 解析bean元素                 processBeanDefinition(ele, delegate);         }         else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {    // 解析内嵌beans元素, 作为根节点递归解析                 doRegisterBeanDefinitions(ele);         } }

        恩,直接从代码就可以看出,Spring首先获取Document的根元素(一般为<beans/>),然后取得根元素所有的子节点并循环解析这些子节点;如果子节点在Spring默认的命名空间内,则按照Spring Bean定义规则来解析,否则按照自定义的节点解析。在按照Spring Bean定义规则进行解析的parseDefaultElement方法中,完成了对<import/>、<alias/>、<bean/>、<beans/>等元素的解析。

        为了使文章简短一点,在这里只关注Spring对<bean>元素的解析过程,其它的解析过程不再分析。

DefaultBeanDefinitionDocumentReader.java

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate{         // 具体的解析委托给BeanDefinitionParserDelegate来完成           // BeanDefinitionHolder是BeanDefinition的封装类, 封装了BeanDefinition、Bean的名字和别名, 用它来完成向IoC容器注册.         BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);         if (bdHolder != null) {                 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);                 try {                         BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());                 }                 catch (BeanDefinitionStoreException ex) {                         getReaderContext().error("Failed to register bean definition with name ‘" +                                 bdHolder.getBeanName() + "‘", ele, ex);                 }                 getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));         } }

BeanDefinitionParserDelegate.java

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {         return parseBeanDefinitionElement(ele, null); } 	 public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {         // 解析Bean定义资源文件中的<Bean>元素,主要处理<Bean>元素的id,name和aliase属性         String id = ele.getAttribute(ID_ATTRIBUTE);         String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);          List<String> aliases = new ArrayList<String>();         if (StringUtils.hasLength(nameAttr)) {                 String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);                 aliases.addAll(Arrays.asList(nameArr));         }          String beanName = id;         // 如果<Bean>元素中没有配置id属性时, 将别名中的第一个值赋值给beanName         if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {                 beanName = aliases.remove(0);                 if (logger.isDebugEnabled()) {                         logger.debug("No XML ‘id‘ specified - using ‘" + beanName +                                 "‘ as bean name and " + aliases + " as aliases");                 }         }          if (containingBean == null) {                 checkNameUniqueness(beanName, aliases, ele);         }          // 对<bean>元素进行详细解析         AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);         if (beanDefinition != null) {                 if (!StringUtils.hasText(beanName)) {                         try {                                 if (containingBean != null) {                                         beanName = BeanDefinitionReaderUtils.generateBeanName(                                         beanDefinition, this.readerContext.getRegistry(), true);                                 }                                 else {                                         beanName = this.readerContext.generateBeanName(beanDefinition);                                         //为解析的Bean使用别名注册时, 为了向后兼容(Spring1.2/2.0给别名添加类名后缀)                                         String beanClassName = beanDefinition.getBeanClassName();                                         if (beanClassName != null &&                                                 beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&                                                 !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {                                                         aliases.add(beanClassName);                                         }                                 }                                 if (logger.isDebugEnabled()) {                                         logger.debug("Neither XML ‘id‘ nor ‘name‘ specified - " +                                                 "using generated bean name [" + beanName + "]");                                 }                         }                         catch (Exception ex) {                                 error(ex.getMessage(), ele);                                 return null;                         }                 }                 String[] aliasesArray = StringUtils.toStringArray(aliases);                 return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);         }          return null; } 	 public AbstractBeanDefinition parseBeanDefinitionElement(                 Element ele, String beanName, BeanDefinition containingBean) {          this.parseState.push(new BeanEntry(beanName));          // 这里只读取<Bean>元素中配置的class名字, 然后载入到BeanDefinition中去             // 只是记录配置的class名字, 并不实例化, 对象的实例化在依赖注入时完成           String className = null;         if (ele.hasAttribute(CLASS_ATTRIBUTE)) {                 className = ele.getAttribute(CLASS_ATTRIBUTE).trim();         }          try {                 String parent = null;                 if (ele.hasAttribute(PARENT_ATTRIBUTE)) {                         parent = ele.getAttribute(PARENT_ATTRIBUTE);                 }                 // 根据<Bean>元素配置的class名称和parent属性值创建BeanDefinition, 为载入Bean定义信息做准备                   AbstractBeanDefinition bd = createBeanDefinition(className, parent);                                  // 对当前<Bean>元素中配置的一些属性进行解析, 如singleton、abstract等                   parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);                 bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));                                  // 对<Bean>元素的meta(元数据)、lookup-method、replaced-method等子元素进行解析                   parseMetaElements(ele, bd);                 parseLookupOverrideSubElements(ele, bd.getMethodOverrides());                 parseReplacedMethodSubElements(ele, bd.getMethodOverrides());                                  parseConstructorArgElements(ele, bd);    // 解析<Bean>元素的构造方法参数                   parsePropertyElements(ele, bd);    // 解析<Bean>元素的<property>设置                   parseQualifierElements(ele, bd);                  bd.setResource(this.readerContext.getResource());                 bd.setSource(extractSource(ele));                  return bd;         }         catch (ClassNotFoundException ex) {                 error("Bean class [" + className + "] not found", ele, ex);         }         catch (NoClassDefFoundError err) {                 error("Class that bean class [" + className + "] depends on not found", ele, err);         }         catch (Throwable ex) {                 error("Unexpected failure during bean definition parsing", ele, ex);         }         finally {                 this.parseState.pop();         }          return null; }

        <bean>元素解析已经完了,而<bean>元素属性及其子元素的解析顺序为:1,解析<bean>元素的属性。2,解析<description>子元素。3,解析<meta>子元素。4,解析<lookup-method/>子元素。5,解析<replaced-method>子元素。6,解析<constructor-arg>子元素。7,解析<property>子元素。8,解析<qualifier>子元素。解析过程中像<meta>、<qualifier>等子元素都很少使用,而下面就直接解析最常用的子元素<property>子元素。

BeanDefinitionParserDelegate.java

public void parsePropertyElements(Element beanEle, BeanDefinition bd) {         // 遍历<bean>所有的子元素         NodeList nl = beanEle.getChildNodes();         for (int i = 0; i < nl.getLength(); i++) {                 Node node = nl.item(i);                 if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {                         parsePropertyElement((Element) node, bd);    // 如果是<property>元素, 则对其进行解析                 }         } }  public void parsePropertyElement(Element ele, BeanDefinition bd) {         String propertyName = ele.getAttribute(NAME_ATTRIBUTE);    // <property>元素name属性         if (!StringUtils.hasLength(propertyName)) {                 error("Tag ‘property‘ must have a ‘name‘ attribute", ele);                 return;         }         this.parseState.push(new PropertyEntry(propertyName));         try {                 // 如果同一个Bean中已经有相同名字的<property>存在, 直接返回                   // 也就是说, 如果一个Bean中定义了两个名字一样的<property>元素, 只有第一个起作用.                 if (bd.getPropertyValues().contains(propertyName)) {                         error("Multiple ‘property‘ definitions for property ‘" + propertyName + "‘", ele);                         return;                 }                 // 解析<property>元素, 返回的对象对应<property>元素的解析结果, 最终封装到PropertyValue中, 并设置到BeanDefinitionHolder中                  Object val = parsePropertyValue(ele, bd, propertyName);                 PropertyValue pv = new PropertyValue(propertyName, val);                 parseMetaElements(ele, pv);                 pv.setSource(extractSource(ele));                 bd.getPropertyValues().addPropertyValue(pv);         }         finally {                 this.parseState.pop();         } }  public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {         String elementName = (propertyName != null) ?                         "<property> element for property ‘" + propertyName + "‘" :                         "<constructor-arg> element";          // 检查<property>的子元素, 只能是ref, value, list等(description, meta除外)其中的一个.          NodeList nl = ele.getChildNodes();         Element subElement = null;         for (int i = 0; i < nl.getLength(); i++) {                 Node node = nl.item(i);                 if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&                         !nodeNameEquals(node, META_ELEMENT)) {                         if (subElement != null) {                                 error(elementName + " must not contain more than one sub-element", ele);                         }                         else {                                 subElement = (Element) node;                         }                 }         }          // 判断property元素是否含有ref和value属性, 不允许既有ref又有value属性.           // 同时也不允许ref和value属性其中一个与子元素共存.           boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);         boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);         if ((hasRefAttribute && hasValueAttribute) ||                 ((hasRefAttribute || hasValueAttribute) && subElement != null)) {                 error(elementName +                          " is only allowed to contain either ‘ref‘ attribute OR ‘value‘ attribute OR sub-element", ele);         }          // 如果属性是ref属性, 创建一个ref的数据对象RuntimeBeanReference, 封装了ref信息          if (hasRefAttribute) {                 String refName = ele.getAttribute(REF_ATTRIBUTE);                 if (!StringUtils.hasText(refName)) {                         error(elementName + " contains empty ‘ref‘ attribute", ele);                 }                 RuntimeBeanReference ref = new RuntimeBeanReference(refName);                 ref.setSource(extractSource(ele));                 return ref;         }         else if (hasValueAttribute) {    // 如果属性是value属性, 创建一个数据对象TypedStringValue, 封装了value信息                  TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));                 valueHolder.setSource(extractSource(ele));                 return valueHolder;         }         else if (subElement != null) {    // 如果当前<property>元素还有子元素                  return parsePropertySubElement(subElement, bd);         }         else {    // propery元素既没有ref或value属性, 也没有子元素, 解析出错返回null                   error(elementName + " must specify a ref or value", ele);                 return null;         } }

        恩,其实<property>元素还有子元素。

BeanDefinitionParserDelegate.java

public Object parsePropertySubElement(Element ele, BeanDefinition bd) {         return parsePropertySubElement(ele, bd, null); }  public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {         if (!isDefaultNamespace(ele)) {    // 如果子元素没有使用Spring默认命名空间, 则使用用户自定义的规则解析                   return parseNestedCustomElement(ele, bd);         }         else if (nodeNameEquals(ele, BEAN_ELEMENT)) {    // 如果子元素是bean元素, 则使用解析<bean>元素的方法解析                   BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);                 if (nestedBd != null) {                         nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);                 }                 return nestedBd;         }         else if (nodeNameEquals(ele, REF_ELEMENT)) {    // 如果子元素是ref, 有且只能有bean、local和parent 3个属性中的一个                 String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);    // 引用普通任意的bean                 boolean toParent = false;                 if (!StringUtils.hasLength(refName)) {                         refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE);    // 引用同一个XML配置文件中的bean                          if (!StringUtils.hasLength(refName)) {                                 refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);    // 引用父容器中的bean                                  toParent = true;                                 if (!StringUtils.hasLength(refName)) {                                         error("‘bean‘, ‘local‘ or ‘parent‘ is required for <ref> element", ele);                                         return null;                                 }                         }                 }                 // ref元素没有bean、local和parent 3个属性中的一个, 返回null.                  if (!StringUtils.hasText(refName)) {                         error("<ref> element contains empty target attribute", ele);                         return null;                 }                 RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);                 ref.setSource(extractSource(ele));                 return ref;         }         else if (nodeNameEquals(ele, IDREF_ELEMENT)) {    // 如果子元素是<idref>, 使用解析idref元素的方法解析                 return parseIdRefElement(ele);         }         else if (nodeNameEquals(ele, VALUE_ELEMENT)) {    // 子元素是<value>                   return parseValueElement(ele, defaultValueType);         }         else if (nodeNameEquals(ele, NULL_ELEMENT)) {    // 子元素是<null>                   TypedStringValue nullHolder = new TypedStringValue(null);                 nullHolder.setSource(extractSource(ele));                 return nullHolder;         }         else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {    // 子元素是<array>                  return parseArrayElement(ele, bd);         }         else if (nodeNameEquals(ele, LIST_ELEMENT)) {    // 子元素是<list>                  return parseListElement(ele, bd);         }         else if (nodeNameEquals(ele, SET_ELEMENT)) {    // 子元素是<set>                   return parseSetElement(ele, bd);         }         else if (nodeNameEquals(ele, MAP_ELEMENT)) {    // 子元素是<map>                   return parseMapElement(ele, bd);         }         else if (nodeNameEquals(ele, PROPS_ELEMENT)) {    // 子元素是<props>                   return parsePropsElement(ele);         }         else {    // 以上都不是, 说明配置错误, 返回null.                   error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);                 return null;         } }

        我们以<list>子元素进行分析

BeanDefinitionParserDelegate.java

public List<Object> parseListElement(Element collectionEle, BeanDefinition bd) {         // 获取<list>元素中的value-type属性, 即集合元素的数据类型         String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE);         NodeList nl = collectionEle.getChildNodes();    // <list>元素所有子节点         ManagedList<Object> target = new ManagedList<Object>(nl.getLength());         target.setSource(extractSource(collectionEle));         target.setElementTypeName(defaultElementType);         target.setMergeEnabled(parseMergeAttribute(collectionEle));         parseCollectionElements(nl, target, bd, defaultElementType);    // 具体解析List元素中的值         return target; }  protected void parseCollectionElements(         NodeList elementNodes, Collection<Object> target, BeanDefinition bd, String defaultElementType) {         // 遍历集合所有子节点         for (int i = 0; i < elementNodes.getLength(); i++) {                 Node node = elementNodes.item(i);                 if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT)) {                         // 如果子节点是Element且不是<description>节点, 则添加进ManagedList.                           // 同时触发对下层子元素的解析, 递归调用.                         target.add(parsePropertySubElement((Element) node, bd, defaultElementType));                 }         } }

        不好意思,没子类了,BeanDefinition就被载入到IoC容器后,就可以在容器中建立了数据映射了。剩下的就是BeanDefinition注册了。

BeanDefinition的注册

        BeanDefinition信息已经在IoC容器内部建立起了自己的数据结构,但这些数据还不能供IoC容器直接使用,需要在IoC容器中对这些BeanDefinition数据进行注册。不同的解析元素解析方式都不同但最后的注册的方式是一样的,我们还是以上面提到的<bean>元素为例。

技术分享

BeanDefinitionReaderUtils.java

public static void registerBeanDefinition(         BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)                     throws BeanDefinitionStoreException {          String beanName = definitionHolder.getBeanName();         // 向IoC容器注册BeanDefinition         registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());          // 如果解析的BeanDefinition有别名, 向容器为其注册别名.           String[] aliases = definitionHolder.getAliases();         if (aliases != null) {                 for (String alias : aliases) {                         registry.registerAlias(beanName, alias);                 }         } }

        上面的registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition())是调用的注册位置,而BeanDefinitionRegistry仅仅是一个接口,而真正实现它的却是最原本的DefaultListableBeanFactory.registerBeanDefinition方法,值得一提的是DefaultListableBeanFactory.registerBeanDefinition方法在最新的Spring 4.0中稳定性方面做了很大改善

技术分享

DefaultListableBeanFactory.java

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");          // 对解析得到的BeanDefinition校验         if (beanDefinition instanceof AbstractBeanDefinition) {                 try {                         ((AbstractBeanDefinition) beanDefinition).validate();                 }                 catch (BeanDefinitionValidationException ex) {                         throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,                                 "Validation of bean definition failed", ex);                 }         }          BeanDefinition oldBeanDefinition;          oldBeanDefinition = this.beanDefinitionMap.get(beanName);         if (oldBeanDefinition != null) {                 if (!isAllowBeanDefinitionOverriding()) {                         throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,                                 "Cannot register bean definition [" + beanDefinition + "] for bean ‘" + beanName +                                 "‘: There is already [" + oldBeanDefinition + "] bound.");                 }                 else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {                         if (this.logger.isWarnEnabled()) {                                 this.logger.warn("Overriding user-defined bean definition for bean ‘" + beanName +                                         "‘ with a framework-generated bean definition: replacing [" +                                         oldBeanDefinition + "] with [" + beanDefinition + "]");                         }                 }                 else if (!beanDefinition.equals(oldBeanDefinition)) {                         if (this.logger.isInfoEnabled()) {                                 this.logger.info("Overriding bean definition for bean ‘" + beanName +                                         "‘ with a different definition: replacing [" + oldBeanDefinition +                                         "] with [" + beanDefinition + "]");                         }                 }                 else {                         if (this.logger.isDebugEnabled()) {                                 this.logger.debug("Overriding bean definition for bean ‘" + beanName +                                         "‘ with an equivalent definition: replacing [" + oldBeanDefinition +                                         "] with [" + beanDefinition + "]");                         }                 }                 this.beanDefinitionMap.put(beanName, beanDefinition);         }         else {                                  if (hasBeanCreationStarted()) {                         // 注册的过程中需要线程同步, 以保证数据的一致性                           synchronized (this.beanDefinitionMap) {                                 this.beanDefinitionMap.put(beanName, beanDefinition);                                 List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);                                 updatedDefinitions.addAll(this.beanDefinitionNames);                                 updatedDefinitions.add(beanName);                                 this.beanDefinitionNames = updatedDefinitions;                                 if (this.manualSingletonNames.contains(beanName)) {                                         Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);                                         updatedSingletons.remove(beanName);                                         this.manualSingletonNames = updatedSingletons;                                 }                         }                 }                 else {                         // 没有同名BeanDefinition注册过, 将Bean名字存入beanDefinitionNames                          this.beanDefinitionMap.put(beanName, beanDefinition);                         this.beanDefinitionNames.add(beanName);                         this.manualSingletonNames.remove(beanName);                 }                 this.frozenBeanDefinitionNames = null;         }          if (oldBeanDefinition != null || containsSingleton(beanName)) {                 resetBeanDefinition(beanName);         } }

        至此,注册完毕后,容器就可用了。虽然这是最原始的容器。

    ApplicationContext容器的设计

        恩,与上一章一样,直接上代码。

应用开发容器:ApplicationContext 

package org.springframework.context;  import org.springframework.beans.factory.HierarchicalBeanFactory; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.core.env.EnvironmentCapable; import org.springframework.core.io.support.ResourcePatternResolver;  /**  * ApplicationContext是spring中较高级的容器。和BeanFactory类似,它可以加载配置文件中定义的bean,将所有的bean集中在一起,当有请求的  * 时候分配bean。 另外,它增加了企业所需要的功能,比如,从属性文件从解析文本信息和将事件传递给所指定的监听器。这个容器在org.springframework.  * context.ApplicationContext接口中定义。ApplicationContext包含BeanFactory所有的功能,一般情况下,相对于BeanFactory,ApplicationContext  * 会被推荐使用。但BeanFactory仍然可以在轻量级应用中使用,比如移动设备或者基于applet的应用程序。  *   * ApplicationContext接口关系  *  1.支持不同的信息源。扩展了MessageSource接口,这个接口为ApplicationContext提供了很多信息源的扩展功能,比如:国际化的实现为多语言版本的应用提供服务。  *  2.访问资源。这一特性主要体现在ResourcePatternResolver接口上,对Resource和ResourceLoader的支持,这样我们可以从不同地方得到Bean定义资源。  *  这种抽象使用户程序可以灵活地定义Bean定义信息,尤其是从不同的IO途径得到Bean定义信息。这在接口上看不出来,不过一般来说,具体ApplicationContext都是  *  继承了DefaultResourceLoader的子类。因为DefaultResourceLoader是AbstractApplicationContext的基类,关于Resource后面会有更详细的介绍。  *  3.支持应用事件。继承了接口ApplicationEventPublisher,为应用环境引入了事件机制,这些事件和Bean的生命周期的结合为Bean的管理提供了便利。  *  4.附件服务。EnvironmentCapable里的服务让基本的Ioc功能更加丰富。  *  5.ListableBeanFactory和HierarchicalBeanFactory是继承的主要容器。  *   * 最常被使用的ApplicationContext接口实现类:  *  1,FileSystemXmlApplicationContext:该容器从XML文件中加载已被定义的bean。在这里,你需要提供给构造器XML文件的完整路径。  *  2,ClassPathXmlApplicationContext:该容器从XML文件中加载已被定义的bean。在这里,你不需要提供XML文件的完整路径,只需正确配置CLASSPATH   *  环境变量即可,因为,容器会从CLASSPATH中搜索bean配置文件。  *  3,WebXmlApplicationContext:该容器会在一个 web 应用程序的范围内加载在XML文件中  *  * @author Rod Johnson  * @author Juergen Hoeller  */ public interface ApplicationContext extends EnvironmentCapableListableBeanFactoryHierarchicalBeanFactory, 		MessageSourceApplicationEventPublisherResourcePatternResolver {  	/** 	 * 得到这个应用环境的独一无二ID 	 * @return 得到这个应用独一无二的ID,或者返回一个空值 	 */ 	String getId();  	/** 	 * 得到这个应用的名称 	 * @return 得到这个应用的名称,或者返回一个空值 	 */ 	String getApplicationName();  	/** 	 * 返回这个应用环境的显示名 	 * @return 这个应用环境的显示名,或者返回一个空值 	 */ 	String getDisplayName(); 	 	/** 	 * 当这个应用第一次载入时,返回一个时间差(ms) 	 * @return 返回一个时间差(ms) 	 */ 	long getStartupDate();  	/** 	 * 得到一个父类的环境,或者空值 	 * @return 返回一个父类的环境,或者空值 	 */ 	ApplicationContext getParent();  	/** 	 * 你可以使用它来自动装配依赖对象,但这是一个非常专业的使用情况下,你在99.99%的时间是不需要他的。 	 * @return 这个应用环境的AutowireCapableBeanFactory接口 	 * @throws IllegalStateException 如果这个应用并不支持AutowireCapableBeanFactory接口,抛出异常 	 */ 	AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException; }

ApplicationContext的层次结构

技术分享ApplicationContext的实现类种类太多,但它们的核心都是将对象工厂功能委托给BeanFactory的实现类DefaultListableBeanFactory,我们就以常用的实现类之一FileSystemXmlApplicationContext来解释。

ApplicationContext的实现方法:FileSystemXmlApplicationContext

package org.springframework.context.support;  import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource;  /**  * 在FileSystemXmlApplicationContext的设计中,我们看到ApplicationContext的主要功能其实已经在AbstractXmlApplicationContext  * 中完成了,而在FileSystemXmlApplicationContext只需要完成它自身的两个功能。  *   * 一个就是启动Ioc容器的refresh()过程。这个会在下一章进行重点论述。  * 另一个就是加载XML的Bean定义资源,主要是getResourceByPath方法来完成。  *  * @author Rod Johnson  * @author Juergen Hoeller  */ public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext { 	 	/** 	 * 创建FileSystemXmlApplicationContext类 	 */ 	public FileSystemXmlApplicationContext() { 	}  	/** 	 * 根据父类,创建FileSystemXmlApplicationContext类 	 * @param parent 父类的接口 	 */ 	public FileSystemXmlApplicationContext(ApplicationContext parent) { 		super(parent); 	}  	/** 	 * 根据XML文件名,创建FileSystemXmlApplicationContext类 	 * @param configLocation BeanDefinition所在的文件路径 	 * @throws BeansException 如果创建失败就抛出异常 	 */  	public FileSystemXmlApplicationContext(String configLocation) throws BeansException { 		this(new String[] {configLocation}, truenull); 	}  	/** 	 * 根据XML文件数组名,创建FileSystemXmlApplicationContext类 	 * @param configLocations XML文件名,可以指定多个BeanDefinition资源路径 	 * @throws BeansException 如果创建失败就抛出异常 	 */ 	public FileSystemXmlApplicationContext(String... configLocations) throws BeansException { 		this(configLocations, truenull); 	}  	/** 	 * 根据载入的父类接口,以及XML文件名自动刷新环境以及创建FileSystemXmlApplicationContext类 	 * @param configLocations XML文件名 	 * @param parent 父类接口,同时指定自己的双亲容器 	 * @throws BeansException 如果创建失败就抛出异常 	 */ 	public FileSystemXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException { 		this(configLocations, true, parent); 	}  	/** 	 * 根据XML文件名自动刷新环境以及创建FileSystemXmlApplicationContext类 	 * @param configLocations XML文件名 	 * @param refresh 是否自动刷新环境 	 * @throws BeansException 如果创建失败就抛出异常 	 */ 	public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException { 		this(configLocations, refresh, null); 	}  	/** 	 * 根据XML文件名、父类接口、自动刷新环境以及创建FileSystemXmlApplicationContext类 	 * 调用父类AbstractRefreshableConfigApplicationContext的方法,设置BeanDefinition定义的资源文件,完成IoC容器Bean定义资源的定位 	 * FileSystemXmlApplicationContext中最重要的实现方法,其他构建大部分都是基于它,类似的设计也在其他实现类中得以运用 	 *  	 * @param configLocations XML文件名 	 * @param refresh 是否自动刷新环境 	 * @param parent 父类接口,同时指定自己的双亲容器 	 * @throws BeansException 如果创建失败就抛出异常 	 */ 	public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) 			throws BeansException {  		super(parent); 		setConfigLocations(configLocations); 		if (refresh) { 			refresh();  	//Ioc容器的refresh()过程,是个非常复杂的过程,但不同的容器实现这里都是相似的,因此基类中就将他们封装好了 		} 	}  	/** 	 * 加载XML Bean的给定资源 	 * 在文件应用中读取XML中的BeanDefinition以应对不同的BeanDefinition读取方式。 	 *  	 * @param string 具体路径 	 * @return Resource 返回一个具体资源 	 */ 	@Override 	protected Resource getResourceByPath(String path) { 		if (path != null && path.startsWith("/")) { 			path = path.substring(1); 		} 		return new FileSystemResource(path); 	} }

容器的入口:refresh

        refresh定义在AbstractApplicationContext类中,它详细描述了整个ApplicationContext的初始化过程,比如BeanFactory的更新、MessageSource和PostProcessor的注册等。这里看起来像是对ApplicationContext进行初始化的模版或执行提纲,这个执行过程为Bean的生命周期管理提供了条件。

AbstractApplicationContext.java

public void refresh() throws BeansException, IllegalStateException {         synchronized (this.startupShutdownMonitor) {                 // 准备刷新容器, 获取容器的当时时间, 同时给容器设置同步标识                   prepareRefresh();                  // 启动子类的refreshBeanFactory方法.                   ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();                  // 为BeanFactory配置容器特性,例如类加载器、事件处理器等.                 prepareBeanFactory(beanFactory);                 try {                         // 设置BeanFactory的后置处理.                           postProcessBeanFactory(beanFactory);                          // 调用BeanFactory的后处理器, 这些后处理器是在Bean定义中向容器注册的.                           invokeBeanFactoryPostProcessors(beanFactory);                          // 注册Bean的后处理器, 在Bean创建过程中调用.                           registerBeanPostProcessors(beanFactory);                          // 初始化上下文中的消息源.                           initMessageSource();                          // 初始化上下文中的事件机制.                           initApplicationEventMulticaster();                          // 初始化其它特殊的Bean.                          onRefresh();                          // 检查并向容器注册监听器Bean.                           registerListeners();                          // 实例化所有剩余的(non-lazy-init) 单例Bean.                         finishBeanFactoryInitialization(beanFactory);                          // 发布容器事件, 结束refresh过程.                           finishRefresh();                 }                 catch (BeansException ex) {                         if (logger.isWarnEnabled()) {                                 logger.warn("Exception encountered during context initialization - " +                                                         "cancelling refresh attempt: " + ex);                         }                         // 销毁已经创建的单例Bean, 以避免资源占用.                          destroyBeans();                         // 取消refresh操作, 重置 ‘active‘ 标志.                           cancelRefresh(ex);                         throw ex;                 }                 finally {                         //重置Spring的核心缓存                         resetCommonCaches();                 }         } }

ApplicationContext容器的使用

        我们以ApplicationContext常用容器的使用来,说明容器的运作原理,实现类我们就用上面的FileSystemXmlApplicationContext,为什么用FileSystemXmlApplicationContext,其实我倒没什么立场问题,只是因为他简单也很具有代表性。而我们就将启动过程中,容器核心部分是如何启动进行说明。其他不作说明,因为太过庞杂了。

package com.kay.cn;  import org.springframework.context.ApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext;  /**  *   * @author kay  * @since 1.0  */ public class Test { 	public static void main(String[] arge) { 		ApplicationContext context = new FileSystemXmlApplicationContext("classpath:applicationContext.xml"); 		Message message = context.getBean("message", Message.class);    //自己写的测试类 		message.printMessage(); 	} }

        因为ApplicationContext和FileSystemXmlApplicationContext代码已经写了,下面是运行时的时效图,所以我们直接从AbstractXmlApplicationContext开始。

FileSystemXmlApplicationContext运行时效图

技术分享

AbstractXmlApplicationContext.java

public AbstractXmlApplicationContext(ApplicationContext parent) {         super(parent); }

        在AbstractXmlApplicationContext中其实,也已经完成仅仅只是继承一下。 

AbstractRefreshableConfigApplicationContext.java

private String[] configLocations;  public AbstractRefreshableConfigApplicationContext(ApplicationContext parent) {         super(parent); }  public void setConfigLocations(String... locations) {         if (locations != null) {                 Assert.noNullElements(locations, "Config locations must not be null");                 this.configLocations = new String[locations.length];                 for (int i = 0; i < locations.length; i++) {                         this.configLocations[i] = resolvePath(locations[i]).trim();                 }         }         else {                 this.configLocations = null;         } }

        而在AbstractRefreshableConfigApplicationContext中,除了继承父类方法,还有就是FileSystemXmlApplicationContext中setConfigLocations方法的实现,setConfigLocations方法主要用于载入XML。

AbstractRefreshableApplicationContext.java

private DefaultListableBeanFactory beanFactory;  public AbstractRefreshableApplicationContext(ApplicationContext parent) {         super(parent); }  protected final void refreshBeanFactory() throws BeansException {         if (hasBeanFactory()) {                 destroyBeans();                 closeBeanFactory();         }         try {                 DefaultListableBeanFactory beanFactory = createBeanFactory();    //容器开始初始化                 beanFactory.setSerializationId(getId());                 customizeBeanFactory(beanFactory);                 loadBeanDefinitions(beanFactory);    //容器的载入、解析和注册                 synchronized (this.beanFactoryMonitor) {                         this.beanFactory = beanFactory;                 }         }         catch (IOException ex) {                 throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);         } }

        在AbstractRefreshableApplicationContext类里,核心部分都在实现refreshBeanFactory方法中得到了实现。但是,却不是在这里进行的调用。

AbstractApplicationContext.java

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {         refreshBeanFactory();         ConfigurableListableBeanFactory beanFactory = getBeanFactory();         if (logger.isDebugEnabled()) {                 logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);         }         return beanFactory; }  protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;

        最后在AbstractApplicationContext类中,进行了调用。通过同在AbstractApplicationContext中的refresh调用obtainFreshBeanFactory,进而调用子类中的refreshBeanFactory。至此,容器核心部分也就初始化完成。

    依赖注入

        上面对Ioc容器的初始化过程进行了分析,而这个初始化过程主要是在Ioc容器中建立BeanDefinition数据映射。但此过程并没有出现对Bean依赖关系进行注入,接下来我们对Bean依赖关系进行注入进行分析。

技术分享

        下面,我们对DefaultListableBeanFactory进行分析。但是对代码进行跟踪,却直接进入了DefaultListableBeanFactory的父类AbstractBeanFactory中。

这是依赖注入部分的时效图

技术分享

AbstractBeanFactory.java

//-------------------------------------------------------------------------------------------- // 这里是对 BeanFactory 接口的实现,比如getBean接口方法 // 这些都是通过doGetBean来实现 // BeanFactory 接口 对应的5个实现,4个在这里,还有一个因为其特殊性并不是在这里重载或者实现的 //-------------------------------------------------------------------------------------------- public Object getBean(String name) throws BeansException {         return doGetBean(name, nullnullfalse); }  //这个方法是我的程序调用的 public <T> T getBean(String name, Class<T> requiredType) throws BeansException {         return doGetBean(name, requiredType, nullfalse);     }  public Object getBean(String name, Object... args) throws BeansException {         return doGetBean(name, null, args, false); }  public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {         return doGetBean(name, requiredType, args, false); }  //这里是实际触发依赖注入的地方 protected <T> T doGetBean(         final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)                 throws BeansException {         //指定名称获取被管理的Bean名称,并且指定名称中对容器的依赖         //如果是别名,将别名转变为Bean的名称         final String beanName = transformedBeanName(name);         Object bean;          //先缓存取得的Bean以及处理创建过的单件模式的Bean         //单态模式的Bean只能创建一次         Object sharedInstance = getSingleton(beanName);         if (sharedInstance != null && args == null) {                 if (logger.isDebugEnabled()) {                         //如果指定名称的Bean在容器中已经存在,则直接返回                         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 + "‘");                         }                 }                 //这里完成FactoryBean的相关处理,对于FactoryBean,BeanFactory已经有所提及,在后面会详细分析                 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);         }         else {                 //缓存中如果已经存在创建的单态模式,因为循环而创建失败,则抛出异常                 if (isPrototypeCurrentlyInCreation(beanName)) {                         throw new BeanCurrentlyInCreationException(beanName);                 }                                  //对容器中的BeanDefinition进行检查,检查能否在当前的BeanFactory中取得Bean.                 //如果在当前的工厂中取不到,则到父类的BeanFactory中去取                 //如果在父类中取不到,则到父类的父类中取                 BeanFactory parentBeanFactory = getParentBeanFactory();                 //当前容器的父容器存在,且当前容器中不存在指名的Bean                 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {                         String nameToLookup = originalBeanName(name);    //解析Bean的原始名                         if (args != null) {                                 //委派给父类容器查找,根据指定的名称和显示参数                                 return (T) parentBeanFactory.getBean(nameToLookup, args);                         }                         else {                                 ///委派给父类容器查找,根据指定的名称和类型                                 return parentBeanFactory.getBean(nameToLookup, requiredType);                         }                 }                                  //创建的Bean是否需要进行验证,一般不需要                 if (!typeCheckOnly) {                         //向容器指定的Bean已被创建                         markBeanAsCreated(beanName);                 }                  try {                         //根据Bean的名字获取BeanDefinition                         final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);                         checkMergedBeanDefinition(mbd, beanName, args);                          //获取当前Bean的所有依赖的名称                         String[] dependsOn = mbd.getDependsOn();                         如果当前Bean有依赖Bean                         if (dependsOn != null) {                                 for (String dependsOnBean : dependsOn) {                                         if (isDependent(beanName, dependsOnBean)) {                                                 throw new BeanCreationException(mbd.getResourceDescription(), beanName,                                                         "Circular depends-on relationship between ‘" + beanName + "‘ and ‘"                                                          + dependsOnBean + "‘");                                         }                                         //把被依赖的Bean注册给当前依赖的Bean                                         registerDependentBean(dependsOnBean, beanName);                                         //触发递归                                         getBean(dependsOnBean);                                     }                         }                          //创建单态模式的Bean实例对象                         if (mbd.isSingleton()) {                                 //使用一个内部匿名类,创建Bean实例对象,并且注册对所依赖的对象                                 sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {                                         @Override                                         public Object getObject() throws BeansException {                                                 try {                                                         //创建一个指定Bean实例对象,如果有父级继承,则合并资对象                                                         return createBean(beanName, mbd, args);                                                 }                                                 catch (BeansException ex) {                                                         //清除显示容器单例模式Bean缓存中的实例对象                                                         destroySingleton(beanName);                                                         throw ex;                                                 }                                         }                                 });                                 //获取给定Bean实例对象                                 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);                         }                         else if (mbd.isPrototype()) {  // 判断是否是原型模式                                 //原型模式会每次创建一个新的对象                                 Object prototypeInstance = null;                                 try {                                         //回调方法,注册原型对象                                         beforePrototypeCreation(beanName);                                         //创建指定Bean对象实例                                         prototypeInstance = createBean(beanName, mbd, args);                                 }                                 finally {                                         //回调方法,Bean无法再次创建                                         afterPrototypeCreation(beanName);                                 }                                 //获取给定Bean的实例对象                                 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);                         }                         else {                                 String scopeName = mbd.getScope();                                 final Scope scope = this.scopes.get(scopeName);                                 //Bean定义资源中没有配置生命周期范围,则Bean不合法                                 if (scope == null) {                                         throw new IllegalStateException("No Scope registered for scope name ‘" + scopeName + "‘");                                 }                                 try {                                         //这里使用一个匿名类,获取一个指定的生命周期范围                                         Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {                                                 @Override                                                 public Object getObject() throws BeansException {                                                         beforePrototypeCreation(beanName);                                                         try {                                                                 return createBean(beanName, mbd, args);                                                         }                                                         finally {                                                                 afterPrototypeCreation(beanName);                                                         }                                                 }                                         });                                         //获取给定Bean的实例对象                                         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);                                 }                         }                 }                 catch (BeansException ex) {                         cleanupAfterBeanCreationFailure(beanName);                         throw ex;                 }         }          // 对创建的Bean进行类型检查,如果没有问题,就返回这个新建的Bean,这个Bean已经包含了依赖关系         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; }

        从上面,可以看出doGetBean,是依赖注入的实际入口,他定义了Bean的定义模式,单例模式(Singleton)和原型模式(Prototype),而依赖注入触发的前提是BeanDefinition数据已经建立好的前提下。其实对于Ioc容器的使用,Spring提供了许多的参数配置,每一个参数配置实际上代表了一个Ioc实现特性,而这些特性的实现很多都需要在依赖注入的过程中或者对Bean进行生命周期管理的过程中完成。Spring Ioc容器作为一个产品,其真正的价值体现在一系列产品特征上,而这些特征都是以依赖反转模式作为核心,他们为控制反转提供了很多便利,从而实现了完整的Ioc容器。

        下面是依赖注入的过程,下面我们重点进行分析。

bean实例的创建和初始化:createBean

        getBean是依赖注入的起点,之后就会调用createBean,createBean可以生成需要的Bean以及对Bean进行初始化,但对createBean进行跟踪,发现他在AbstractBeanFactory中仅仅是声明,而具体实现是在AbstractAutowireCapableBeanFactory类里。

AbstractBeanFactory.java

protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) 			throws BeanCreationException;

AbstractAutowireCapableBeanFactory.java

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {         if (logger.isDebugEnabled()) {                 logger.debug("Creating instance of bean ‘" + beanName + "‘");         }         RootBeanDefinition mbdToUse = mbd;          //判断创建的Bean是否需要实例化,以及这个类是否需要通过类来装载         Class<?> resolvedClass = resolveBeanClass(mbd, beanName);         if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {                 mbdToUse = new RootBeanDefinition(mbd);                 mbdToUse.setBeanClass(resolvedClass);         }          try {                 //校验和准备中的方法覆盖                 mbdToUse.prepareMethodOverrides();         }         catch (BeanDefinitionValidationException ex) {                 throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),                                 beanName, "Validation of method overrides failed", ex);         }          try {                 //如果Bean配置了初始化前和后的处理器,则返回一个Bean对象                 Object bean = resolveBeforeInstantiation(beanName, mbdToUse);                 if (bean != null) {                         return bean;                 }         }         catch (Throwable ex) {                 throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,                                 "BeanPostProcessor before instantiation of bean failed", ex);         }                  //创建Bean的入口         Object beanInstance = doCreateBean(beanName, mbdToUse, args);         if (logger.isDebugEnabled()) {                 logger.debug("Finished creating instance of bean ‘" + beanName + "‘");         }         return beanInstance; }  //Bean的真正创建位置 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {         // 这个BearWrapper是用来封装创建出来的Bean对象的         BeanWrapper instanceWrapper = null;         // 如果是单态模式,就先把缓存中同名的Bean清除         if (mbd.isSingleton()) {                 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);         }         //创建Bean,由createBeanInstance来完成         if (instanceWrapper == null) {                 instanceWrapper = createBeanInstance(beanName, mbd, args);         }         final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);         Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);                  //调用PostProcessor后置处理器         synchronized (mbd.postProcessingLock) {                 if (!mbd.postProcessed) {                         applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);                         mbd.postProcessed = true;                 }         }                  //缓存单态模式的Bean对象,以防循环引用         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<Object>() {                         @Override                         public Object getObject() throws BeansException {                                 return getEarlyBeanReference(beanName, mbd, bean);                         }                 });         }          //初始化Bean的地方,依赖注入发生的地方         //exposedObject在初始化完成后,会作为依赖注入完成后的Bean         Object exposedObject = bean;         try {                 //将Bean实例对象进行封装,并将Bean定义的配置属性赋值给实例对象                 populateBean(beanName, mbd, instanceWrapper);                     if (exposedObject != null) {                         //初始化Bean                         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) {                         //判断注册的实例化Bean和正在实例化的Bean是同一个                         if (exposedObject == bean) {                                 exposedObject = earlySingletonReference;                         }                         //当前Bean依赖其他Bean,并且当发生循环引用时不允许创建新实例                         else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {                                 String[] dependentBeans = getDependentBeans(beanName);                                 Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);                                 //获取当前Bean的所有依赖                                 for (String dependentBean : dependentBeans) {                                         //对依赖bean进行检查                                         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.");                                 }                         }                 }         }                  //注册完成依赖注入的Bean         try {                 registerDisposableBeanIfNecessary(beanName, bean, mbd);         }         catch (BeanDefinitionValidationException ex) {                 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);         }          return exposedObject; }

        在对doCreateBean的追踪中我们发现Bean的创建方法createBeanInstance与BeanDefinition的载入与解析方法populateBean方法是最为重要的。因为控制反转原理的实现就是在这两个方法中实现的。

生成Bean中的对象:createBeanInstance

        在createBeanInstance中生成了Bean所包含的Java对象,对象的生成有很多种不同的方法:工厂方法+反射,容器的autowire特性等等,这些生成方法都是由相关BeanDefinition来指定的。

AbstractAutowireCapableBeanFactory.java

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {         // 确认需要创建的Bean实例的类可以实例化         Class<?> beanClass = resolveBeanClass(mbd, beanName);          //这里使用工厂方法对Bean进行实例化         if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {                 throw new BeanCreationException(mbd.getResourceDescription(), beanName,                                 "Bean class isn‘t public, and non-public access not allowed: " + beanClass.getName());         }          if (mbd.getFactoryMethodName() != null)  {                 //工厂发生进行实例化                 return instantiateUsingFactoryMethod(beanName, mbd, args);         }          //使用容器自动装配方法进行实例化         boolean resolved = false;         boolean autowireNecessary = false;         if (args == null) {                 synchronized (mbd.constructorArgumentLock) {                         if (mbd.resolvedConstructorOrFactoryMethod != null) {                                 resolved = true;                                 autowireNecessary = mbd.constructorArgumentsResolved;                         }                 }         }         if (resolved) {                 if (autowireNecessary) {                         //配置自动装配属性,使用容器自动实例化                         return autowireConstructor(beanName, mbd, nullnull);                 }                 else {                         //无参构造方法实例化                         return instantiateBean(beanName, mbd);                 }         }          //使用构造函数进行实例化         Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);         if (ctors != null ||                         mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||                         mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {                 //使用容器自动装配,调用构造方法实例化                 return autowireConstructor(beanName, mbd, ctors, args);         }          //使用默认构造函数对Bean进行实例化         return instantiateBean(beanName, mbd); }  /**  * CGLIB是一个常用的字节码生成器的类库,他提供了一系列的API来提供生成和转换Java的字节码功能。  * 在Spring AOP中也使用CGLIB对Java的字节码进行了增强。  */  private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();  protected InstantiationStrategy getInstantiationStrategy() {         return this.instantiationStrategy; }  /**  * 最常见的实例化过程instantiateBean  * 使用默认的实例化策略对Bean进行实例化,默认的实例化策略是  * CglibSubclassingInstantiationStrategy,也就是用CGLIB来对Bean进行实例化  */ protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {         try {                 Object beanInstance;                 final BeanFactory parent = this;                 //获取系统的安全管理接口                 if (System.getSecurityManager() != null) {                         beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {                                 @Override                                 public Object run() {                                         return getInstantiationStrategy().instantiate(mbd, beanName, parent);                                 }                         }, getAccessControlContext());                 }                 else {                         //实例化的对象封装                         beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);                 }                 BeanWrapper bw = new BeanWrapperImpl(beanInstance);                 initBeanWrapper(bw);                 return bw;         }         catch (Throwable ex) {                 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);         } }

        我们对CglibSubclassingInstantiationStrategy进行跟踪,发现Spring中的CGLIB生成,是由SimpleInstantiationStrategy.instantiate方法来完成的,所以我们就直接看SimpleInstantiationStrategy.instantiate。如果你对CGLIB有兴趣,可以仔细去研究,这里因为篇幅,所以。。。

SimpleInstantiationStrategy.java

public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {         if (bd.getMethodOverrides().isEmpty()) {                 Constructor<?> constructorToUse;    //指定构造器或者生成的对象工厂方法来对Bean进行实例化                 synchronized (bd.constructorArgumentLock) {                         constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;                         if (constructorToUse == null) {                                 final Class<?> clazz = bd.getBeanClass();                                 if (clazz.isInterface()) {                                         throw new BeanInstantiationException(clazz, "Specified class is an interface");                                 }                                 try {                                         if (System.getSecurityManager() != null) {                                                 constructorToUse = AccessController.doPrivileged(                                                         new PrivilegedExceptionAction<Constructor<?>>() {                                                                 @Override                                                                 public Constructor<?> run() throws Exception {                                                                         return clazz.getDeclaredConstructor((Class[]) null);                                                                 }                                                 });                                         }                                         else {                                                 constructorToUse = clazz.getDeclaredConstructor((Class[]) null);                                         }                                         bd.resolvedConstructorOrFactoryMethod = constructorToUse;                                 }                                 catch (Exception ex) {                                         throw new BeanInstantiationException(clazz, "No default constructor found", ex);                                 }                         }                 }                 //通过BeanUtils进行实例化,这个BeanUtils的实例化通过Constructor来完成                 return BeanUtils.instantiateClass(constructorToUse);         }         else {                 //使用CGLIB来实例化对象                 return instantiateWithMethodInjection(bd, beanName, owner);         } }

属性依赖注入实现:populateBean

        Bean对象进行实例化以后。怎么把这些Bean对象之间的依赖关系处理好,以完成整个依赖注入,而这里就涉及到各种Bean对象依赖关系的处理过程了,而这些依赖关系都已经解析到了BeanDefinition。如果要仔细理解这个过程,我们必须从前面提到的populateBean方法入手。

AbstractAutowireCapableBeanFactory.java

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {         //这里取得BeanDefinition中的property值         PropertyValues pvs = mbd.getPropertyValues();                  //实例对象为NULL         if (bw == null) {                 //属性不能为空                 if (!pvs.isEmpty()) {                         throw new BeanCreationException(                                 mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");                 }                 else {                         //实例对象为NULL,属性值也为空,不需设置,直接返回                         return;                 }         }          //在设置属性之前调用Bean的PostProcessor后置处理器           boolean continueWithPropertyPopulation = true;          if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {                 for (BeanPostProcessor bp : getBeanPostProcessors()) {                         if (bp instanceof InstantiationAwareBeanPostProcessor) {                                 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;                                 if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {                                         continueWithPropertyPopulation = false;                                         break;                                 }                         }                 }         }          if (!continueWithPropertyPopulation) {                 return;         }          //开始进行依赖注入过程,先处理autowire的注入         if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||                         mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {                 MutablePropertyValues newPvs = new MutablePropertyValues(pvs);                  //根据Bean的名字或者类型自动装配处理                 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {                         autowireByName(beanName, mbd, bw, newPvs);                 }                                  //根据类型自动装配注入                 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {                         autowireByType(beanName, mbd, bw, newPvs);                 }                  pvs = newPvs;         }          //检查日期是否持有用于单态模式Bean关闭时的后置处理器         boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();         //Bean实例对象没有依赖,也没有继承         boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);         if (hasInstAwareBpps || needsDepCheck) {                 //从实例对象中提取属性描述符                 PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);                 if (hasInstAwareBpps) {                         for (BeanPostProcessor bp : getBeanPostProcessors()) {                                 if (bp instanceof InstantiationAwareBeanPostProcessor) {                                         InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;                                         //使用BeanPostProcessor处理器处理属性值                                           pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);                                         if (pvs == null) {                                                 return;                                         }                                 }                         }                 }                 if (needsDepCheck) {                         //对要配置的属性进行依赖检查                         checkDependencies(beanName, mbd, filteredPds, pvs);                 }         }                  //对属性进行依赖注入         applyPropertyValues(beanName, mbd, bw, pvs); }  protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {         if (pvs == null || pvs.isEmpty()) {                 return;         }          //封装属性值         MutablePropertyValues mpvs = null;         List<PropertyValue> original;          if (System.getSecurityManager() != null) {                 if (bw instanceof BeanWrapperImpl) {                         //设置安全上下文,JDK安全机制                           ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());                 }         }          if (pvs instanceof MutablePropertyValues) {                 mpvs = (MutablePropertyValues) pvs;                 //属性值已经转换                   if (mpvs.isConverted()) {                         try {                                 //为实例化对象设置属性值                                   bw.setPropertyValues(mpvs);                                 return;                         }                         catch (BeansException ex) {                                 throw new BeanCreationException(                                         mbd.getResourceDescription(), beanName, "Error setting property values", ex);                         }                 }                 //获取属性值对象的原始类型值                   original = mpvs.getPropertyValueList();         }         else {                 original = Arrays.asList(pvs.getPropertyValues());         }          //获取用户自定义的类型转换           TypeConverter converter = getCustomTypeConverter();         if (converter == null) {                 converter = bw;         }         //创建一个Bean定义属性值解析器,将Bean定义中的属性值解析为Bean实例对象           //的实际值           BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);          //这里为解析值创建的一个副本,然后通过副本注入Bean         List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());         boolean resolveNecessary = false;         for (PropertyValue pv : original) {                 //属性值不需要转换                  if (pv.isConverted()) {                         deepCopy.add(pv);                 }                 //属性值需要转换                   else {                         String propertyName = pv.getName();                         //原始的属性值,即转换之前的属性值                           Object originalValue = pv.getValue();                         //转换属性值,例如将引用转换为IoC容器中实例化对象引用                           Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);                         //转换之后的属性值                           Object convertedValue = resolvedValue;                         //属性值是否可以转换                          boolean convertible = bw.isWritableProperty(propertyName) &&                                         !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);                         if (convertible) {                                 //使用用户自定义的类型转换器转换属性值                                   convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);                         }                                                  //存储转换后的属性值,避免每次属性注入时的转换工作                           if (resolvedValue == originalValue) {                                 if (convertible) {                                         //设置属性转换之后的值                                           pv.setConvertedValue(convertedValue);                                 }                                 deepCopy.add(pv);                         }                         //属性是可转换的,且属性原始值是字符串类型,且属性的原始类型值不是                           //动态生成的字符串,且属性的原始值不是集合或者数组类型                           else if (convertible && originalValue instanceof TypedStringValue &&                                         !((TypedStringValue) originalValue).isDynamic() &&                                         !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {                                 pv.setConvertedValue(convertedValue);                                 deepCopy.add(pv);                         }                         else {                                 resolveNecessary = true;                                 //重新封装属性的值                                 deepCopy.add(new PropertyValue(pv, convertedValue));                         }                 }         }         if (mpvs != null && !resolveNecessary) {                 mpvs.setConverted();    //标记属性值已经转换过           }          // 这里是依赖注入发生的地方         try {                 bw.setPropertyValues(new MutablePropertyValues(deepCopy));         }         catch (BeansException ex) {                 throw new BeanCreationException(                         mbd.getResourceDescription(), beanName, "Error setting property values", ex);         } }

        对代码的分析,我们知道当BeanDefinition完成载入和解析后,就进入依赖注入,这里以属性注入为例。但真正依赖注入的地方却是BeanWrapper接口。我们对BeanWrapper接口进行跟踪

技术分享

        他在doCreateBean中最先被定义,然后进入createBeanInstance

技术分享

        恩,最后,进入instantiateBean

技术分享

        最后得到BeanWrapperImpl,就是说依赖注入是在BeanWrapperImpl里完成的。但是以相同的方法对BeanWrapperImpl进行解析,最后发现AbstractNestablePropertyAccessor.setPropertyValue方法最为重要。

        而对BeanWrapper接口的跟踪,我们发现,BeanWrapper是一个组件接口,根据源码分析,其作用是封装主程序中的Bean实例。以此,我们对applyPropertyValues重新分析,发现BeanDefinitionValueResolver.resolveValueIfNecessary方法是依赖注入的另一个关键下面,我们就对其进行分析。

属性值的解析:resolveValueIfNecessary

BeanDefinitionValueResolver.java

public Object resolveValueIfNecessary(Object argName, Object value) {         //对引用类型的属性进行解析         if (value instanceof RuntimeBeanReference) {                 RuntimeBeanReference ref = (RuntimeBeanReference) value;                 //调用引用类型属性的解析方法                 return resolveReference(argName, ref);         }         //对属性值是引用容器中另一个Bean名称的解析         else if (value instanceof RuntimeBeanNameReference) {                 String refName = ((RuntimeBeanNameReference) value).getBeanName();                 refName = String.valueOf(doEvaluate(refName));                 //从容器中获取指定名称的Bean                   if (!this.beanFactory.containsBean(refName)) {                         throw new BeanDefinitionStoreException(                                         "Invalid bean name ‘" + refName + "‘ in bean reference for " + argName); 			}                 return refName;         }         //对Bean类型属性的解析,主要是Bean中的内部类           else if (value instanceof BeanDefinitionHolder) {                 BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;                 return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());         }         else if (value instanceof BeanDefinition) {                 BeanDefinition bd = (BeanDefinition) value;                 String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR +                         ObjectUtils.getIdentityHexString(bd);                 return resolveInnerBean(argName, innerBeanName, bd);         }         //对集合数组类型的属性解析           else if (value instanceof ManagedArray) {                 ManagedArray array = (ManagedArray) value;                 Class<?> elementType = array.resolvedElementType;    //获取数组的类型                   if (elementType == null) {                         String elementTypeName = array.getElementTypeName();    //获取数组元素的类型                           if (StringUtils.hasText(elementTypeName)) {                                 try {                                         //使用反射机制创建指定类型的对象                                           elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());                                         array.resolvedElementType = elementType;                                 }                                 catch (Throwable ex) {                                         throw new BeanCreationException(                                                 this.beanDefinition.getResourceDescription(), this.beanName,                                                 "Error resolving array type for " + argName, ex);                                 }                         }                         //没有获取到数组的类型,也没有获取到数组元素的类型,则直接设置数                           //组的类型为Object                           else {                                 elementType = Object.class;                         }                 }                 //创建指定类型的数组                   return resolveManagedArray(argName, (List<?>) value, elementType);         }         //解析list类型的属性值           else if (value instanceof ManagedList) {                 return resolveManagedList(argName, (List<?>) value);         }         //解析set类型的属性值           else if (value instanceof ManagedSet) {                 return resolveManagedSet(argName, (Set<?>) value);         }         //解析map类型的属性值           else if (value instanceof ManagedMap) {                 return resolveManagedMap(argName, (Map<?, ?>) value);         }         //解析props类型的属性值,props其实就是key和value均为字符串的map           else if (value instanceof ManagedProperties) {                 Properties original = (Properties) value;                 Properties copy = new Properties();    //创建一个拷贝,用于作为解析后的返回值                   for (Map.Entry<ObjectObject> propEntry : original.entrySet()) {                         Object propKey = propEntry.getKey();                         Object propValue = propEntry.getValue();                         if (propKey instanceof TypedStringValue) {                                 propKey = evaluate((TypedStringValue) propKey);                         }                         if (propValue instanceof TypedStringValue) {                                 propValue = evaluate((TypedStringValue) propValue);                         }                         copy.put(propKey, propValue);                 }                 return copy;         }         //解析字符串类型的属性值           else if (value instanceof TypedStringValue) {                 TypedStringValue typedStringValue = (TypedStringValue) value;                 Object valueObject = evaluate(typedStringValue);                 try {                         Class<?> resolvedTargetType = resolveTargetType(typedStringValue);     //获取属性的目标类型                           if (resolvedTargetType != null) {                                 return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);                         }                         //没有获取到属性的目标对象,则按Object类型返回                          else {                                 return valueObject;                         }                 }                 catch (Throwable ex) {                         throw new BeanCreationException(                                 this.beanDefinition.getResourceDescription(), this.beanName,                                 "Error converting typed String value for " + argName, ex);                 }         }         else {                 return evaluate(value);         } }  private Object resolveReference(Object argName, RuntimeBeanReference ref) {         try {                 String refName = ref.getBeanName();    //获取引用的Bean名称                   refName = String.valueOf(doEvaluate(refName));                                  //如果引用的对象在父类容器中,则从父类容器中获取指定的引用对象                   if (ref.isToParent()) {                         if (this.beanFactory.getParentBeanFactory() == null) {                                 throw new BeanCreationException(                                         this.beanDefinition.getResourceDescription(), this.beanName,                                         "Can‘t resolve reference to bean ‘" + refName +                                         "‘ in parent factory: no parent factory available");                         }                         return this.beanFactory.getParentBeanFactory().getBean(refName);                 }                 //从当前的容器中获取指定的引用Bean对象,如果指定的Bean没有被实例化                   //则会递归触发引用Bean的初始化和依赖注入                   else {                         Object bean = this.beanFactory.getBean(refName);                         //将当前实例化对象的依赖引用对象                           this.beanFactory.registerDependentBean(refName, this.beanName);                         return bean;                 }         }         catch (BeansException ex) {                 throw new BeanCreationException(                         this.beanDefinition.getResourceDescription(), this.beanName,                         "Cannot resolve reference to bean ‘" + ref.getBeanName() + "‘ while setting " + argName, ex);         } }

属性值得依赖注入:setPropertyValue

        AbstractNestablePropertyAccessor的setPropertyValue有三个,但都指向最后一个:

AbstractNestablePropertyAccessor.java

protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {         //PropertyTokenHolder主要保存属性的名称、路径,以及集合的size等信息           String propertyName = tokens.canonicalName;         String actualName = tokens.actualName;          //keys是用来保存集合类型属性的size           if (tokens.keys != null) {                 //将属性信息拷贝                   PropertyTokenHolder getterTokens = new PropertyTokenHolder();                 getterTokens.canonicalName = tokens.canonicalName;                 getterTokens.actualName = tokens.actualName;                 getterTokens.keys = new String[tokens.keys.length - 1];                 System.arraycopy(tokens.keys, 0, getterTokens.keys, 0, tokens.keys.length - 1);                 Object propValue;                 try {                         //获取属性值,该方法内部使用JDK的内省(Introspector)机制,调用getter(readerMethod)方法,获取属性的值                         propValue = getPropertyValue(getterTokens);                 }                 catch (NotReadablePropertyException ex) {                         throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,                                         "Cannot access indexed value in property referenced " +                                         "in indexed property path ‘" + propertyName + "‘", ex);                 }                 String key = tokens.keys[tokens.keys.length - 1];    //获取集合类型属性的长度                 if (propValue == null) {                         if (isAutoGrowNestedPaths()) {                                 int lastKeyIndex = tokens.canonicalName.lastIndexOf(‘[‘);                                 getterTokens.canonicalName = tokens.canonicalName.substring(0, lastKeyIndex);                                 propValue = setDefaultValue(getterTokens);                         }                         else {                                 throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + propertyName,                                         "Cannot access indexed value in property referenced " +                                         "in indexed property path ‘" + propertyName + "‘: returned null");                         }                 }                 //注入array类型的属性值                 if (propValue.getClass().isArray()) {                         PropertyHandler ph = getLocalPropertyHandler(actualName);    //获取属性的描述符                           Class<?> requiredType = propValue.getClass().getComponentType();    //获取数组的类型                           int arrayIndex = Integer.parseInt(key);    //获取数组的长度                           Object oldValue = null;                         try {                                 //获取数组以前初始化的值                                  if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {                                         oldValue = Array.get(propValue, arrayIndex);                                 }                                 //将属性的值赋值给数组中的元素                                 Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(),                                         requiredType, ph.nested(tokens.keys.length));                                 int length = Array.getLength(propValue);                                 if (arrayIndex >= length && arrayIndex < this.autoGrowCollectionLimit) {                                         Class<?> componentType = propValue.getClass().getComponentType();                                         Object newArray = Array.newInstance(componentType, arrayIndex + 1);                                         System.arraycopy(propValue, 0, newArray, 0, length);                                         setPropertyValue(actualName, newArray);                                         propValue = getPropertyValue(actualName);                                 }                                 Array.set(propValue, arrayIndex, convertedValue);                         }                         catch (IndexOutOfBoundsException ex) {                                 throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,                                         "Invalid array index in property path ‘" + propertyName + "‘", ex);                         }                 }                 //注入list类型的属性值                   else if (propValue instanceof List) {                         PropertyHandler ph = getPropertyHandler(actualName);                         Class<?> requiredType = ph.getCollectionType(tokens.keys.length);    //获取list集合的类型                           List<Object> list = (List<Object>) propValue;                         int index = Integer.parseInt(key);    //获取list集合的size                           Object oldValue = null;                         if (isExtractOldValueForEditor() && index < list.size()) {                                 oldValue = list.get(index);                         }                         Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(),                                         requiredType, ph.nested(tokens.keys.length));    //获取list解析后的属性值                           int size = list.size();    //为list属性赋值                          //如果list的长度大于属性值的长度,则多余的元素赋值为null                           if (index >= size && index < this.autoGrowCollectionLimit) {                                 for (int i = size; i < index; i++) {                                         try {                                                 list.add(null);                                             }                                         catch (NullPointerException ex) {                                                 throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,                                                                 "Cannot set element with index " + index + " in List of size " +                                                                 size + ", accessed using property path ‘" + propertyName +                                                                 "‘: List does not support filling up gaps with null elements");                                         }                                 }                                 list.add(convertedValue);                         }                         else {                                 try {                                         list.set(index, convertedValue);                                 }                                 catch (IndexOutOfBoundsException ex) {                                         throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,                                                 "Invalid list index in property path ‘" + propertyName + "‘", ex);                                 }                         }                 }                 /注入map类型的属性值                   else if (propValue instanceof Map) {                         PropertyHandler ph = getLocalPropertyHandler(actualName);                         Class<?> mapKeyType = ph.getMapKeyType(tokens.keys.length);    //获取map集合key的类型                           Class<?> mapValueType = ph.getMapValueType(tokens.keys.length);    //获取map集合value的类型                          Map<ObjectObject> map = (Map<ObjectObject>) propValue;                         TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(mapKeyType);                         Object convertedMapKey = convertIfNecessary(nullnull, key, mapKeyType, typeDescriptor);    //解析map类型属性key值                           Object oldValue = null;                         if (isExtractOldValueForEditor()) {                                 oldValue = map.get(convertedMapKey);                         }                         //解析map类型属性value值                         Object convertedMapValue = convertIfNecessary(propertyName, oldValue, pv.getValue(),                                 mapValueType, ph.nested(tokens.keys.length));                         map.put(convertedMapKey, convertedMapValue);    //将解析后的key和value值赋值给map集合属性                   }                 else {                         throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,                                 "Property referenced in indexed property path ‘" + propertyName +                                 "‘ is neither an array nor a List nor a Map; returned value was [" + propValue + "]");                 }         }         //对非集合类型的属性注入           else {                 PropertyHandler ph = getLocalPropertyHandler(actualName);                 if (ph == null || !ph.isWritable()) {                         if (pv.isOptional()) {                                 if (logger.isDebugEnabled()) {                                         logger.debug("Ignoring optional value for property ‘" + actualName +                                                 "‘ - property not found on bean class [" + getRootClass().getName() + "]");                                 }                                 return;                         }                         else {                                 throw createNotWritablePropertyException(propertyName);                         }                 }                 Object oldValue = null;                 try {                         Object originalValue = pv.getValue();                         Object valueToApply = originalValue;                         if (!Boolean.FALSE.equals(pv.conversionNecessary)) {                                 if (pv.isConverted()) {                                         valueToApply = pv.getConvertedValue();                                 }                                 else {                                         if (isExtractOldValueForEditor() && ph.isReadable()) {                                                 try {                                                         oldValue = ph.getValue();                                                 }                                                 catch (Exception ex) {                                                         if (ex instanceof PrivilegedActionException) {                                                                 ex = ((PrivilegedActionException) ex).getException();                                                         }                                                         if (logger.isDebugEnabled()) {                                                                 logger.debug("Could not read previous value of property ‘" +                                                                         this.nestedPath + propertyName + "‘", ex);                                                         }                                                 }                                         }                                         valueToApply = convertForProperty(                                                 propertyName, oldValue, originalValue, ph.toTypeDescriptor());                                 }                                 pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);                         }                         ph.setValue(object, valueToApply);                 }                 catch (TypeMismatchException ex) {                         throw ex;                 }                 catch (InvocationTargetException ex) {                         PropertyChangeEvent propertyChangeEvent =                                 new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());                         if (ex.getTargetException() instanceof ClassCastException) {                                 throw new TypeMismatchException(propertyChangeEvent, ph.getPropertyType(), ex.getTargetException());                         }                         else {                                 Throwable cause = ex.getTargetException();                                 if (cause instanceof UndeclaredThrowableException) {                                         cause = cause.getCause();                                 }                                 throw new MethodInvocationException(propertyChangeEvent, cause);                         }                 }                 catch (Exception ex) {                         PropertyChangeEvent pce =                                 new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());                                         throw new MethodInvocationException(pce, ex);                 }         } }

        好了,自此,依赖注入部分就完了。

    其他特性

        如果把Ioc容器比喻成一个人的话,Bean对象们就构成了他的骨架,依赖注入就是他的血肉,各种组件和支持则汇成了他的筋脉和皮肤,而各种特性则是他的灵魂。各种特性真正的使Spring Ioc有别于其他Ioc框架,也成就了应用开发的丰富多彩,Spring Ioc 作为一个产品,可以说,他的各种特性才是它真正的价值所在。

        Spring Ioc的特性非常的多,了解了Spring Ioc容器整个运行原理后,按照相同思路分析这些特性相信也不是一件难事。如果读者感兴趣的话,也可以按照相同的思路进行研究。这里仅仅举个例子:

        例子:Bean的完整生命周期

        Spring Bean的完整生命周期从创建Spring容器开始,直到最终Spring容器销毁Bean,这其中包含了一系列关键点。

技术分享

        Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:

            1、Bean自身的方法:这个包括了Bean本身调用的方法和通过配置文件中<bean>的init-method和destroy-method指定的方法

            2、Bean级生命周期接口方法:这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法

            3、容器级生命周期接口方法:这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。

            4、工厂后处理器接口方法:这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。

       

闲言小叙

    Spring Ioc容器小结

        Spring Ioc容器的核心是BeanFactory和BeanDefinition。分别对应对象工厂和依赖配置的概念。虽然我们通常使用的是ApplicationContext的实现类,但ApplicationContext只是封装和扩展了BeanFactory的功能。XML的配置形式只是Spring依赖注入的一种常用形式而已,AnnotationConfigApplicationContext配合Annotation注解和泛型,早已经提供了更简易的配置方式AnnotationConfigApplicationContext和AnnotationConfigWebApplicationContext则是实现无XML配置的核心接口,但无论你使用任何配置,最后都会映射到BeanDefinition。

        其次,这里特别要注意的还是BeanDefinition, Bean在XML文件里面的展现形式是<bean id="...">...</bean>,当这个节点被加载到内存中,就被抽象为BeanDefinition了,在XML Bean节点中的那些关键字,在BeanDefinition中都有相对应的成员变量。如何把一个XML节点转换成BeanDefinition,这个工作自然是由BeanDefinitionReader来完成的。Spring通过定义BeanDefinition来管理基于Spring的应用中的各种对象以及它们之间的相互依赖关系。BeanDefinition抽象了我们对Bean的定义,是让容器起作用的主要数据类型。我们知道在计算机世界里,所有的功能都是建立在通过数据对现实进行抽象的基础上的。Ioc容器是用BeanDefinition来管理对象依赖关系的,对Ioc容器而言,BeanDefinition就是对控制反转模式中管理的对象依赖关系的数据抽象,也是容器实现控制反转的核心数据结构,有了他们容器才能发挥作用。

        最后,其实IoC从原理上说是非常简单的,就是把xml文件解析出来,然后放到内存的map里,最后在内置容器里管理bean。但是看IoC的源码,却发现其非常庞大,看着非常吃力。这是因为spring加入了很多特性和为扩展性预留很多的接口,这些特性和扩展,造就了它无与伦比的功能以及未来无限的可能性,可以说正是他们将技术的美学以最简单的方法呈现在了人们面前,当然这也导致了他的复杂性

    太史公曰

        Spring 的核心容器包括 Spring-Core、Spring-Context、Spring-beansSpring-expression四个模块。不知你察觉没有, 笔者首先以BeanFactory容器为切入点,囊括了Bean的创建、解析以及定义和依赖注入的实现,都在Spring-beans的核心部分中。而Spring-Context和Spring-Core也一样,分别以ApplicationContext容器和Resource接口体系进行了囊括。Core模块主要就是定义了访问资源的方式,以及对于各种资源进行用统一的接口来抽象。而Context模块的主要作用则是为Bean对象提供、标识一个运行时环境,初始化BeanFactory并利用BeanFactory来将解析已经注册的Bean进而进行依赖注入,保存Bean对象之间的依赖关系。Context的主要职责是将Core和Bean两个模块融合在一起。而Spring-expression模块,笔者因为时间不够所以没有写,望大家见谅。


Spring 源码学习(二)