【spring】spring源码阅读之xml读取、bean注入(BeanFactory)

前言

  此源码其实是在4月中旬就看了,而且当初也写了一份word文档,但不打算直接把word发上来。还是跟着以前的笔记、跟踪代码边看边写吧。

  其实当初看源码的理由很简单,1、才进新公司,比较有空闲。2、面试老是问spring的问题,我理论又不好,所以想看下。

  但现在,我重新看的目的其实不在于其实现原理,而是想学习和写出好的编码风格。(当初大概花了1周看,记得那时把看到的都理解深刻了,但现在基本不记得什么了。毕竟开发用不到)

一、如何开始阅读源码?

  最初我也一头雾水,不知道从哪开始看、怎么看、看源码的目的是什么等等。

  1、从哪开始看?

    针对本文的话,还是可以知道入口是哪的(后面给出demo),所以我还知道从哪开始开起。

  2、怎么看?

    我都是跟踪代码,一步一步的看的。(其效率很慢,但暂时也只会这么看)

  3、目的?

    当初我只关注spring是怎么读取xml配置、怎么如入bean。但发现,即使我当初看的时候理解在深刻,一个月不回想,再过不多久就不知道都是些什么了。

    而且,现在我更想学习的是好的编码风格,如何才能写出好看、好理解、易扩展的代码(即遵循SOLID原则)

    (开发设计原则 此文章是我较早学习整理的,其正文就是我看到较好的一篇blog内容。)

二、入口代码demo  spring版本3.2.16.RELEASE

public class Demo0102Run {
//	static String path = new Demo0102Run().getClass().getClassLoader().getResource("").getPath();
	public static void main(String[] args) {
//		System.out.println(System.getProperty("user.dir"));
		//step1: 读取spring的xml   (spring核心的是BeanFactory)
		/* 把资源文件封装为Spring的Resource
		 * spring把资源文件封装成统一的Resource进行管理,和提供一些基本的方法。 */
		Resource resource = new ClassPathResource("spring-demo0102.xml",Demo0102Run.class);

//		System.out.println(resource.isOpen());
		/* 加载资源文件,把xml中的bean definition注册到:1.把Resource再次封装为EncodedResource
		 *
		 */
		XmlBeanFactory factory = new XmlBeanFactory(resource);
//		BeanFactory factory = new XmlBeanFactory(resource);

		//step2:根据读取的xml配置,注入对应的bean
		/*
		 *  需要了解 BeanFactory和FactoryBean的区别:http://chenzehe.iteye.com/blog/1481476
		 * 备注01: 如果是beanName的命名是"&"开头,ex:"&demo0102Bean" spring会有别的处理。
		 * 		a. 对于beanInstance是FactoryBean的,会返回FactoryBean的的实例。并不是返回通过FactoryBean创建的bean实例
		 */
		Demo0102Bean bean = (Demo0102Bean) factory.getBean("demo0102Bean");
		System.out.println(bean.getResult());
	}
}
public class Demo0102Bean {
	private String result = "Demo0102Bean result String!";

	public String getResult() {  return result;  }
	public void setResult(String result) {  this.result = result;  }
}

  通过demo,可以很好的跟踪进代码,然后一步一步分析。(我是这样看的,不一定可取)

三、spring读取xml (为了好看,源码中部分注释被删除、部分代码被简写)

Resource resource = new ClassPathResource("spring-demo0102.xml",Demo0102Run.class);

  3.1 new ClassPathResource("spring-demo0102.xml",Demo0102Run.class);

    构造一个ClassPathResource(),根据ClassPathResource的类结构可知:实际是构造了Resource资源文件的实例对象

   在后续的资源处理就可以利用Resource提供各种的服务来操作。

    在demo中,有了ClassPathResource(即Resource)就可以对XmlBeanFactory进行初始化new XmlBeanFactory(...)。

/** Resource.class的实现类,使用给定的ClassLoader或Class去加载资源文件。
 *  	顺序是Class、ClassLoader、null,
 *  详见ClassPathResource.getInputStream()
 */
public class ClassPathResource extends AbstractFileResolvingResource {
	private final String path;
	private ClassLoader classLoader;
	private Class<?> clazz;
	/**
	创建一个 new ClassPathResource();
           Create a new {@code ClassPathResource} for {@code Class} usage.The path can be relative to the given class,
           or absolute within the classpath via a leading slash.
	@param path relative or absolute path within the class path
	@param clazz the class to load resources with
	@see java.lang.Class#getResourceAsStream
	*/
	public ClassPathResource(String path, Class<?> clazz) {// 还有别的构造函数,详见源码; 区别是,是否设置了class、classLoader 
		Assert.notNull(path, "Path must not be null");
		this.path = StringUtils.cleanPath(path);
		this.clazz = clazz;
	}	
           public InputStream getInputStream() throws IOException {
		InputStream is;
		//if else判断根据用Class\ClassLoader去读取资源文件.构造函数中设置
		if (this.clazz != null) is = this.clazz.getResourceAsStream(this.path);
		else if (this.classLoader != null) is = this.classLoader.getResourceAsStream(this.path);
		else is = ClassLoader.getSystemResourceAsStream(this.path);
		
		if (is == null) throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");
		return is;
	}
}

image

    通过ClassPathResource的UML可知道其继承关系(本来显示全名的,但不知道怎么弄)。

    根据此关系及ClassPathResource实际源码,可以发现ClassPathResource实现了Resource中部分抽象方法。

    (在ClassPathResource源码,并未实现全部的Resource。一部分是AbstractResource中实现的,但AbstractResource部份不是真实的实现。e.g.: isOpen();AbstractResource总是返回false。 )

  3.1.1 Resource资源是如何被封装的?

    在demo中是通过new ClassPathResource(...); 通过Resource的关系图,也可以用别的来封装。

image

    image

  3.1.2 Spring为什么需要封装Resource?

    Spring用Resource接口对其内部要用到的资源进行统一的处理。及定义一些基本方法。

    clip_image001

  3.1.3 Spring中的Resource及 InputStreamSource

    通过图Resource类的UML可以看出,对于不同来源的资源文件都有相应的Resource实现:

    • 文件                   :FileSystemResource.class
    • Classpath资源     :ClassPathResource.class
    • URL资源             :UrlResource.class
    • InputStream资源 :InputStreamResource.class
    • Byte数组            :ByteArrayResource.class
    • 等等
/**
 * Interface for a resource descriptor that abstracts from the actual
 * type of underlying resource, such as a file or class path resource.
 *
 * <p>An InputStream can be opened for every resource if it exists in
 * physical form, but a URL or File handle can just be returned for
 * certain resources. The actual behavior is implementation-specific.
*/
public interface Resource extends InputStreamSource {

	/** 返回资源是否存在 */
	boolean exists();
	/** 返回资源内容是否可读 */
	boolean isReadable();

/** 返回这个资源是否有已打开流的处理。
* 如果为true,则此InputStream就不能被多次读取,
*而且只能被读取和关闭以避免资源泄漏
	*/
	boolean isOpen();

	/** 转换Resource到URL
	 * Return a URL handle for this resource.
	 * @throws IOException if the resource cannot be resolved as URL,
	 * i.e. if the resource is not available as descriptor
	 */
	URL getURL() throws IOException;

	/** 转换Resource到URI
	 * Return a URI handle for this resource.
	 * @throws IOException if the resource cannot be resolved as URI,
	 * i.e. if the resource is not available as descriptor
	 */
	URI getURI() throws IOException;

	/** 转换Resource到File
	 * Return a File handle for this resource.
	 * @throws IOException if the resource cannot be resolved as absolute file path, i.e. if the resource is not available in a file system
	 */
	File getFile() throws IOException;

	/** 返回该资源的内容长度
	 * Determine the content length for this resource.
	 * @throws IOException if the resource cannot be resolved
	 * (in the file system or as some other known physical resource type)
	 */
	long contentLength() throws IOException;

	/**
	 * Determine the last-modified timestamp for this resource.
	 * @throws IOException if the resource cannot be resolved
	 * (in the file system or as some other known physical resource type)
	 */
	long lastModified() throws IOException;

	/** 创建资源相对于这个资源
	 * Create a resource relative to this resource.
	 * @param relativePath the relative path (relative to this resource)
	 * @return the resource handle for the relative resource
	 * @throws IOException if the relative resource cannot be determined
	 */
	Resource createRelative(String relativePath) throws IOException;

	/**
	 * Determine a filename for this resource, i.e. typically the last
	 * part of the path: for example, "myfile.txt".
	 * <p>Returns {@code null} if this type of resource does not
	 * have a filename.
	 */
	String getFilename();

	/** 返回该资源的描述,用于错误处理中打印信息。
	 * Return a description for this resource,
	 * to be used for error output when working with the resource.
	 * <p>Implementations are also encouraged to return this value
	 * from their {@code toString} method.
	 * @see Object#toString()
	 */
	String getDescription();

}
Resource类源码
Resource类源码
public interface InputStreamSource {
	/**
	 * @return the input stream for the underlying resource (must not be null)
	 */
	InputStream getInputStream() throws IOException;
}
InputStreamSource类源码

  3.1.4 Resource读取资源的具体实现

    以getInputStream()为例,在ClassPathResource中的实现方式是通过class或者classLoader提供的底层方法调用的,返回InputStream。

    当通过Resource完成了对配置文件进行封装后,配置文件的读取工作就完全交给了XmlBeanDefinitionReader来处理。

	/**
	 * This implementation opens an InputStream for the given class path resource.
	 * @see java.lang.ClassLoader#getResourceAsStream(String)
	 * @see java.lang.Class#getResourceAsStream(String)
	 */
	public InputStream getInputStream() throws IOException {
		InputStream is;
		// if else 判断根据用Class 、 ClassLoader去读取资源文件;在构造函数中设置
		if (this.clazz != null) {
			is = this.clazz.getResourceAsStream(this.path);
		}
		else if (this.classLoader != null) {
			is = this.classLoader.getResourceAsStream(this.path);
		}
		else {
			is = ClassLoader.getSystemResourceAsStream(this.path);
		}
		if (is == null) {
			throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");
		}
		return is;
	}

  3.2 new XmlBeanFactory(resource)

public class XmlBeanFactory extends DefaultListableBeanFactory {

	private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);

	/**
	 * Create a new XmlBeanFactory with the given resource,
	 * which must be parsable using DOM.
	 * @param resource XML resource to load bean definitions from
	 * @throws BeansException in case of loading or parsing errors
	 */
	public XmlBeanFactory(Resource resource) throws BeansException {
		this(resource, null);
	}

	/**
	 * Create a new XmlBeanFactory with the given input stream,
	 * which must be parsable using DOM.
	 * @param resource XML resource to load bean definitions from
	 * @param parentBeanFactory parent bean factory
	 * @throws BeansException in case of loading or parsing errors
	 */
	public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
		/* 调用父类的构造函数,进行了一个中要处理。
		 * 在 AbstractAutowireCapableBeanFactory.class构造函数中有如下设置:
		 * 	ignoreDependencyInterface(BeanNameAware.class);
		 * 	ignoreDependencyInterface(BeanFactoryAware.class);
		 * 	ignoreDependencyInterface(BeanClassLoaderAware.class);
		 *
		 *  ignoreDependencyInterface(...)方法描述: 忽略给定依赖接口的自动装配功能
		 *     具体看方法。
		 */
		super(parentBeanFactory);//此处调用的是:AbstractAutowireCapableBeanFactory.class

		/*
		 * XmlBeanFactory方式整个资源加载的核心
		 */
		this.reader.loadBeanDefinitions(resource);
	}

}
XmlBeanFactory类源码
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
	public DefaultListableBeanFactory(BeanFactory parentBeanFactory) {
		super(parentBeanFactory);
	}
}
DefaultListableBeanFactory类部分源码
image

3.2.1 为什么要ignoreDependencyInterface(...)?

  当A中有属性B时,在spring获取A的Bean的时候,如果属性B还没有初始化,则spring会自动初始化B(这是spring的一个重要特性);

  但是,某些情况下B不会被初始化,其中一种情况就是B实现了BeanNameAware接口。

  ignoreDependencyInterface中注释表明了,忽略给定依赖接口的自动装配功能。典型的是通过其他方式解析ApplicationContext。

  比如:BeanFactory通过BeanFactoryAware进行注入,或者ApplicationContext通过ApplicationContextAware进行注入。

  (这是当初记下的,现在回头看。完全不知道说的什么…>.<!)

3.2.2 (核心)new XmlBeanDefinitionReader(this).loadBeanDefinitions(resource); XmlBeanDefinitionReader方式整个资源加载的核心。

// 整个xml加载的核心代码
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
	/**
	 * Load bean definitions from the specified XML file.
	 * @param resource the resource descriptor for the XML file
	 * @return the number of bean definitions found
	 * @throws BeanDefinitionStoreException in case of loading or parsing errors
	 */
	public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
	  /*
	   * 1:把Resource进一步封装为EncodedResource;
	   * 原因:考虑到Resource可能对编码有要,所以EncodedResource可以指定encoding编码、charset字符集。
	   * EncodedResource中的重要方法是getReader(),返回InputStreamReader.class(java.io.Reader的子类)
	   * 2:再调用加载资源文件的方法。
	   */
	  return loadBeanDefinitions(new EncodedResource(resource));
	}
           //记录已经加载过的资源。注意:用了ThreadLocal
           private final ThreadLocal<Set<EncodedResource>> resourcesCurrentlyBeingLoaded =
			new NamedThreadLocal<Set<EncodedResource>>("XML bean definition resources currently being loaded");

	/**
	 * Load bean definitions from the specified XML file.
	 * @param encodedResource the resource descriptor for the XML file,
	 * allowing to specify an encoding to use for parsing the file
	 * @return the number of bean definitions found
	 * @throws BeanDefinitionStoreException in case of loading or parsing errors
	 */
	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());
		}
                       // 通过类属性resourcesCurrentlyBeingLoaded 记录已加载的资源。
		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
		if (currentResources == null) {
			currentResources = new HashSet<EncodedResource>(4);
			this.resourcesCurrentlyBeingLoaded.set(currentResources);
		}
		//添加新资源到类属性;最后finally中有remove() 处理循环加载exception
		if (!currentResources.add(encodedResource)) {
			//循环加载exception
			throw new BeanDefinitionStoreException(
					"Detected cyclic loading of " + encodedResource
					+ " - check your import definitions!");
		}
		try {
                                // 封装的EncodeResource先获取Resource,在通过Resource获取InputStream 
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
                                // 把InputStream封装为InputSource;org.xml.sax.InputSource不属于Spring		
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				// doLoadBeanDefinitions才是核心加载资源文件
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}
			finally {
				inputStream.close();
			}
		}catch (IOException ex) {
			throw new BeanDefinitionStoreException("IOException parsing XML document from "+ encodedResource.getResource(), ex);
		}
                       // 问题01:finally的作用是什么? 原以为resourcesCurrentlyBeingLoaded类似缓存的作用,但在finally看来应该不是,那resourcesCurrentlyBeingLoaded实际作用是什么?
		finally {
			currentResources.remove(encodedResource);
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
			}
		}
	}

	private DocumentLoader documentLoader = new DefaultDocumentLoader();
	private ErrorHandler errorHandler = new SimpleSaxErrorHandler(logger);

	/** 实际上真正的去加载bean的定义,从指定的xml文件中
	 * Actually load bean definitions from the specified XML file.
	 * @param inputSource the SAX InputSource to read from
	 * @param resource the resource descriptor for the XML file
	 * @return the number of bean definitions found
	 * @throws BeanDefinitionStoreException in case of loading or parsing errors
	 */
	protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
		try {
			// 注册核心01: 获取对xml文件的验证模式
			int validationMode = getValidationModeForResource(resource);
			/* 注册核心02:利用spring核心的DocumentLoader加载xml,得到对应的org.w3c.dom.Document
			 * 	inputSource:就是通过Resource.getInputStream(),在用InputStream构造InputSource
			 *  getEntityResolver():得到一个实体解析器(org.xml.sax.EntityResolver),可以通过AbstractBeanDefinitionReader.setResourceLoader()设置。
			 *  this.errorHandler:xml错误处理。(org.xml.sax.ErrorHandler,不属于spring)
			 *  validationMode:xml验证模式
			 *  isNamespaceAware():Return whether or not the XML parser should be XML namespace aware.
			 */
			Document doc = this.documentLoader.loadDocument(
					inputSource,
					getEntityResolver(),
					this.errorHandler,
					validationMode,
					isNamespaceAware());
			/*
			 * 注册核心03:根据返回的Document注册bean的信息。(重点,解析配置文件,然后注册bean信息)
			 * (理解注册、注入,lyn个人理解:
			 *  	注册:好比创建了一个登陆帐号,保存到了数据库
			 *	注入:根据输入的登陆信息,去数据库找,找到就返回(把bean实例化)
			 * )
			 */
			return registerBeanDefinitions(doc, resource);
		}
		catch (*Exception ex) {
			throw new *Exception(...);
		}
	}
	/** 获取指定的Resource的验证模式,如果没有配置明确的验证模式,则使用自动检测
	 * Gets the validation mode for the specified {@link Resource}. If no explicit validation mode has been configured then the validation mode is
	 * {@link #detectValidationMode detected}.
	 *
	 * <p>Override this method if you would like full control over the validation mode, even when something other than {@link #VALIDATION_AUTO} was set.
	 */
	protected int getValidationModeForResource(Resource resource) {
		int validationModeToUse = getValidationMode();
		// 如果手动指定了验证模式,则使用指定的
		//(可在XmlBeanDefinitionReader.setValidationMode()方法设置)
		if (validationModeToUse != VALIDATION_AUTO) {
			return validationModeToUse;
		}
		// 如果未指定,则使用自动检测
		int detectedMode = detectValidationMode(resource);
		if (detectedMode != VALIDATION_AUTO) {
			return detectedMode;
		}
		// Hmm, we didn't get a clear indication... Let's assume XSD,
		// since apparently no DTD declaration has been found up until
		// detection stopped (before finding the document's root tag).
		return VALIDATION_XSD;
	}

	private boolean namespaceAware = false; // 默认false
	/**
	 * Return whether or not the XML parser should be XML namespace aware.
	 */
	public boolean isNamespaceAware() {
		return this.namespaceAware;
	}
	/** 返回EntityResolver的使用,构建一个默认的EntityResolver(实体解析器)
	 * Return the EntityResolver to use, building a default resolver
	 * if none specified. 如果未指定
	 * getResourceLoader()、getBeanClassLoader()都是AbstractBeanDefinitionReader.class中的方法。
	 */
	protected EntityResolver getEntityResolver() {
		if (this.entityResolver == null) {
			// 确定默认使用的EntityResolver(实体解析器) 
			// Determine default EntityResolver to use.
			ResourceLoader resourceLoader = getResourceLoader();
			if (resourceLoader != null) this.entityResolver = new ResourceEntityResolver(resourceLoader);
			else this.entityResolver = new DelegatingEntityResolver(getBeanClassLoader());
		}
		return this.entityResolver;
	}
}
/** 对Resource进行封装,考虑到Resource可能对编码有要,所以EncodedResource可以指定encoding编码、charset字符集。
 * 当指定后,获取Reader会根据charset、encoding、default的顺序去获取InputStreamReader,看具体代码getReader();
 * Holder that combines a Resource descriptor with a specific encoding
 * or Charset to be used for reading from the resource.
 *
 * <p>Used as an argument for operations that support reading content with a specific encoding, typically via a java.io.Reader.
*/
public class EncodedResource {
	private final Resource resource;
	private final String encoding;
	private final Charset charset;

	/**
	 * Create a new EncodedResource for the given Resource,
	 * not specifying an explicit encoding or Charset.
	 * @param resource the Resource to hold; never null
	 */
	public EncodedResource(Resource resource) {
		this(resource, null, null);
	}

	/**
	 * Create a new EncodedResource for the given Resource,
	 * using the specified encoding.
	 * @param resource the Resource to hold; never null
	 * @param encoding the encoding to use for reading from the resource
	 */
	public EncodedResource(Resource resource, String encoding) {
		this(resource, encoding, null);
	}

	/**
	 * Create a new {@code EncodedResource} for the given {@code Resource},
	 * using the specified {@code Charset}.
	 * @param resource the {@code Resource} to hold; never {@code null}
	 * @param charset the {@code Charset} to use for reading from the resource
	 */
	public EncodedResource(Resource resource, Charset charset) {
		this(resource, null, charset);
	}

	private EncodedResource(Resource resource, String encoding, Charset charset) {
		super();
		Assert.notNull(resource, "Resource must not be null");
		this.resource = resource;
		this.encoding = encoding;
		this.charset = charset;
	}

	/**
	 * Return the {@code Resource} held by this {@code EncodedResource}.
	 */
	public final Resource getResource() {
		return this.resource;
	}

	/**
	 * Return the encoding to use for reading from the {@linkplain #getResource() resource},
	 * or {@code null} if none specified.
	 */
	public final String getEncoding() {
		return this.encoding;
	}

	/**
	 * Return the {@code Charset} to use for reading from the {@linkplain #getResource() resource},
	 * or {@code null} if none specified.
	 */
	public final Charset getCharset() {
		return this.charset;
	}

	/**
	 * Determine whether a {@link Reader} is required as opposed to an {@link InputStream},
	 * i.e. whether an {@linkplain #getEncoding() encoding} or a {@link #getCharset() Charset}
	 * has been specified.
	 * @see #getReader()
	 * @see #getInputStream()
	 */
	public boolean requiresReader() {
		return (this.encoding != null || this.charset != null);
	}

	/** 当设置了encoding或者charset后,会通过指定的去获取InputStreamReader
	 * Open a {@code java.io.Reader} for the specified resource, using the specified
	 * {@link #getCharset() Charset} or {@linkplain #getEncoding() encoding}
	 * (if any).
	 * @throws IOException if opening the Reader failed
	 * @see #requiresReader()
	 * @see #getInputStream()
	 */
	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());
		}
	}

	/**
	 * Open a java.io.InputStream for the specified resource, ignoring any specified {@link #getCharset() Charset} or {@linkplain #getEncoding() encoding}.
	 * @throws IOException if opening the InputStream failed
	 * @see #requiresReader()
	 * @see #getReader()
	 */
	public InputStream getInputStream() throws IOException {
		return this.resource.getInputStream();
	}


	@Override
	public boolean equals(Object obj) {
		if (obj == this) {
			return true;
		}
		if (obj instanceof EncodedResource) {
			EncodedResource that = (EncodedResource) obj;
			return (this.resource.equals(that.resource)
		&& ObjectUtils.nullSafeEquals(this.charset, that.charset) 			&& ObjectUtils.nullSafeEquals(this.encoding, that.encoding));
		}
		return false;
	}

	@Override
	public int hashCode() {
		return this.resource.hashCode();
	}

	@Override
	public String toString() {
		return this.resource.toString();
	}

}
EncodedResource类部分源码

3.2.3 注册核心01: 获取对xml文件的验证模式

  为了保证xml文件的正确性,一般对xml的验证模式有2种:

  (1) DTD:Document Type Definition ,类型定义

  (2) XSD:XML Schemas Definition ,XML结构定义

  问题02DTD和XSD验证XML文件的区别,待看。

  在spring,XmlBeanDefinitionReader中的setValidationMode(int x);可以设置xml的验证方式。如果未设置,则用自动检测模式。

  protected int XmlBeanDefinitionReader.getValidationModeForResource(Resource resource) 可以获取xml的验证方式。

  在其内部又把自动检测detectValidationMode(Resource resource)交给了专门用于处理xml验证的类XmlValidationModeDetector.class

  在XmlValidationModeDetector.class内部,判断xml验证模式的标准是:xml中是否包含"DOCTYPE",如果包含则 DTD验证,否则用XSD;

<!-- 包含"DOCTYPE",用 DTD验证 -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<!-- 未包含"DOCTYPE",用 XSD验证 -->
<?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:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.1.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd"
	>
xml验证模式
public class XmlValidationModeDetector {
	public int detectValidationMode(InputStream inputStream) throws IOException {
		// Peek into the file to look for DOCTYPE. 在读取文件中查找"DOCTYPE"
		BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
		try {
			boolean isDtdValidated = false;
			String content;
			while ((content = reader.readLine()) != null) {
				content = consumeCommentTokens(content);
				//读取的行是null 或者 是注释 则略过
				if (this.inComment || !StringUtils.hasText(content)) { continue; }
				//如果包含DOCTYPE 则验证模式是DTD,否则XSD
				if (hasDoctype(content)) { isDtdValidated = true;break; }
				//读取到<开始符号,验证模式会在开始符号之前(分析xml结构)
				if (hasOpeningTag(content)) {
					// End of meaningful data...
					break;
				}
			}
			return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);
		}
		catch (CharConversionException ex) {
			// Choked on some character encoding...
			// Leave the decision up to the caller.
			return VALIDATION_AUTO;
		}
		finally {
			reader.close();
		}
	}
	/**
	 * Does the supplied content contain an XML opening tag. If the parse state is currently in an XML comment then this method always returns false. It is expected that all comment tokens will have consumed for the supplied content before passing the remainder to this method.
	 */
	private boolean hasOpeningTag(String content) {
		if (this.inComment) { return false;}
		int openTagIndex = content.indexOf('<');
		// Character.isLetter 确定字符是字母,是字母返回true
		return (openTagIndex > –1 && (content.length() > openTagIndex + 1)
                                                 && Character.isLetter(content.charAt(openTagIndex + 1))
				);
	}
}

  结合上面的2种xml理解 hasOpeningTag(content):

    因为都是行读取reader.readLine();

  第一行:<?xml version="1.0" encoding="UTF-8"?>

    openTagIndex > -1 ,0 > -1:true

    (content.length() > openTagIndex + 1) :true

    Character.isLetter(“?”) :?不是字母false

  第二行:<beans xmlns="http://www.springframework.org/schema/beans"

    openTagIndex > -1 ,0 > -1:true

    (content.length() > openTagIndex + 1) :true

    Character.isLetter(“b”) :true

    此时会结束while循环,执行

      return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);

3.2.4 最核心加载xml

        /* 注册核心02:利用spring核心的DocumentLoader加载xml,得到对应的org.w3c.dom.Document

         * inputSource:就是通过Resource.getInputStream(),在用InputStream构造InputSource

         * getEntityResolver():得到一个实体解析器(org.xml.sax.EntityResolver),可以通过AbstractBeanDefinitionReader.setResourceLoader()设置。

         * this.errorHandler:xml错误处理。(org.xml.sax.ErrorHandler,不属于spring)

         * validationMode:xml验证模式

         * isNamespaceAware():Return whether or not the XML parser should be XML namespace aware.

         */

         Document doc = this.documentLoader.loadDocument( inputSource,

                                                                                       getEntityResolver(),

                                                                                       this.errorHandler,

                                                                                       validationMode,

                                                                                       isNamespaceAware());

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
	// DocumentLoader是一个接口,spring唯一实现类是DefaultDocumentLoader;
	private DocumentLoader documentLoader = new DefaultDocumentLoader();

	/** 可以自己实现DocumentLoader, 然后通过该方法设置documentLoader
	 * Specify the {@link DocumentLoader} to use.
	 * <p>The default implementation is {@link DefaultDocumentLoader}
	 * which loads {@link Document} instances using JAXP.
	 */
	public void setDocumentLoader(DocumentLoader documentLoader) {
		this.documentLoader = (documentLoader != null ? documentLoader : new DefaultDocumentLoader());
	}
}
public class DefaultDocumentLoader implements DocumentLoader {
/** JAXP attribute used to configure the schema language for validation.
	 */
	private static final String SCHEMA_LANGUAGE_ATTRIBUTE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
	/**
	 * JAXP attribute value indicating the XSD schema language.
	 */
	private static final String XSD_SCHEMA_LANGUAGE = "http://www.w3.org/2001/XMLSchema";
	private static final Log logger = LogFactory.getLog(DefaultDocumentLoader.class);
	/**
	 * 使用标准的JAXP配置把InputSource加载为Document
	 * Load the {@link Document} at the supplied {@link InputSource} using the standard JAXP-configured
	 * XML parser.
	 */
	public Document loadDocument(InputSource inputSource,
			      EntityResolver entityResolver,
                                        ErrorHandler errorHandler,
			      int validationMode,
			      boolean namespaceAware) throws Exception {
		/* 利用给定的validationMode, namespaceAware;创建一个javax.xml.parsers.DocumentBuilderFactory的实例。
		 * 主要对验证模式是XSD的处理
		 */
		DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
		if (logger.isDebugEnabled()) {
			logger.debug("Using JAXP provider ["+ factory.getClass().getName() + "]");
		}
		/* 利用创建的DocumentBuilderFactory和 给定的entityResolver、errorHandler构造 javax.xml.parsers.DocumentBuilder
		 */
		DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
		/* 用得到的DocumentBuilder解析InputSource,返回Document */
		return builder.parse(inputSource);
	}

	/** 创建一个 javax.xml.parsers.DocumentBuilderFactory的实例
	 * <p>主要对验证模式是XSD的处理
	 * Create the {@link DocumentBuilderFactory} instance.
	 * @param validationMode the type of validation: DTD or XSD
	 * @param namespaceAware whether the returned factory is to provide support for XML namespaces
	 * @return the JAXP DocumentBuilderFactory
	 * @throws ParserConfigurationException if we failed to build a proper DocumentBuilderFactory
	 */
	protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware)
			throws ParserConfigurationException {

		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setNamespaceAware(namespaceAware);
		if(validationMode != XmlValidationModeDetector.VALIDATION_NONE) {
			factory.setValidating(true);
			if(validationMode == XmlValidationModeDetector.VALIDATION_XSD) {
				// Enforce namespace aware for XSD...对XSD强制命名空间感知?
				factory.setNamespaceAware(true);
				try {
					factory.setAttribute(SCHEMA_LANGUAGE_ATTRIBUTE,XSD_SCHEMA_LANGUAGE);
				}catch (IllegalArgumentException ex) {
					ParserConfigurationException pcex =
							new ParserConfigurationException(
			                                                 "Unable to validate using XSD: Your JAXP provider ["
		                                                             + factory +"] does not support XML Schema. Are you running on Java 1.4 with Apache Crimson? " 
                                                                                    + "Upgrade to Apache Xerces (or Java 1.5) for full XSD support.");
					pcex.initCause(ex);
					throw pcex;
				}
			}
		}
		return factory;
	}
	/**创建一个JAXP的DocumentBuilder,这个bean定义阅读器将用于解析xml文档。
	 * 可以在子类中重写,加入进一步的对builder的初始化。
	 * Create a JAXP DocumentBuilder that this bean definition reader
	 * will use for parsing XML documents. Can be overridden in subclasses,
	 * adding further initialization of the builder.
	 * @param factory the JAXP DocumentBuilderFactory that the DocumentBuilder
	 * should be created with
	 * @param entityResolver the SAX EntityResolver to use
	 * @param errorHandler the SAX ErrorHandler to use
	 * @return the JAXP DocumentBuilder
	 * @throws ParserConfigurationException if thrown by JAXP methods
	 */
	protected DocumentBuilder createDocumentBuilder(
			DocumentBuilderFactory factory,
			EntityResolver entityResolver,
			ErrorHandler errorHandler)
			throws ParserConfigurationException {

		DocumentBuilder docBuilder = factory.newDocumentBuilder();
		if (entityResolver != null) {
			docBuilder.setEntityResolver(entityResolver);
		}
		if (errorHandler != null) {
			docBuilder.setErrorHandler(errorHandler);
		}
		return docBuilder;
	}
}

3.2.5 根据返回的Document注册bean的信息

/** 注册核心03:根据返回的Document注册bean的信息。(重点,解析配置文件,然后注册bean信息)

* (理解注册、注入,lyn个人理解:

* 注册:好比创建了一个登陆帐号,保存到了数据库

* 注入:根据输入的登陆信息,去数据库找,找到就返回(把bean实例化)

*/

return registerBeanDefinitions(doc, resource);

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
	private Class<?> documentReaderClass = DefaultBeanDefinitionDocumentReader.class;
	/**
	 * Register the bean definitions contained in the given DOM document.
	 * Called by {@code loadBeanDefinitions}.
	 * <p>Creates a new instance of the parser class and invokes
	 * {@code registerBeanDefinitions} on it.
	 * @param doc the DOM document
	 * @param resource the resource descriptor (for context information)
	 * @return the number of bean definitions found
	 * @throws BeanDefinitionStoreException in case of parsing errors
	 * @see #loadBeanDefinitions
	 * @see #setDocumentReaderClass
	 * @see BeanDefinitionDocumentReader#registerBeanDefinitions
	 */
	@SuppressWarnings("deprecation")
	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
	//org.springframework.beans.factory.xml.BeanDefinitionDocumentReader

	   /* 使用DefaultBeanDefinitionDocumentReader实例化
		BeanDefinitionDocumentReader(spring封装接口)。
	    *  可通过XmlBeanDefinitionReader.setDocumentReaderClass(...)设置
	    */
                BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();

	    /* 设置环境变量 ,对profile来说不可能为null */
	    documentReader.setEnvironment(getEnvironment());

	   /* 获取之前bean definition的加载数量
	     * getRegistry()->XmlBeanFactory extends DefaultListableBeanFactory
	    */
	    int countBefore = getRegistry().getBeanDefinitionCount();

	    /* 核心 加载及注册此次的bean definition*/
	    documentReader.registerBeanDefinitions(doc,createReaderContext(resource));

	    /* 返回本次加载的bean definition数量*/
	    return getRegistry().getBeanDefinitionCount() - countBefore;
	}
	/** 创建的BeanDefinitionDocumentReader用于实际从XML文档中读取bean定义。
	 * 	默认实例指定的是“documentReaderClass”,
	 *  可通过XmlBeanDefinitionReader.setDocumentReaderClass(...)设置
	 * Create the {@link BeanDefinitionDocumentReader} to use for actually
	 * reading bean definitions from an XML document.
	 * <p>The default implementation instantiates the specified "documentReaderClass".
	 * @see #setDocumentReaderClass
	 */	protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
		return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
	}
	/**
	 * Specify the BeanDefinitionDocumentReader implementation to use,
	 * responsible for the actual reading of the XML bean definition document.
	 * <p>The default is DefaultBeanDefinitionDocumentReader.
	 * @param documentReaderClass the desired BeanDefinitionDocumentReader implementation class
	 */
	public void setDocumentReaderClass(Class<?> documentReaderClass) {
		if (documentReaderClass == null || !BeanDefinitionDocumentReader.class.isAssignableFrom(documentReaderClass)) {
			throw new IllegalArgumentException("documentReaderClass must be an implementation of the BeanDefinitionDocumentReader interface");
		}
		this.documentReaderClass = documentReaderClass;
	}
}
public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
	/** 注册bean definition的核心。该方法提取Document中的org.w3c.dom.Element、及设置XmlReaderContext readerContext = XX;
	 * 然后把提取的Element传入核心的doRegisterBeanDefinitions(element),在进一部处理
	 * <p>此实现解析bean definition 根据"spring-beans" XSD(or DTD)
	 * <p>This implementation parses bean definitions according to the "spring-beans" XSD
	 * (or DTD, historically).
	 * <p>打开一个DOM文档,然后初始化在默认的指定的<beans/>中;最后解析包含的bean definition
	 * <p>Opens a DOM Document; then initializes the default settings
	 * specified at the {@code <beans/>} level; then parses the contained bean definitions.
	 */
	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		logger.debug("Loading bean definitions");
		Element root = doc.getDocumentElement();
		/* ********核心注册bean********* */
		doRegisterBeanDefinitions(root);
	}
	/**  注册的核心方法。 利用了模版方法模式 Template method。
	 * 注册每个bean definition从给定的元素<beans/>中.
	 * <p> 如果想在xml解析前后对Element元素做一些处理,
	 * 	则在DefaultBeanDefinitionDocumentReader的子类重写preProcessXml(...)、postProcessXml(...)即可
	 * Register each bean definition within the given root {@code <beans/>} element.
	 */
	protected void doRegisterBeanDefinitions(Element root) {
		// 处理profile属性
		String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
		if (StringUtils.hasText(profileSpec)) {
			String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec,
		                                               BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			if (!getEnvironment().acceptsProfiles(specifiedProfiles)) { return; }
		}
                      // 任何嵌套的<beans/> 都会在parseBeanDefinitions()中递归处理,
                      // Any nested <beans> elements will cause recursion in this method. In
                      // order to propagate and preserve <beans> default-* attributes correctly,
                      // keep track of the current (parent) delegate, which may be null. Create
                      // the new (child) delegate with a reference to the parent for fallback purposes,
                      // then ultimately reset this.delegate back to its original (parent) reference.
                      // this behavior emulates a stack of delegates without actually necessitating one.
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(this.readerContext, root, parent);

		/** 利用了模版方法模式 Template method */
		//解析xml前处理,默认是空实现,留给子类扩展
		preProcessXml(root);
		//核心,把bean definition注册到了
		parseBeanDefinitions(root, this.delegate);
		//解析xml后处理,默认是空实现,留给子类扩展
		postProcessXml(root);

		this.delegate = parent;
	}
	/**
	 * Parse the elements at the root level in the document:
	 * "import", "alias", "bean".
	 * @param root the DOM root element of the document
	 */
	protected void parseBeanDefinitions(Element root,BeanDefinitionParserDelegate delegate) {
		//对beans处理,默认的namespace
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
	                                             //对默认的元素标签处理 如<bean id="b1" class="..."/> <alias/> <import/>
					if (delegate.isDefaultNamespace(ele)) {										
                                                                     parseDefaultElement(ele, delegate);
					}
					else {//对自定义元素标签处理 如<tx:annotation-driven/>
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {  delegate.parseCustomElement(root);  }
	}
	/**
	 * 处理默认元素标签,  <import/> <alias/> <bean/> <beans/>
	 * @param ele
	 * @param delegate
	 */
	private void parseDefaultElement(Element ele,BeanDefinitionParserDelegate delegate) {
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse 如果是<beans/>则递归
			doRegisterBeanDefinitions(ele);
		}
	}
	/** 处理给定的bean元素,并且解析bean definition和调用BeanDefinitionRegistry.registerBeanDefinition(...) 放到相应的ConcurrentHashMap中(线程安全,解决高并发、高吞吐的Map)
	 * Process the given bean element, parsing the bean definition
	 * and registering it with the registry.
	 */
	protected void processBeanDefinition(Element ele,BeanDefinitionParserDelegate delegate) {
                      /* 利用BeanDefinitionParserDelegate.parseBeanDefinitionElement(Element e)
                       * 解析给定bean元素信息为 BeanDefinitionHolder ,这其中就包含了 id,class,alias,name等属性
                           * */
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
		           // 若默认标签的子节点下有 自定义属性 , 还需要再次对自定义标签进行解析
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance. 
				// 最后调用 BeanDefinitionRegistry.registerBeanDefinition(...) 放到相应的ConcurrentHashMap中(线程安全,解决高并发、高吞吐的Map)
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event. 发送注册事件;
			// 通知相关的监听器,这个bean已经注册完成
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}
	// createHelper留给子类重写,但注解表明不推荐使用了; 模版方法模式
	protected BeanDefinitionParserDelegate createDelegate(XmlReaderContext readerContext,
			Element root, BeanDefinitionParserDelegate parentDelegate) {

		BeanDefinitionParserDelegate delegate = createHelper(readerContext, root, parentDelegate);
		if (delegate == null) {
			delegate = new BeanDefinitionParserDelegate(readerContext, getEnvironment());
			delegate.initDefaults(root, parentDelegate);
		}
		return delegate;
	}
	// 可以留给子类重写
	@Deprecated
	protected BeanDefinitionParserDelegate createHelper(XmlReaderContext readerContext,Element root, BeanDefinitionParserDelegate parentDelegate) {
		return null;
	}
}

/**
 * Utility methods that are useful for bean definition reader implementations. Mainly intended for internal use.
 * @author Juergen Hoeller
 * @author Rob Harrop
 * @since 1.1
 * @see PropertiesBeanDefinitionReader
 * @see org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader
 */
public class BeanDefinitionReaderUtils {
	/**
	 * Register the given bean definition with the given bean factory.
	 * @param definitionHolder the bean definition including name and aliases
	 * @param registry the bean factory to register with
	 * @throws BeanDefinitionStoreException if registration failed
	 */
	public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		String beanName = definitionHolder.getBeanName();
	           /** **最终的bean注册,把bean definition保存到ConcurrentHashMap中** */
		registry.registerBeanDefinition(beanName,definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String aliase : aliases) {
				registry.registerAlias(beanName, aliase);
			}
		}
	}
}
PropertiesBeanDefinitionReader类部分源码

BeanDefinitionRegistry是个接口,spring用来统一管理bean definition的注册。

在以上demo中,核心的一个方法是registerBeanDefinition(...).把bean definiton保存到ConcurrentHashMap中(线程安全,解决高并发、高吞吐的Map);

在spring给出的3个实现该方法的类中:

a) DefaultListableBeanFactory.class

b) GenericApplicationContext.class(调用就是a的实现)

c) SimpleBeanDefinitionRegistry.class

都是保存到ConcurrentHashMap中。DefaultListableBeanFactory.class相对于SimpleBeanDefinitionRegistry.class做了一些逻辑处理,且DefaultListableBeanFactory.class中提供了更多的信息,

比如:private final List<String> beanDefinitionNames = new ArrayList<String>(64); 保存了已注册的bean-definition的beanNames。

image

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
	/** Map of bean definition objects, keyed by bean name */
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
	/** List of bean definition names, in registration order */
	private final List<String> beanDefinitionNames = new ArrayList<String>(64);
	/** Cached array of bean definition names in case of frozen configuration */
	private String[] frozenBeanDefinitionNames;
//---------------------------------------------------------------------
// Implementation of BeanDefinitionRegistry interface  实现bean definition的注册
//---------------------------------------------------------------------
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");
		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,"Validation of bean definition failed", ex);
			}
		}

		BeanDefinition oldBeanDefinition;
		synchronized (this.beanDefinitionMap) {
			oldBeanDefinition = this.beanDefinitionMap.get(beanName);
			if (oldBeanDefinition != null) {
				if (!this.allowBeanDefinitionOverriding) {
					throw new BeanDefinitionStoreException(
						beanDefinition.getResourceDescription(),
						beanName,
						"Cannot register bean definition ["
							+ beanDefinition + "] for bean '" + beanName
							+"': There is already [" + oldBeanDefinition
							+ "] bound.");
				}
		                     // 允许重复定义,logger信息(就的bean-definition被替换成新的)
				else {
					if (this.logger.isInfoEnabled()) {
						this.logger.info("Overriding bean definition for bean '" + beanName +"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
					}
				}
			}
			else { //新注册bean-definition
				this.beanDefinitionNames.add(beanName);
				this.frozenBeanDefinitionNames = null;
			}
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		//处理允许重复bean-definition的情况
		if (oldBeanDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
	}
}
DefaultListableBeanFactory类部分源码
// 在GenericApplicationContext.class ->DefaultListableBeanFactory.class
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
	private final DefaultListableBeanFactory beanFactory;
	//---------------------------------------------------------------------
	// Implementation of BeanDefinitionRegistry
	//---------------------------------------------------------------------
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {
		this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
	}
}
GenericApplicationContext类部分源码
public class SimpleBeanDefinitionRegistry extends SimpleAliasRegistry implements BeanDefinitionRegistry {
		/** Map of bean definition objects, keyed by bean name */
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);

	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
		Assert.hasText(beanName, "'beanName' must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");
		this.beanDefinitionMap.put(beanName, beanDefinition);
	}
}
SimpleBeanDefinitionRegistry 类部分源码

3.2.6 什么是profile,其作用是什么?

clip_image002

3.3 获取已注册的bean,并注入. Demo0102Bean bean = (Demo0102Bean) factory.getBean("demo0102Bean");

  此时,factory都是顶层BeanFactory.class的子类/实现类;

  针对demo的例子,此时factory 是以XmlBeanFactory构造的: 

image

DefaultListableBeanFactory:非抽象类

在demo中,factory.getBean("demo0102Bean"); –>  getBean(...)是在BeanFactory接口中定义的,而在AbstractApplicationContext中实现.

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

	/** Parent bean factory, for bean inheritance support(父级BeanFactory,为了支持bean的继承)*/
	private BeanFactory parentBeanFactory;

	/** ClassLoader to resolve bean class names with, if necessary(ClassLoader类加载器,当需要解析bean的类名时。)*/
	private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();

	/** ClassLoader to temporarily resolve bean class names with, if necessary(临时的ClassLoader,如果需要解析bean的类名时) */
	private ClassLoader tempClassLoader;

	/** Whether to cache bean metadata or rather reobtain it for every access;每次访问获得的更精确的元数据,是否再次缓存。默认true */
	private boolean cacheBeanMetadata = true;

	/** Resolution strategy for expressions in bean definition values */
	private BeanExpressionResolver beanExpressionResolver;

	/** Spring ConversionService to use instead of PropertyEditors */
	private ConversionService conversionService;

	/** Custom PropertyEditorRegistrars to apply to the beans of this factory */
	private final Set<PropertyEditorRegistrar> propertyEditorRegistrars =
			new LinkedHashSet<PropertyEditorRegistrar>(4);

	/** A custom TypeConverter to use, overriding the default PropertyEditor mechanism */
	private TypeConverter typeConverter;

	/** Custom PropertyEditors to apply to the beans of this factory */
	private final Map<Class<?>, Class<? extends PropertyEditor>> customEditors =
			new HashMap<Class<?>, Class<? extends PropertyEditor>>(4);

	/** String resolvers to apply e.g. to annotation attribute values */
	private final List<StringValueResolver> embeddedValueResolvers = new LinkedList<StringValueResolver>();

	/** BeanPostProcessors to apply in createBean */
	private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<BeanPostProcessor>();

	/** Indicates whether any InstantiationAwareBeanPostProcessors have been registered */
	private boolean hasInstantiationAwareBeanPostProcessors;

	/** Indicates whether any DestructionAwareBeanPostProcessors have been registered */
	private boolean hasDestructionAwareBeanPostProcessors;

	/** Map from scope identifier String to corresponding Scope */
	private final Map<String, Scope> scopes = new HashMap<String, Scope>(8);

	/** Security context used when running with a SecurityManager */
	private SecurityContextProvider securityContextProvider;

	/** Map from bean name to merged RootBeanDefinition:bean name -> RootBeanDefinition */
	private final Map<String, RootBeanDefinition> mergedBeanDefinitions =
			new ConcurrentHashMap<String, RootBeanDefinition>(64);

	/** Names of beans that have already been created at least once(那些已经至少被创建过一次的beanName的ConcurrentHashMap) */
	private final Map<String, Boolean> alreadyCreated = new ConcurrentHashMap<String, Boolean>(64);

	/** Names of beans that are currently in creation(当前正在创建的bean名称,NamedThreadLocal<Object>)*/
	private final ThreadLocal<Object> prototypesCurrentlyInCreation =
			new NamedThreadLocal<Object>("Prototype beans currently in creation");


	/**
	 * Create a new AbstractBeanFactory.
	 */
	public AbstractBeanFactory() {
	}

	/**
	 * Create a new AbstractBeanFactory with the given parent.
	 * @param parentBeanFactory parent bean factory, or {@code null} if none
	 * @see #getBean
	 */
	public AbstractBeanFactory(BeanFactory parentBeanFactory) {
		this.parentBeanFactory = parentBeanFactory;
	}


	//---------------------------------------------------------------------
	// Implementation of BeanFactory interface BeanFactory接口的实现
	//---------------------------------------------------------------------
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}

	public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
		return doGetBean(name, requiredType, null, false);
	}

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

	/**
	 * Return an instance, which may be shared or independent, of the specified bean.
	 * @param name the name of the bean to retrieve
	 * @param requiredType the required type of the bean to retrieve
	 * @param args arguments to use if creating a prototype using explicit arguments to a
	 * static factory method. It is invalid to use a non-null args value in any other case.
	 * @return an instance of the bean
	 * @throws BeansException if the bean could not be created
	 */
	public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {
		return doGetBean(name, requiredType, args, false);
	}

	/** 返回指定bean的实例,其可以是共享 or 独立的
	 * Return an instance, which may be shared or independent, of the specified bean.
	 * @param name the name of the bean to retrieve ;bean的名称检索
	 * @param requiredType the required type of the bean to retrieve ; 需要注入的bean的类型检索
	 * @param args arguments to use if creating a prototype using explicit arguments to a
	 * static factory method. It is invalid to use a non-null args value in any other case.
	 * @param typeCheckOnly whether the instance is obtained for a type check,
	 * not for actual use
	 * @return an instance of the bean
	 * @throws BeansException if the bean could not be created
	 */
	@SuppressWarnings("unchecked")
	protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
			throws BeansException {
		// transformedBeanName(...) 返回真实的bean的名字
		final String beanName = transformedBeanName(name);
		Object bean;	//最后返回已注入的bean

		/* 要优先检测缓存的原因:
		 * 	因为在创建单例bean的时候,可能存在依赖注入的情况。而在创建依赖的时候为了避免循环依赖,
		 * spring的原则是不等bean创建完成就会将创建bean的ObjectFactory提早暴露出来。
		 * 也就是将ObjectFactory加入到缓存中,一旦当前bean创建时存在需要依赖另一个bean情况(这另一个bean可能在之前已创建过),
		 * 	则通过DefaultSingletonBeanRegistry.getSingleton(String beanName) 可以得到已创建的bean的sharedInstance。
		 * 		(在方法内部,也可能是找到了用于创建sharedInstance的ObjectFactory,再在方法内部用找到的ObjectFactory创建新sharedInstance加入缓存并返回)
		 */
		// Eagerly check singleton cache for manually registered singletons. 检测缓存中是否有单例对象的bean实例
		Object sharedInstance = getSingleton(beanName);
		//如果能从缓存中获得已缓存的单例bean,并且参数args == null(只能在创建prototype时使用),那么直接返回缓存中的bean,否则继续创建bean
		if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			//返回对应的实例,可能存在是FactoryBean的情况,返回的实际是通过FactoryBean创建的bean实例(如果beanName的命名是&开头,那么返回的 Factorybean实例)
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else { //不能在缓存中找到单例bean
			/** 只有单例模式下,才会尝试解决循环依赖。 原型模式下直接抛异常BeanCurrentlyInCreationException;
			 *   什么是循环依赖:例如A中有B属性,B中也有A属性。但A还未创建完成时,会先去创建B,但创建B的时候B又要先去创建A,造成了循环依赖。
			 */
			// Fail if we're already creating this bean instance: 失败,如果我们已经创建了这个bean的实例
			// We're assumably within a circular reference.   我们大概在循环引用
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory. 检测在当前factory是否存在对bean的定义。
			BeanFactory parentBeanFactory = getParentBeanFactory();
			/* 如果当前工厂AbstractBeanFactory存在父级BeanFactory,
			 * 	且当前AbstractBeanFactory不存在bean的定义(BeanDefinition),则把创建bean的职责交给父级Beanfactory
			 */
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				//  递归父类查找。 
				if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}

			if (!typeCheckOnly) {  //是否是简单的只做类型检测,不只是类型检测的话要加入缓存
				// 把指定的beanName记录到alreadyCreated map中(缓存),表明该beanName已经创建过,或即将创建(beanFactory用此来优化beanName重复创建)
				markBeanAsCreated(beanName);
			}

			try {
				//将存储XML配置文件的GernericBeanDefinition转换成RootBeanDefinition,如果指定的beanName是子bean的话,还会合并其父类的信息。
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {  //  若存在依赖,则需要递归实例化依赖的bean。即A中有属性B,B中有C,则递归先实例化C, 在实例话B 最后实例化A
					for (String dependsOnBean : dependsOn) {
						getBean(dependsOnBean);	//递归
						registerDependentBean(dependsOnBean, beanName);//缓存依赖调用
					}
				}

				// Create bean instance. 依赖的bean实例化后,就可以创建bean自身的实例 
				if (mbd.isSingleton()) {	//如果是singleton
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						public Object getObject() throws BeansException {
							try {
								//调用AbstractBeanFactory的实现类AbstractAutowireCapableBeanFactory中createBean方法
								return createBean(beanName, mbd, args);
							}
							catch (BeansException ex) {
								// Explicitly remove instance from singleton cache: It might have been put there
								// eagerly by the creation process, to allow for circular reference resolution.
								// Also remove any beans that received a temporary reference to the bean.
								destroySingleton(beanName);
								throw ex;
							}
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				else if (mbd.isPrototype()) { //如果是prototype
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else { //指定的scope上实例化bean
					String scopeName = mbd.getScope();
					final Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
							public Object getObject() throws BeansException {
								beforePrototypeCreation(beanName);
								try {
									return createBean(beanName, mbd, args);
								}
								finally {
									afterPrototypeCreation(beanName);
								}
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						throw new BeanCreationException(beanName,
								"Scope '" + scopeName + "' is not active for the current thread; " +
								"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
								ex);
					}
				}
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

		// 检查需要的类型是否匹配实际的bean实例化类型
		// Check if required type matches the type of the actual bean instance.
		if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
			try {
				return getTypeConverter().convertIfNecessary(bean, requiredType);
			}
			catch (TypeMismatchException ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("Failed to convert bean '" + name + "' to required type [" +
							ClassUtils.getQualifiedName(requiredType) + "]", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}

	public boolean containsBean(String name) {
		String beanName = transformedBeanName(name);
		if (containsSingleton(beanName) || containsBeanDefinition(beanName)) {
			return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name));
		}
		// Not found -> check parent.
		BeanFactory parentBeanFactory = getParentBeanFactory();
		return (parentBeanFactory != null && parentBeanFactory.containsBean(originalBeanName(name)));
	}

	public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
		String beanName = transformedBeanName(name);

		Object beanInstance = getSingleton(beanName, false);
		if (beanInstance != null) {
			if (beanInstance instanceof FactoryBean) {
				return (BeanFactoryUtils.isFactoryDereference(name) || ((FactoryBean<?>) beanInstance).isSingleton());
			}
			else {
				return !BeanFactoryUtils.isFactoryDereference(name);
			}
		}
		else if (containsSingleton(beanName)) {
			return true;
		}

		else {
			// No singleton instance found -> check bean definition.
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// No bean definition found in this factory -> delegate to parent.
				return parentBeanFactory.isSingleton(originalBeanName(name));
			}

			RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

			// In case of FactoryBean, return singleton status of created object if not a dereference.
			if (mbd.isSingleton()) {
				if (isFactoryBean(beanName, mbd)) {
					if (BeanFactoryUtils.isFactoryDereference(name)) {
						return true;
					}
					FactoryBean<?> factoryBean = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
					return factoryBean.isSingleton();
				}
				else {
					return !BeanFactoryUtils.isFactoryDereference(name);
				}
			}
			else {
				return false;
			}
		}
	}

	public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
		String beanName = transformedBeanName(name);

		BeanFactory parentBeanFactory = getParentBeanFactory();
		if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
			// No bean definition found in this factory -> delegate to parent.
			return parentBeanFactory.isPrototype(originalBeanName(name));
		}

		RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
		if (mbd.isPrototype()) {
			// In case of FactoryBean, return singleton status of created object if not a dereference.
			return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(beanName, mbd));
		}
		else {
			// Singleton or scoped - not a prototype.
			// However, FactoryBean may still produce a prototype object...
			if (BeanFactoryUtils.isFactoryDereference(name)) {
				return false;
			}
			if (isFactoryBean(beanName, mbd)) {
				final FactoryBean<?> factoryBean = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
				if (System.getSecurityManager() != null) {
					return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
						public Boolean run() {
							return ((factoryBean instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factoryBean).isPrototype()) ||
									!factoryBean.isSingleton());
						}
					}, getAccessControlContext());
				}
				else {
					return ((factoryBean instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factoryBean).isPrototype()) ||
							!factoryBean.isSingleton());
				}
			}
			else {
				return false;
			}
		}
	}

	public boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException {
		String beanName = transformedBeanName(name);
		Class<?> typeToMatch = (targetType != null ? targetType : Object.class);

		// Check manually registered singletons.
		Object beanInstance = getSingleton(beanName, false);
		if (beanInstance != null) {
			if (beanInstance instanceof FactoryBean) {
				if (!BeanFactoryUtils.isFactoryDereference(name)) {
					Class<?> type = getTypeForFactoryBean((FactoryBean<?>) beanInstance);
					return (type != null && ClassUtils.isAssignable(typeToMatch, type));
				}
				else {
					return ClassUtils.isAssignableValue(typeToMatch, beanInstance);
				}
			}
			else {
				return !BeanFactoryUtils.isFactoryDereference(name) &&
						ClassUtils.isAssignableValue(typeToMatch, beanInstance);
			}
		}
		else if (containsSingleton(beanName) && !containsBeanDefinition(beanName)) {
			// null instance registered
			return false;
		}

		else {
			// No singleton instance found -> check bean definition.
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// No bean definition found in this factory -> delegate to parent.
				return parentBeanFactory.isTypeMatch(originalBeanName(name), targetType);
			}

			// Retrieve corresponding bean definition.
			RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

			Class<?>[] typesToMatch = (FactoryBean.class.equals(typeToMatch) ?
					new Class<?>[] {typeToMatch} : new Class<?>[] {FactoryBean.class, typeToMatch});

			// Check decorated bean definition, if any: We assume it'll be easier
			// to determine the decorated bean's type than the proxy's type.
			BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
			if (dbd != null && !BeanFactoryUtils.isFactoryDereference(name)) {
				RootBeanDefinition tbd = getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd);
				Class<?> targetClass = predictBeanType(dbd.getBeanName(), tbd, typesToMatch);
				if (targetClass != null && !FactoryBean.class.isAssignableFrom(targetClass)) {
					return typeToMatch.isAssignableFrom(targetClass);
				}
			}

			Class<?> beanType = predictBeanType(beanName, mbd, typesToMatch);
			if (beanType == null) {
				return false;
			}

			// Check bean class whether we're dealing with a FactoryBean.
			if (FactoryBean.class.isAssignableFrom(beanType)) {
				if (!BeanFactoryUtils.isFactoryDereference(name)) {
					// If it's a FactoryBean, we want to look at what it creates, not the factory class.
					beanType = getTypeForFactoryBean(beanName, mbd);
					if (beanType == null) {
						return false;
					}
				}
			}
			else if (BeanFactoryUtils.isFactoryDereference(name)) {
				// Special case: A SmartInstantiationAwareBeanPostProcessor returned a non-FactoryBean
				// type but we nevertheless are being asked to dereference a FactoryBean...
				// Let's check the original bean class and proceed with it if it is a FactoryBean.
				beanType = predictBeanType(beanName, mbd, FactoryBean.class);
				if (beanType == null || !FactoryBean.class.isAssignableFrom(beanType)) {
					return false;
				}
			}

			return typeToMatch.isAssignableFrom(beanType);
		}
	}

	public Class<?> getType(String name) throws NoSuchBeanDefinitionException {
		String beanName = transformedBeanName(name);

		// Check manually registered singletons.
		Object beanInstance = getSingleton(beanName, false);
		if (beanInstance != null) {
			if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
				return getTypeForFactoryBean((FactoryBean<?>) beanInstance);
			}
			else {
				return beanInstance.getClass();
			}
		}
		else if (containsSingleton(beanName) && !containsBeanDefinition(beanName)) {
			// null instance registered
			return null;
		}

		else {
			// No singleton instance found -> check bean definition.
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// No bean definition found in this factory -> delegate to parent.
				return parentBeanFactory.getType(originalBeanName(name));
			}

			RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

			// Check decorated bean definition, if any: We assume it'll be easier
			// to determine the decorated bean's type than the proxy's type.
			BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
			if (dbd != null && !BeanFactoryUtils.isFactoryDereference(name)) {
				RootBeanDefinition tbd = getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd);
				Class<?> targetClass = predictBeanType(dbd.getBeanName(), tbd);
				if (targetClass != null && !FactoryBean.class.isAssignableFrom(targetClass)) {
					return targetClass;
				}
			}

			Class<?> beanClass = predictBeanType(beanName, mbd);

			// Check bean class whether we're dealing with a FactoryBean.
			if (beanClass != null && FactoryBean.class.isAssignableFrom(beanClass)) {
				if (!BeanFactoryUtils.isFactoryDereference(name)) {
					// If it's a FactoryBean, we want to look at what it creates, not at the factory class.
					return getTypeForFactoryBean(beanName, mbd);
				}
				else {
					return beanClass;
				}
			}
			else {
				return (!BeanFactoryUtils.isFactoryDereference(name) ? beanClass : null);
			}
		}
	}

	@Override
	public String[] getAliases(String name) {
		String beanName = transformedBeanName(name);
		List<String> aliases = new ArrayList<String>();
		boolean factoryPrefix = name.startsWith(FACTORY_BEAN_PREFIX);
		String fullBeanName = beanName;
		if (factoryPrefix) {
			fullBeanName = FACTORY_BEAN_PREFIX + beanName;
		}
		if (!fullBeanName.equals(name)) {
			aliases.add(fullBeanName);
		}
		String[] retrievedAliases = super.getAliases(beanName);
		for (String retrievedAlias : retrievedAliases) {
			String alias = (factoryPrefix ? FACTORY_BEAN_PREFIX : "") + retrievedAlias;
			if (!alias.equals(name)) {
				aliases.add(alias);
			}
		}
		if (!containsSingleton(beanName) && !containsBeanDefinition(beanName)) {
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null) {
				aliases.addAll(Arrays.asList(parentBeanFactory.getAliases(fullBeanName)));
			}
		}
		return StringUtils.toStringArray(aliases);
	}


	//---------------------------------------------------------------------
	// Implementation of HierarchicalBeanFactory interface 实现接口HierarchicalBeanFactory的方法
	//---------------------------------------------------------------------
	/**
	 * Return the parent bean factory, or null if there is none.
	 */
	public BeanFactory getParentBeanFactory() {
		return this.parentBeanFactory;
	}

	public boolean containsLocalBean(String name) {
		String beanName = transformedBeanName(name);
		return ((containsSingleton(beanName) || containsBeanDefinition(beanName)) &&
				(!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(beanName)));
	}


	//---------------------------------------------------------------------
	// Implementation of ConfigurableBeanFactory interface
	//---------------------------------------------------------------------

	public void setParentBeanFactory(BeanFactory parentBeanFactory) {
		if (this.parentBeanFactory != null && this.parentBeanFactory != parentBeanFactory) {
			throw new IllegalStateException("Already associated with parent BeanFactory: " + this.parentBeanFactory);
		}
		this.parentBeanFactory = parentBeanFactory;
	}

	public void setBeanClassLoader(ClassLoader beanClassLoader) {
		this.beanClassLoader = (beanClassLoader != null ? beanClassLoader : ClassUtils.getDefaultClassLoader());
	}

	public ClassLoader getBeanClassLoader() {
		return this.beanClassLoader;
	}

	public void setTempClassLoader(ClassLoader tempClassLoader) {
		this.tempClassLoader = tempClassLoader;
	}

	public ClassLoader getTempClassLoader() {
		return this.tempClassLoader;
	}

	public void setCacheBeanMetadata(boolean cacheBeanMetadata) {
		this.cacheBeanMetadata = cacheBeanMetadata;
	}

	public boolean isCacheBeanMetadata() {
		return this.cacheBeanMetadata;
	}

	public void setBeanExpressionResolver(BeanExpressionResolver resolver) {
		this.beanExpressionResolver = resolver;
	}

	public BeanExpressionResolver getBeanExpressionResolver() {
		return this.beanExpressionResolver;
	}

	public void setConversionService(ConversionService conversionService) {
		this.conversionService = conversionService;
	}

	public ConversionService getConversionService() {
		return this.conversionService;
	}

	public void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar) {
		Assert.notNull(registrar, "PropertyEditorRegistrar must not be null");
		this.propertyEditorRegistrars.add(registrar);
	}

	/**
	 * Return the set of PropertyEditorRegistrars.
	 */
	public Set<PropertyEditorRegistrar> getPropertyEditorRegistrars() {
		return this.propertyEditorRegistrars;
	}

	public void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass) {
		Assert.notNull(requiredType, "Required type must not be null");
		Assert.isAssignable(PropertyEditor.class, propertyEditorClass);
		this.customEditors.put(requiredType, propertyEditorClass);
	}

	public void copyRegisteredEditorsTo(PropertyEditorRegistry registry) {
		registerCustomEditors(registry);
	}

	/**
	 * Return the map of custom editors, with Classes as keys and PropertyEditor classes as values.
	 */
	public Map<Class<?>, Class<? extends PropertyEditor>> getCustomEditors() {
		return this.customEditors;
	}

	public void setTypeConverter(TypeConverter typeConverter) {
		this.typeConverter = typeConverter;
	}

	/**
	 * Return the custom TypeConverter to use, if any.
	 * @return the custom TypeConverter, or {@code null} if none specified
	 */
	protected TypeConverter getCustomTypeConverter() {
		return this.typeConverter;
	}

	public TypeConverter getTypeConverter() {
		TypeConverter customConverter = getCustomTypeConverter();
		if (customConverter != null) {
			return customConverter;
		}
		else {
			// Build default TypeConverter, registering custom editors.
			SimpleTypeConverter typeConverter = new SimpleTypeConverter();
			typeConverter.setConversionService(getConversionService());
			registerCustomEditors(typeConverter);
			return typeConverter;
		}
	}

	public void addEmbeddedValueResolver(StringValueResolver valueResolver) {
		Assert.notNull(valueResolver, "StringValueResolver must not be null");
		this.embeddedValueResolvers.add(valueResolver);
	}

	public String resolveEmbeddedValue(String value) {
		String result = value;
		for (StringValueResolver resolver : this.embeddedValueResolvers) {
			if (result == null) {
				return null;
			}
			result = resolver.resolveStringValue(result);
		}
		return result;
	}

	public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
		Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
		this.beanPostProcessors.remove(beanPostProcessor);
		this.beanPostProcessors.add(beanPostProcessor);
		if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
			this.hasInstantiationAwareBeanPostProcessors = true;
		}
		if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
			this.hasDestructionAwareBeanPostProcessors = true;
		}
	}

	public int getBeanPostProcessorCount() {
		return this.beanPostProcessors.size();
	}

	/**
	 * Return the list of BeanPostProcessors that will get applied
	 * to beans created with this factory.
	 */
	public List<BeanPostProcessor> getBeanPostProcessors() {
		return this.beanPostProcessors;
	}

	/**
	 * Return whether this factory holds a InstantiationAwareBeanPostProcessor
	 * that will get applied to singleton beans on shutdown.
	 * @see #addBeanPostProcessor
	 * @see org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor
	 */
	protected boolean hasInstantiationAwareBeanPostProcessors() {
		return this.hasInstantiationAwareBeanPostProcessors;
	}

	/**
	 * Return whether this factory holds a DestructionAwareBeanPostProcessor
	 * that will get applied to singleton beans on shutdown.
	 * @see #addBeanPostProcessor
	 * @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor
	 */
	protected boolean hasDestructionAwareBeanPostProcessors() {
		return this.hasDestructionAwareBeanPostProcessors;
	}

	public void registerScope(String scopeName, Scope scope) {
		Assert.notNull(scopeName, "Scope identifier must not be null");
		Assert.notNull(scope, "Scope must not be null");
		if (SCOPE_SINGLETON.equals(scopeName) || SCOPE_PROTOTYPE.equals(scopeName)) {
			throw new IllegalArgumentException("Cannot replace existing scopes 'singleton' and 'prototype'");
		}
		this.scopes.put(scopeName, scope);
	}

	public String[] getRegisteredScopeNames() {
		return StringUtils.toStringArray(this.scopes.keySet());
	}

	public Scope getRegisteredScope(String scopeName) {
		Assert.notNull(scopeName, "Scope identifier must not be null");
		return this.scopes.get(scopeName);
	}

	/**
	 * Set the security context provider for this bean factory. If a security manager
	 * is set, interaction with the user code will be executed using the privileged
	 * of the provided security context.
	 */
	public void setSecurityContextProvider(SecurityContextProvider securityProvider) {
		this.securityContextProvider = securityProvider;
	}

	/**
	 * Delegate the creation of the access control context to the
	 * {@link #setSecurityContextProvider SecurityContextProvider}.
	 */
	@Override
	public AccessControlContext getAccessControlContext() {
		return (this.securityContextProvider != null ?
				this.securityContextProvider.getAccessControlContext() :
				AccessController.getContext());
	}

	public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) {
		Assert.notNull(otherFactory, "BeanFactory must not be null");
		setBeanClassLoader(otherFactory.getBeanClassLoader());
		setCacheBeanMetadata(otherFactory.isCacheBeanMetadata());
		setBeanExpressionResolver(otherFactory.getBeanExpressionResolver());
		if (otherFactory instanceof AbstractBeanFactory) {
			AbstractBeanFactory otherAbstractFactory = (AbstractBeanFactory) otherFactory;
			this.customEditors.putAll(otherAbstractFactory.customEditors);
			this.propertyEditorRegistrars.addAll(otherAbstractFactory.propertyEditorRegistrars);
			this.beanPostProcessors.addAll(otherAbstractFactory.beanPostProcessors);
			this.hasInstantiationAwareBeanPostProcessors = this.hasInstantiationAwareBeanPostProcessors ||
					otherAbstractFactory.hasInstantiationAwareBeanPostProcessors;
			this.hasDestructionAwareBeanPostProcessors = this.hasDestructionAwareBeanPostProcessors ||
					otherAbstractFactory.hasDestructionAwareBeanPostProcessors;
			this.scopes.putAll(otherAbstractFactory.scopes);
			this.securityContextProvider = otherAbstractFactory.securityContextProvider;
		}
		else {
			setTypeConverter(otherFactory.getTypeConverter());
		}
	}

	/**
	 * Return a 'merged' BeanDefinition for the given bean name,
	 * merging a child bean definition with its parent if necessary.
	 * <p>This {@code getMergedBeanDefinition} considers bean definition
	 * in ancestors as well.
	 * @param name the name of the bean to retrieve the merged definition for
	 * (may be an alias)
	 * @return a (potentially merged) RootBeanDefinition for the given bean
	 * @throws NoSuchBeanDefinitionException if there is no bean with the given name
	 * @throws BeanDefinitionStoreException in case of an invalid bean definition
	 */
	public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {
		String beanName = transformedBeanName(name);

		// Efficiently check whether bean definition exists in this factory.
		if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
			return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
		}
		// Resolve merged bean definition locally.
		return getMergedLocalBeanDefinition(beanName);
	}

	public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
		String beanName = transformedBeanName(name);

		Object beanInstance = getSingleton(beanName, false);
		if (beanInstance != null) {
			return (beanInstance instanceof FactoryBean);
		}
		else if (containsSingleton(beanName)) {
			// null instance registered
			return false;
		}

		// No singleton instance found -> check bean definition.
		if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
			// No bean definition found in this factory -> delegate to parent.
			return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
		}

		return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
	}

	@Override
	public boolean isActuallyInCreation(String beanName) {
		return isSingletonCurrentlyInCreation(beanName) || isPrototypeCurrentlyInCreation(beanName);
	}

	/** 返回指定bean原型当前是否处于正在创建(当前线程内)
	 * Return whether the specified prototype bean is currently in creation
	 * (within the current thread).
	 * @param beanName the name of the bean
	 */
	protected boolean isPrototypeCurrentlyInCreation(String beanName) {
		Object curVal = this.prototypesCurrentlyInCreation.get();
		return (curVal != null &&
				(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
	}

	/**
	 * Callback before prototype creation.
	 * <p>The default implementation register the prototype as currently in creation.
	 * @param beanName the name of the prototype about to be created
	 * @see #isPrototypeCurrentlyInCreation
	 */
	@SuppressWarnings("unchecked")
	protected void beforePrototypeCreation(String beanName) {
		Object curVal = this.prototypesCurrentlyInCreation.get();
		if (curVal == null) {
			this.prototypesCurrentlyInCreation.set(beanName);
		}
		else if (curVal instanceof String) {
			Set<String> beanNameSet = new HashSet<String>(2);
			beanNameSet.add((String) curVal);
			beanNameSet.add(beanName);
			this.prototypesCurrentlyInCreation.set(beanNameSet);
		}
		else {
			Set<String> beanNameSet = (Set<String>) curVal;
			beanNameSet.add(beanName);
		}
	}

	/**
	 * Callback after prototype creation.
	 * <p>The default implementation marks the prototype as not in creation anymore.
	 * @param beanName the name of the prototype that has been created
	 * @see #isPrototypeCurrentlyInCreation
	 */
	@SuppressWarnings("unchecked")
	protected void afterPrototypeCreation(String beanName) {
		Object curVal = this.prototypesCurrentlyInCreation.get();
		if (curVal instanceof String) {
			this.prototypesCurrentlyInCreation.remove();
		}
		else if (curVal instanceof Set) {
			Set<String> beanNameSet = (Set<String>) curVal;
			beanNameSet.remove(beanName);
			if (beanNameSet.isEmpty()) {
				this.prototypesCurrentlyInCreation.remove();
			}
		}
	}

	public void destroyBean(String beanName, Object beanInstance) {
		destroyBean(beanName, beanInstance, getMergedLocalBeanDefinition(beanName));
	}

	/**
	 * Destroy the given bean instance (usually a prototype instance
	 * obtained from this factory) according to the given bean definition.
	 * @param beanName the name of the bean definition
	 * @param beanInstance the bean instance to destroy
	 * @param mbd the merged bean definition
	 */
	protected void destroyBean(String beanName, Object beanInstance, RootBeanDefinition mbd) {
		new DisposableBeanAdapter(beanInstance, beanName, mbd, getBeanPostProcessors(), getAccessControlContext()).destroy();
	}

	public void destroyScopedBean(String beanName) {
		RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
		if (mbd.isSingleton() || mbd.isPrototype()) {
			throw new IllegalArgumentException(
					"Bean name '" + beanName + "' does not correspond to an object in a mutable scope");
		}
		String scopeName = mbd.getScope();
		Scope scope = this.scopes.get(scopeName);
		if (scope == null) {
			throw new IllegalStateException("No Scope SPI registered for scope '" + scopeName + "'");
		}
		Object bean = scope.remove(beanName);
		if (bean != null) {
			destroyBean(beanName, bean, mbd);
		}
	}


	//---------------------------------------------------------------------
	// Implementation methods
	//---------------------------------------------------------------------

	/** 返回bean的名字,
	 * Return the bean name, stripping out(剔除) the factory dereference prefix(前缀) if necessary,
	 * and resolving aliases to canonical names.解决别名规范名称
	 * @param name the user-specified name
	 * @return the transformed bean name
	 */
	protected String transformedBeanName(String name) {
		return canonicalName(BeanFactoryUtils.transformedBeanName(name));
	}

	/**
	 * Determine the original bean name, resolving locally defined aliases to canonical names.
	 * @param name the user-specified name
	 * @return the original bean name
	 */
	protected String originalBeanName(String name) {
		String beanName = transformedBeanName(name);
		if (name.startsWith(FACTORY_BEAN_PREFIX)) {
			beanName = FACTORY_BEAN_PREFIX + beanName;
		}
		return beanName;
	}

	/**
	 * Initialize the given BeanWrapper with the custom editors registered
	 * with this factory. To be called for BeanWrappers that will create
	 * and populate bean instances.
	 * <p>The default implementation delegates to {@link #registerCustomEditors}.
	 * Can be overridden in subclasses.
	 * @param bw the BeanWrapper to initialize
	 */
	protected void initBeanWrapper(BeanWrapper bw) {
		bw.setConversionService(getConversionService());
		registerCustomEditors(bw);
	}

	/**
	 * Initialize the given PropertyEditorRegistry with the custom editors
	 * that have been registered with this BeanFactory.
	 * <p>To be called for BeanWrappers that will create and populate bean
	 * instances, and for SimpleTypeConverter used for constructor argument
	 * and factory method type conversion.
	 * @param registry the PropertyEditorRegistry to initialize
	 */
	protected void registerCustomEditors(PropertyEditorRegistry registry) {
		PropertyEditorRegistrySupport registrySupport =
				(registry instanceof PropertyEditorRegistrySupport ? (PropertyEditorRegistrySupport) registry : null);
		if (registrySupport != null) {
			registrySupport.useConfigValueEditors();
		}
		if (!this.propertyEditorRegistrars.isEmpty()) {
			for (PropertyEditorRegistrar registrar : this.propertyEditorRegistrars) {
				try {
					registrar.registerCustomEditors(registry);
				}
				catch (BeanCreationException ex) {
					Throwable rootCause = ex.getMostSpecificCause();
					if (rootCause instanceof BeanCurrentlyInCreationException) {
						BeanCreationException bce = (BeanCreationException) rootCause;
						if (isCurrentlyInCreation(bce.getBeanName())) {
							if (logger.isDebugEnabled()) {
								logger.debug("PropertyEditorRegistrar [" + registrar.getClass().getName() +
										"] failed because it tried to obtain currently created bean '" +
										ex.getBeanName() + "': " + ex.getMessage());
							}
							onSuppressedException(ex);
							continue;
						}
					}
					throw ex;
				}
			}
		}
		if (!this.customEditors.isEmpty()) {
			for (Map.Entry<Class<?>, Class<? extends PropertyEditor>> entry : this.customEditors.entrySet()) {
				Class<?> requiredType = entry.getKey();
				Class<? extends PropertyEditor> editorClass = entry.getValue();
				registry.registerCustomEditor(requiredType, BeanUtils.instantiateClass(editorClass));
			}
		}
	}


	/** 返回一个合并RootBeanDefinition,将存储XML配置文件的GernericBeanDefinition转换成RootBeanDefinition,如果指定的beanName是子bean的话,还会合并其父类的信息。
	 * <p>Return a merged RootBeanDefinition, traversing the parent bean definition
	 * if the specified bean corresponds to a child bean definition.
	 * @param beanName the name of the bean to retrieve the merged definition for
	 * @return a (potentially merged) RootBeanDefinition for the given bean
	 * @throws NoSuchBeanDefinitionException if there is no bean with the given name
	 * @throws BeanDefinitionStoreException in case of an invalid bean definition
	 */
	protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
		// Quick check on the concurrent map first, with minimal locking. 快速检查并发映射,以最小的锁定(此小锁中的map所包含的key可能不存在,但全锁可能存在,所以后面还有全锁检测)
		RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
		if (mbd != null) {
			return mbd;
		}
		return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
	}

	/**
	 * Return a RootBeanDefinition for the given top-level bean, by merging with
	 * the parent if the given bean's definition is a child bean definition.
	 * @param beanName the name of the bean definition
	 * @param bd the original bean definition (Root/ChildBeanDefinition)
	 * @return a (potentially merged) RootBeanDefinition for the given bean
	 * @throws BeanDefinitionStoreException in case of an invalid bean definition
	 */
	protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
			throws BeanDefinitionStoreException {

		return getMergedBeanDefinition(beanName, bd, null);
	}

	/**
	 * Return a RootBeanDefinition for the given bean, by merging with the
	 * parent if the given bean's definition is a child bean definition.
	 * @param beanName the name of the bean definition
	 * @param bd the original bean definition (Root/ChildBeanDefinition)
	 * @param containingBd the containing bean definition in case of inner bean,
	 * or {@code null} in case of a top-level bean
	 * @return a (potentially merged) RootBeanDefinition for the given bean
	 * @throws BeanDefinitionStoreException in case of an invalid bean definition
	 */
	protected RootBeanDefinition getMergedBeanDefinition(
			String beanName, BeanDefinition bd, BeanDefinition containingBd)
			throws BeanDefinitionStoreException {

		synchronized (this.mergedBeanDefinitions) {
			RootBeanDefinition mbd = null;

			// Check with full lock now in order to enforce the same merged instance.
			if (containingBd == null) {
				//全锁检测是否已存在了 已合并的 相同beanName; (ConcurrentHashMap分离锁特性,前面用最小的锁检测过,但可能别的线程/锁 进行了合并,所以要再次用全锁检测。)
				mbd = this.mergedBeanDefinitions.get(beanName);
			}

			if (mbd == null) {
				//if判断是否需要合并 父类的bean-definiton
				if (bd.getParentName() == null) {  //不存在父类的bean-definition
					// Use copy of given root bean definition.
					if (bd instanceof RootBeanDefinition) {
						mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
					}
					else {
						mbd = new RootBeanDefinition(bd);
					}
				}
				else { //需要合并父类的bean-definition
					// Child bean definition: needs to be merged with parent.
					BeanDefinition pbd;
					try {
						String parentBeanName = transformedBeanName(bd.getParentName());
						if (!beanName.equals(parentBeanName)) {
							pbd = getMergedBeanDefinition(parentBeanName);
						}
						else {
							if (getParentBeanFactory() instanceof ConfigurableBeanFactory) {
								pbd = ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(parentBeanName);
							}
							else {
								throw new NoSuchBeanDefinitionException(bd.getParentName(),
										"Parent name '" + bd.getParentName() + "' is equal to bean name '" + beanName +
										"': cannot be resolved without an AbstractBeanFactory parent");
							}
						}
					}
					catch (NoSuchBeanDefinitionException ex) {
						throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
								"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
					}
					// Deep copy with overridden values.
					mbd = new RootBeanDefinition(pbd);
					mbd.overrideFrom(bd);
				}

				// Set default singleton scope, if not configured before. 设置默认为单例模式
				if (!StringUtils.hasLength(mbd.getScope())) {
					mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
				}

				// 一个包含了非单例的bean,其本身不可能是单例; 则把指定的beanName的bean-definiton的scope指定为 containingBd.getScope()
				// A bean contained in a non-singleton bean cannot be a singleton itself.
				// Let's correct(纠正) this on the fly here, since this might be the result of
				// parent-child merging for the outer bean, in which case the original inner bean
				// definition will not have inherited the merged outer bean's singleton status.
				/** if判断,当指定beanName包含一个非单例的bean,且beanName自身是单例,则把beanName的scope纠正为其包含的bean的scope*/
				if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
					mbd.setScope(containingBd.getScope());
				}

				// Only cache the merged bean definition if we're already about to create an
				// instance of the bean, or at least have already created an instance before.
				/** 只是缓存一个合并后的bean-definiton,如果我们已创建了这个beanName的实例,或者至少在之前已经创建过 。
				 * (把当前指定beanName的bean-definiton存到mergedBeanDefinitions map中做缓存)
				 *   isCacheBeanMetadata():每次访问获得的更精确的元数据,是否再次缓存。默认true
				 *   isBeanEligibleForMetadataCaching(beanName): 确定指定的beanName是否有资格对 其bean-definition元数据进行缓存
				 */
				if (containingBd == null && isCacheBeanMetadata() && isBeanEligibleForMetadataCaching(beanName)) {
					this.mergedBeanDefinitions.put(beanName, mbd);
				}
			}

			return mbd;
		}
	}

	/** 校验给定的 merged-bean-definition,
	 * Check the given merged bean definition,
	 * potentially throwing validation exceptions.
	 * @param mbd the merged bean definition to check
	 * @param beanName the name of the bean
	 * @param args the arguments for bean creation, if any
	 * @throws BeanDefinitionStoreException in case of validation failure
	 */
	protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, Object[] args)
			throws BeanDefinitionStoreException {

		// check if bean definition is not abstract
		if (mbd.isAbstract()) {
			throw new BeanIsAbstractException(beanName);
		}

		// Check validity of the usage of the args parameter. This can
		// only be used for prototypes constructed via a factory method.
		if (args != null && !mbd.isPrototype()) {
			throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
					"Can only specify arguments for the getBean method when referring to a prototype bean definition");
		}
	}

	/**
	 * Remove the merged bean definition for the specified bean,
	 * recreating it on next access.
	 * @param beanName the bean name to clear the merged definition for
	 */
	protected void clearMergedBeanDefinition(String beanName) {
		this.mergedBeanDefinitions.remove(beanName);
	}

	/** 根据RootBeanDefinition中设定的beanClass信息来解析bean,得到其Class<?>
	 * Resolve the bean class for the specified bean definition,
	 * resolving a bean class name into a Class reference (if necessary)
	 * and storing the resolved Class in the bean definition for further use.
	 * @param mbd the merged bean definition to determine the class for
	 * @param beanName the name of the bean (for error handling purposes)
	 * @param typesToMatch the types to match in case of internal type matching purposes
	 * (also signals that the returned {@code Class} will never be exposed to application code)
	 * @return the resolved bean class (or {@code null} if none)
	 * @throws CannotLoadBeanClassException if we failed to load the class
	 */
	protected Class<?> resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch)
			throws CannotLoadBeanClassException {
		try {
			if (mbd.hasBeanClass()) {
				return mbd.getBeanClass();
			}
			if (System.getSecurityManager() != null) {  //权限验证
				return AccessController.doPrivileged(new PrivilegedExceptionAction<Class<?>>() {
					public Class<?> run() throws Exception {
						return doResolveBeanClass(mbd, typesToMatch);
					}
				}, getAccessControlContext());
			}
			else {
				return doResolveBeanClass(mbd, typesToMatch);
			}
		}
		catch (PrivilegedActionException pae) {
			ClassNotFoundException ex = (ClassNotFoundException) pae.getException();
			throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
		}
		catch (ClassNotFoundException ex) {
			throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
		}
		catch (LinkageError err) {
			throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
		}
	}
	/**
	 * 如果typesToMatch !=null,则会尝试用this.tempClassLoader临时类加载器,去解析bean得到其类;<br>
	 *  否则,用this.beanClassLoader,去解析bean得到其类; <b>都可能返回null</b>
	 * @param mbd
	 * @param typesToMatch
	 * @return 根据bean解析得到的Class<?>
	 * @throws ClassNotFoundException
	 */
	private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch) throws ClassNotFoundException {
		if (!ObjectUtils.isEmpty(typesToMatch)) { //当类型匹配不是null时,尝试用tempClassLoader 临时类加载器去解析bean得到其类
			ClassLoader tempClassLoader = getTempClassLoader();
			if (tempClassLoader != null) {
				if (tempClassLoader instanceof DecoratingClassLoader) {
					DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
					for (Class<?> typeToMatch : typesToMatch) {
						dcl.excludeClass(typeToMatch.getName());
					}
				}
				String className = mbd.getBeanClassName();
				return (className != null ? ClassUtils.forName(className, tempClassLoader) : null);
			}
		}
		return mbd.resolveBeanClass(getBeanClassLoader());  //用bean的类加载器去解析bean得到其类
	}

	/**
	 * Evaluate the given String as contained in a bean definition,
	 * potentially resolving it as an expression.
	 * @param value the value to check
	 * @param beanDefinition the bean definition that the value comes from
	 * @return the resolved value
	 * @see #setBeanExpressionResolver
	 */
	protected Object evaluateBeanDefinitionString(String value, BeanDefinition beanDefinition) {
		if (this.beanExpressionResolver == null) {
			return value;
		}
		Scope scope = (beanDefinition != null ? getRegisteredScope(beanDefinition.getScope()) : null);
		return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope));
	}


	/**
	 * Predict the eventual bean type (of the processed bean instance) for the
	 * specified bean. Called by {@link #getType} and {@link #isTypeMatch}.
	 * Does not need to handle FactoryBeans specifically, since it is only
	 * supposed to operate on the raw bean type.
	 * <p>This implementation is simplistic in that it is not able to
	 * handle factory methods and InstantiationAwareBeanPostProcessors.
	 * It only predicts the bean type correctly for a standard bean.
	 * To be overridden in subclasses, applying more sophisticated type detection.
	 * @param beanName the name of the bean
	 * @param mbd the merged bean definition to determine the type for
	 * @param typesToMatch the types to match in case of internal type matching purposes
	 * (also signals that the returned {@code Class} will never be exposed to application code)
	 * @return the type of the bean, or {@code null} if not predictable
	 */
	protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
		if (mbd.getFactoryMethodName() != null) {
			return null;
		}
		return resolveBeanClass(mbd, beanName, typesToMatch);
	}

	/**
	 * Check whether the given bean is defined as a {@link FactoryBean}.
	 * @param beanName the name of the bean
	 * @param mbd the corresponding bean definition
	 */
	protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
		Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);
		return (beanType != null && FactoryBean.class.isAssignableFrom(beanType));
	}

	/**
	 * Determine the bean type for the given FactoryBean definition, as far as possible.
	 * Only called if there is no singleton instance registered for the target bean already.
	 * <p>The default implementation creates the FactoryBean via {@code getBean}
	 * to call its {@code getObjectType} method. Subclasses are encouraged to optimize
	 * this, typically by just instantiating the FactoryBean but not populating it yet,
	 * trying whether its {@code getObjectType} method already returns a type.
	 * If no type found, a full FactoryBean creation as performed by this implementation
	 * should be used as fallback.
	 * @param beanName the name of the bean
	 * @param mbd the merged bean definition for the bean
	 * @return the type for the bean if determinable, or {@code null} else
	 * @see org.springframework.beans.factory.FactoryBean#getObjectType()
	 * @see #getBean(String)
	 */
	protected Class<?> getTypeForFactoryBean(String beanName, RootBeanDefinition mbd) {
		if (!mbd.isSingleton()) {
			return null;
		}
		try {
			FactoryBean<?> factoryBean = doGetBean(FACTORY_BEAN_PREFIX + beanName, FactoryBean.class, null, true);
			return getTypeForFactoryBean(factoryBean);
		}
		catch (BeanCreationException ex) {
			// Can only happen when getting a FactoryBean.
			if (logger.isDebugEnabled()) {
				logger.debug("Ignoring bean creation exception on FactoryBean type check: " + ex);
			}
			onSuppressedException(ex);
			return null;
		}
	}

	/** 标记指定的beanName为已创建(或即将创建);这容许让beanFactory对重复创建的beanName做缓存优化
	 * Mark the specified bean as already created (or about to be created).
	 * <p>This allows the bean factory to optimize its caching for repeated
	 * creation of the specified bean.
	 * @param beanName the name of the bean
	 */
	protected void markBeanAsCreated(String beanName) {
		if (!this.alreadyCreated.containsKey(beanName)) {
			this.alreadyCreated.put(beanName, Boolean.TRUE);
		}
	}

	/**
	 * Perform appropriate cleanup of cached metadata after bean creation failed.
	 * @param beanName the name of the bean
	 */
	protected void cleanupAfterBeanCreationFailure(String beanName) {
		this.alreadyCreated.remove(beanName);
	}

	/** 确定指定的beanName是否有资格对 其bean-definition元数据进行缓存。(如果alreadyCreated map中包含此beanName,返回true)
	 * <p>Determine whether the specified bean is eligible for having
	 * its bean definition metadata cached.
	 * @param beanName the name of the bean
	 * @return {@code true} if the bean's metadata may be cached
	 * at this point already
	 */
	protected boolean isBeanEligibleForMetadataCaching(String beanName) {
		return this.alreadyCreated.containsKey(beanName);
	}

	/**
	 * Remove the singleton instance (if any) for the given bean name,
	 * but only if it hasn't been used for other purposes than type checking.
	 * @param beanName the name of the bean
	 * @return {@code true} if actually removed, {@code false} otherwise
	 */
	protected boolean removeSingletonIfCreatedForTypeCheckOnly(String beanName) {
		if (!this.alreadyCreated.containsKey(beanName)) {
			removeSingleton(beanName);
			return true;
		}
		else {
			return false;
		}
	}

	/** 获取给定bean的实例化对象,无论是bean实例本身  或  是在FactoryBean下生成的bean<BR>
	 * (主要是beanName是否以&开头,是则返回FactoryBean;否则返回FactoryBean创建的bean实例)<p>
	 * Get the object for the given bean instance, either the bean
	 * instance itself or its created object in case of a FactoryBean.
	 * @param beanInstance the shared bean instance
	 * @param name name that may include factory dereference prefix
	 * @param beanName the canonical bean name
	 * @param mbd the merged bean definition
	 * @return the object to expose for the bean
	 */
	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {

		// Don't let calling code try to dereference the factory if the bean isn't a factory.
		if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
			throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
		}

		/* 现在我们已经有了一个bean的实例化(即参数传入的beanInstance),它可能普通的bean,也可能是FactoryBean。
		 * 如果它是FactoryBean,我们就用这个FactoryBean创建一个新的bean实例化对象返回,
		 * 	除非调用者想要的就是一个factory的引用,(即使beanInstance是FactoryBean,但也可以通过beanName的命名来返回FactoryBean,而非FactoryBean创建的bean。
		 * 		强制返回本身的实例beanInstance,这beanName以"&"开头。 BeanFactoryUtils.isFactoryDereference(name)中判断的返回true )
		 */

		// Now we have the bean instance, which may be a normal bean or a FactoryBean.
		// If it's a FactoryBean, we use it to create a bean instance, unless the
		// caller actually wants a reference to the factory.
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;	//如果不是FactoryBean的情况,返回其本身的bean实例化对象
		}

		// 当beanInstance是FactoryBean,且beanName不是以"&"开头,即要返回的是通过FactoryBean创建的bean对象实例
		Object object = null;
		if (mbd == null) {
			// 先从缓存中获取
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// Return bean instance from factory. 到此,beanInstance一定是FactoryBean,进行Object -> FactoryBean的类型转换
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton. 
			// containsBeanDefinition(...) 检测beanDefinitionMap中(即所有已加载的类中)是否已定义了beanName
			if (mbd == null && containsBeanDefinition(beanName)) {	 //已定义beanName
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			//是否是用户定义的而不是程序自身定义
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

	/**
	 * Determine whether the given bean name is already in use within this factory,
	 * i.e. whether there is a local bean or alias registered under this name or
	 * an inner bean created with this name.
	 * @param beanName the name to check
	 */
	public boolean isBeanNameInUse(String beanName) {
		return isAlias(beanName) || containsLocalBean(beanName) || hasDependentBean(beanName);
	}

	/**
	 * Determine whether the given bean requires destruction on shutdown.
	 * <p>The default implementation checks the DisposableBean interface as well as
	 * a specified destroy method and registered DestructionAwareBeanPostProcessors.
	 * @param bean the bean instance to check
	 * @param mbd the corresponding bean definition
	 * @see org.springframework.beans.factory.DisposableBean
	 * @see AbstractBeanDefinition#getDestroyMethodName()
	 * @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor
	 */
	protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
		return (bean != null &&
				(DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || hasDestructionAwareBeanPostProcessors()));
	}

	/**
	 * Add the given bean to the list of disposable beans in this factory,
	 * registering its DisposableBean interface and/or the given destroy method
	 * to be called on factory shutdown (if applicable). Only applies to singletons.
	 * @param beanName the name of the bean
	 * @param bean the bean instance
	 * @param mbd the bean definition for the bean
	 * @see RootBeanDefinition#isSingleton
	 * @see RootBeanDefinition#getDependsOn
	 * @see #registerDisposableBean
	 * @see #registerDependentBean
	 */
	protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
		AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
		if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
			if (mbd.isSingleton()) {
				// Register a DisposableBean implementation that performs all destruction
				// work for the given bean: DestructionAwareBeanPostProcessors,
				// DisposableBean interface, custom destroy method.
				registerDisposableBean(beanName,
						new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
			}
			else {
				// A bean with a custom scope...
				Scope scope = this.scopes.get(mbd.getScope());
				if (scope == null) {
					throw new IllegalStateException("No Scope registered for scope '" + mbd.getScope() + "'");
				}
				scope.registerDestructionCallback(beanName,
						new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
			}
		}
	}


	//---------------------------------------------------------------------
	// Abstract methods to be implemented by subclasses
	//---------------------------------------------------------------------

	/**
	 * Check if this bean factory contains a bean definition with the given name.
	 * Does not consider any hierarchy this factory may participate in.
	 * Invoked by {@code containsBean} when no cached singleton instance is found.
	 * <p>Depending on the nature of the concrete bean factory implementation,
	 * this operation might be expensive (for example, because of directory lookups
	 * in external registries). However, for listable bean factories, this usually
	 * just amounts to a local hash lookup: The operation is therefore part of the
	 * public interface there. The same implementation can serve for both this
	 * template method(模版方法设计模式) and the public interface method in that case.
	 * @param beanName the name of the bean to look for
	 * @return if this bean factory contains a bean definition with the given name
	 * @see #containsBean
	 * @see org.springframework.beans.factory.ListableBeanFactory#containsBeanDefinition
	 */
	protected abstract boolean containsBeanDefinition(String beanName);

	/**
	 * Return the bean definition for the given bean name.
	 * Subclasses should normally implement caching, as this method is invoked
	 * by this class every time bean definition metadata is needed.
	 * <p>Depending on the nature of the concrete bean factory implementation,
	 * this operation might be expensive (for example, because of directory lookups
	 * in external registries). However, for listable bean factories, this usually
	 * just amounts to a local hash lookup: The operation is therefore part of the
	 * public interface there. The same implementation can serve for both this
	 * template method and the public interface method in that case.
	 * @param beanName the name of the bean to find a definition for
	 * @return the BeanDefinition for this prototype name (never {@code null})
	 * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
	 * if the bean definition cannot be resolved
	 * @throws BeansException in case of errors
	 * @see RootBeanDefinition
	 * @see ChildBeanDefinition
	 * @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory#getBeanDefinition
	 */
	protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;

	/**
	 * Create a bean instance for the given bean definition.
	 * The bean definition will already have been merged with the parent
	 * definition in case of a child definition.
	 * <p>All the other methods in this class invoke this method, although
	 * beans may be cached after being instantiated by this method. All bean
	 * instantiation within this class is performed by this method.
	 * @param beanName the name of the bean
	 * @param mbd the merged bean definition for the bean
	 * @param args arguments to use if creating a prototype using explicit arguments to a
	 * static factory method. This parameter must be {@code null} except in this case.
	 * @return a new instance of the bean
	 * @throws BeanCreationException if the bean could not be created
	 */
	protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)
			throws BeanCreationException;

}

image

四、总结心得

  (太晚了,明早睡起来写…)

  隔一晚上都不知道要写什么了,也不想写了。现在通过看源码主要的不是想知道其是如何实现,现阶段更想学到的是通过好的源码学习编码风格、命名、及部分代码该怎么写(比如exception)

posted @ 2016-12-04 03:45  淡丶无欲  阅读(5567)  评论(1编辑  收藏  举报