码迷,mamicode.com
首页 > 编程语言 > 详细

spring源码分析(一)IoC、DI

时间:2016-08-12 23:38:31      阅读:381      评论:0      收藏:0      [点我收藏+]

标签:

创建日期:2016.08.06

修改日期:2016.08.07 - 2016.08.12

交流QQ:992591601

参考书籍:《spring源码深度解析》、《spring技术内幕》

参考文章:http://www.cnblogs.com/xing901022/p/4178963.html

                   http://www.myexception.cn/program/1031276.html

                  http://blog.csdn.net/qian_348840260/article/details/7994936

 

一、搭建工程,运行简单示例:

技术分享

 

 

[java] view plain copy
 
 技术分享技术分享
  1. @Test  
  2. public void testSimpleLoad() {  
  3.     BeanFactory bf = new XmlBeanFactory(new ClassPathResource ("beans.xml"));  
  4.     Person bean = (Person) bf.getBean("person");  
  5.     bean.info();  
  6. }  


其余代码我就不贴了,很基本。要说明一点,要看spring源码的话,需要在导入的spring jar包附上额外的源码包,eclipse可以配置:

 

技术分享

二、这个工程的test程序只有短短几行,但背后的spring代码却是繁多复杂的。

BeanFactory bf = new XmlBeanFactory(new ClassPathResource ("beans.xml"));
Person bean = (Person) bf.getBean("person");

        这两句的逻辑看起来很简单,首先依据xml文件创建工厂类,再通过工厂类从容器获取bean。在这个过程中用ClassPathResource类来对配置文件作一个包装,然后作为XmlBeanFactory构造函数的参数。

        BeanFactory是一个接口。

 

        先来看ClassPathResource类。经过代码阅读,可以总结UML图:

技术分享

          可以清晰看得出来,spring的设计者在这里应用了一个著名设计模式:策略模式。简单些讲,就是面向接口编程的一种思路。在这里UrlResource和ClassPathResource都实现了Resource接口,是Resource接口的两种实现策略。

我们首先看Resource接口,这是最基础的定义:

 

[java] view plain copy
 
 技术分享技术分享
  1. public interface Resource extends InputStreamSource {  
  2.     boolean exists();  
  3.     boolean isReadable();  
  4.     boolean isOpen();  
  5.   
  6.   
  7.     URL getURL() throws IOException;  
  8.     URI getURI() throws IOException;  
  9.     File getFile() throws IOException;  
  10.     long contentLength() throws IOException;  
  11.     long lastModified() throws IOException;  
  12.     Resource createRelative(String relativePath) throws IOException;  
  13.     String getFilename();  
  14.     String getDescription();  
  15. }  

        该接口定义了一些很基本的方法。都是一些很必要的get操作。具体实现自然要交给两个策略来实现:UrlResource和ClassPathResource。另外,值得一提的是该接口还继承了一个接口InputStreamSource。该接口只定义了一个方法:

 

        InputStream getInputStream() throws IOException;    是用来获取java I/O的。

        抽象类AbstractResource是接口与实现策略之间的中间层。实现了Resource接口的所有方法。在此基础上,策略类继承该抽象类之后,就只需提供自己特有的方法即可了。然而很多方法例如getURL都要在策略类里重写的,因为url这种数据还是要具体实例化时才能得到。

        具体实现细节不多说,总结一下,就是spring的资源文件通过Resource接口的实现类来包装。而这些实现类与Resource接口的关系是一种策略模式。

 

接下来看XmlBeanFactory类的代码:

 

[java] view plain copy
 
 技术分享技术分享
  1. public class XmlBeanFactory extends DefaultListableBeanFactory {  
  2.   
  3.     private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);  
  4.   
  5.   
  6.     /** 
  7.      * Create a new XmlBeanFactory with the given resource, 
  8.      * which must be parsable using DOM. 
  9.      * @param resource XML resource to load bean definitions from 
  10.      * @throws BeansException in case of loading or parsing errors 
  11.      */  
  12.     public XmlBeanFactory(Resource resource) throws BeansException {  
  13.         this(resource, null);  
  14.     }  
  15.   
  16.     /** 
  17.      * Create a new XmlBeanFactory with the given input stream, 
  18.      * which must be parsable using DOM. 
  19.      * @param resource XML resource to load bean definitions from 
  20.      * @param parentBeanFactory parent bean factory 
  21.      * @throws BeansException in case of loading or parsing errors 
  22.      */  
  23.     public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {  
  24.         super(parentBeanFactory);  
  25.         this.reader.loadBeanDefinitions(resource);  
  26.     }  
  27.   
  28. }  

 

XmlBeanFactory将Resource作为构造函数参数。这里XmlBeanDefinitionReader是关键,用来根据Resource来loadBeanDefinitions。这是XmlBeanFactory对基类DefaultListableBeanFactory的添加。

EncodeResource是对resource的封装,采用装饰者模式。主要增加了编码的信息。在很多时候,虽然两个类具有一定继承关系,但采用组合代替继承是更好的设计

 

[java] view plain copy
 
 技术分享技术分享
  1. public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {  
  2.     Assert.notNull(encodedResource, "EncodedResource must not be null");  
  3.     if (logger.isInfoEnabled()) {  
  4.         logger.info("Loading XML bean definitions from " + encodedResource.getResource());  
  5.     }  
  6.   
  7.     Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();  
  8.     if (currentResources == null) {  
  9.         currentResources = new HashSet<EncodedResource>(4);  
  10.         this.resourcesCurrentlyBeingLoaded.set(currentResources);  
  11.     }  
  12.     if (!currentResources.add(encodedResource)) {  
  13.         throw new BeanDefinitionStoreException(  
  14.                 "Detected cyclic loading of " + encodedResource + " - check your import definitions!");  
  15.     }  
  16.     try {  
  17.         InputStream inputStream = encodedResource.getResource().getInputStream();  
  18.         try {  
  19.             InputSource inputSource = new InputSource(inputStream);  
  20.             if (encodedResource.getEncoding() != null) {  
  21.                 inputSource.setEncoding(encodedResource.getEncoding());  
  22.             }  
  23.             return doLoadBeanDefinitions(inputSource, encodedResource.getResource());  
  24.         }  
  25.         finally {  
  26.             inputStream.close();  
  27.         }  
  28.     }  
  29.     catch (IOException ex) {  
  30.         throw new BeanDefinitionStoreException(  
  31.                 "IOException parsing XML document from " + encodedResource.getResource(), ex);  
  32.     }  
  33.     finally {  
  34.         currentResources.remove(encodedResource);  
  35.         if (currentResources.isEmpty()) {  
  36.             this.resourcesCurrentlyBeingLoaded.remove();  
  37.         }  
  38.     }  
  39. }  

该方法作用是将XML文件转化为BeanDefinitions。

这段代码意思是:

1,获取线程局部变量resourcesCurrentlyBeingLoaded,  final ThreadLocal<Set<EncodedResource>>类型。

      将当前要加载的Source,放入final ThreadLocal<Set<EncodedResource>>,若无法放入则抛出异常。

2,核心,真正的去加载Resource:

InputStream inputStream = encodedResource.getResource().getInputStream();
try {
        InputSource inputSource = new InputSource(inputStream);
        if (encodedResource.getEncoding() != null) {
                inputSource.setEncoding(encodedResource.getEncoding());
        }
        return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
       inputStream.close();
}

3,将加载过的Resource从resourcesCurrentlyBeingLoaded删除。

 

这里面1和3涉及多线程操作,这里面了解下java的ThreadLocal:ThreadLocal是指线程类的局部变量,他可以保证每一个线程都保有一份自己的局部变量的副本,线程之间不会对别的线程的ThreadLocal产生影响。

从代码上看,1和3的意义就是用ThreadLocal标注当前线程正在加载的Resource。

2是核心部分,调用doLoadBeanDefinitions(InputSource inputSource, Resource resource)方法

 

[java] view plain copy
 
 技术分享技术分享
  1. protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)  
  2.         throws BeanDefinitionStoreException {  
  3.     try {  
  4.         int validationMode = getValidationModeForResource(resource);  
  5.         Document doc = this.documentLoader.loadDocument(  
  6.                 inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());  
  7.         return registerBeanDefinitions(doc, resource);  
  8.     }  
  9.     catch (BeanDefinitionStoreException ex) {  
  10.         throw ex;  
  11.     }  
  12.     catch (SAXParseException ex) {  
  13.         throw new XmlBeanDefinitionStoreException(resource.getDescription(),  
  14.                 "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);  
  15.     }  
  16.     catch (SAXException ex) {  
  17.         throw new XmlBeanDefinitionStoreException(resource.getDescription(),  
  18.                 "XML document from " + resource + " is invalid", ex);  
  19.     }  
  20.     catch (ParserConfigurationException ex) {  
  21.         throw new BeanDefinitionStoreException(resource.getDescription(),  
  22.                 "Parser configuration exception parsing XML from " + resource, ex);  
  23.     }  
  24.     catch (IOException ex) {  
  25.         throw new BeanDefinitionStoreException(resource.getDescription(),  
  26.                 "IOException parsing XML document from " + resource, ex);  
  27.     }  
  28.     catch (Throwable ex) {  
  29.         throw new BeanDefinitionStoreException(resource.getDescription(),  
  30.                 "Unexpected exception parsing XML document from " + resource, ex);  
  31.     }  
  32. }  


关键是这三句:

 

int validationMode = getValidationModeForResource(resource);
Document doc = this.documentLoader.loadDocument(
                                                  inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
return registerBeanDefinitions(doc, resource);

继续看loadDocument方法代码:

 

[java] view plain copy
 
 技术分享技术分享
  1. public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,  
  2.         ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {  
  3.   
  4.     DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);  
  5.     if (logger.isDebugEnabled()) {  
  6.         logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");  
  7.     }  
  8.     DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);  
  9.     return builder.parse(inputSource);  
  10. }  

关于参数,entityResolver,解释起来有些麻烦,直接引用《spring源码深度解析》一书的文字吧:

技术分享

int validationMode = getValidationModeForResource(resource); 这句是获取对应资源的验证方式。两种验证模式:DTD、XSD

这里DocumentBuilder的创建方式体现了工厂模式。具体创建是靠DocumentBuilderFactory factory作为参数。而factory的创建是方法protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware)

DocumentBuilderFactory和DocumentBuilder都是抽象类,真正实例化的是对抽象类的实现类。

不管怎么样,它return builder.parse(inputSource)   return的是一个Document类。

Document接口注释:

 * The <code>Document</code> interface represents the entire HTML or XML
 * document. Conceptually, it is the root of the document tree, and provides
 * the primary access to the document‘s data.

而Document接口又是继承了Node接口。

loadDocument方法就是将文件转化为Document类的过程。

继续看代码:

[java] view plain copy
 
 技术分享技术分享
  1. public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {  
  2.     // Read document based on new BeanDefinitionDocumentReader SPI.  
  3.     BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();  
  4.     int countBefore = getRegistry().getBeanDefinitionCount();  
  5.     documentReader.registerBeanDefinitions(doc, createReaderContext(resource));  
  6.     return getRegistry().getBeanDefinitionCount() - countBefore;  
  7. }  



 

 

[java] view plain copy
 
 技术分享技术分享
  1. public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {  
  2.     this.readerContext = readerContext;  
  3.   
  4.     logger.debug("Loading bean definitions");  
  5.     Element root = doc.getDocumentElement();  
  6.   
  7.     BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);  
  8.   
  9.     preProcessXml(root);  
  10.     parseBeanDefinitions(root, delegate);  
  11.     postProcessXml(root);  
  12. }  
  13.   
  14. protected BeanDefinitionParserDelegate createHelper(XmlReaderContext readerContext, Element root) {  
  15.     BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);  
  16.     delegate.initDefaults(root);  
  17.     return delegate;  
  18. }  

Element root = doc.getDocumentElement();获取根节点Element。

 

/**
 * The <code>Element</code> interface represents an element in an HTML or XML
 * document. Elements may have attributes associated with them; since the
 * <code>Element</code> interface inherits from <code>Node</code>, the
 * generic <code>Node</code> interface attribute <code>attributes</code> may
 * be used to retrieve the set of all attributes for an element. There are
 * methods on the <code>Element</code> interface to retrieve either an
 * <code>Attr</code> object by name or an attribute value by name. In XML,
 * where an attribute value may contain entity references, an
 * <code>Attr</code> object should be retrieved to examine the possibly
 * fairly complex sub-tree representing the attribute value. On the other
 * hand, in HTML, where all attributes have simple string values, methods to
 * directly access an attribute value can safely be used as a convenience.
 * <p ><b>Note:</b> In DOM Level 2, the method <code>normalize</code> is
 * inherited from the <code>Node</code> interface where it was moved.
 * <p>See also the <a href=‘http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407‘>Document Object Model (DOM) Level 3 Core Specification</a>.
 */
public interface Element extends Node{……}

 

而这里的BeanDefinitionParserDelegate delegate是用来做转换工作。

spring源码的阅读工作就是一层套一层……然而并不难搞懂

理解下面的代码必须要提及spring XML配置里有两种bean的声明,一种是默认的<bean id = "test" class = "test.TestBean"/>另一种就是自定义的:<tx:annotation-driven/>:

 

[java] view plain copy
 
 技术分享技术分享
  1. /** 
  2.  * Parse the elements at the root level in the document: 
  3.  * "import", "alias", "bean". 
  4.  * @param root the DOM root element of the document 
  5.  */  
  6. protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {  
  7.                //如果是默认方式声明bean  
  8.     if (delegate.isDefaultNamespace(root)) {  
  9.         NodeList nl = root.getChildNodes();  
  10.         for (int i = 0; i < nl.getLength(); i++) {  
  11.             Node node = nl.item(i);  
  12.             if (node instanceof Element) {  
  13.                 Element ele = (Element) node;  
  14.                 if (delegate.isDefaultNamespace(ele)) {  
  15.                     parseDefaultElement(ele, delegate);  
  16.                 }  
  17.                 else {  
  18.                     delegate.parseCustomElement(ele);  
  19.                 }  
  20.             }  
  21.         }  
  22.     }  
  23.                //自定义方式声明bean  
  24.     else {  
  25.         delegate.parseCustomElement(root);  
  26.     }  
  27. }  



 

这里是从根节点,开始转换。

继续看核心操作parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)方法:

 

[java] view plain copy
 
 技术分享技术分享
  1. private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {  
  2.     if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {  
  3.         importBeanDefinitionResource(ele);  
  4.     }  
  5.     else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {  
  6.         processAliasRegistration(ele);  
  7.     }  
  8.     else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {  
  9.         processBeanDefinition(ele, delegate);  
  10.     }  
  11. }  


看代码感觉这是在根据节点名称类型选择注册操作,继续看void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)方法:

 

 

[java] view plain copy
 
 技术分享技术分享
  1. /** 
  2.  * Process the given bean element, parsing the bean definition 
  3.  * and registering it with the registry. 
  4.  */  
  5. protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {  
  6.     BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);  
  7.     if (bdHolder != null) {  
  8.         bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);  
  9.         try {  
  10.             // Register the final decorated instance.  
  11.             BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());  
  12.         }  
  13.         catch (BeanDefinitionStoreException ex) {  
  14.             getReaderContext().error("Failed to register bean definition with name ‘" +  
  15.                     bdHolder.getBeanName() + "‘", ele, ex);  
  16.         }  
  17.         // Send registration event.  
  18.         getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));  
  19.     }  
  20. }  

这里BeanDefinitionHolder也是采用了装饰者模式。包含了BeanDefinition,添加了:

 

private final String beanName;

private final String[] aliases;
两个私有final变量。

 

另外注意BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());这句。

 

[java] view plain copy
 
 技术分享技术分享
  1. public static void registerBeanDefinition(  
  2.         BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)  
  3.         throws BeanDefinitionStoreException {  
  4.   
  5.     // Register bean definition under primary name.  
  6.     String beanName = definitionHolder.getBeanName();  
  7.     registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());  
  8.   
  9.     // Register aliases for bean name, if any.  
  10.     String[] aliases = definitionHolder.getAliases();  
  11.     if (aliases != null) {  
  12.         for (String aliase : aliases) {  
  13.             registry.registerAlias(beanName, aliase);  
  14.         }  
  15.     }  
  16. }  

BeanDefinitionRegistry是XMLBeanFactory的基类之一。设置断点跟踪,我们可以发现,进入这个方法,传进来的类实例正是XmlBeanFactory。接下来调用的是XmlBeanFactory类的方法,registerBeanDefinition。方法内部调用的这里是真正的注册的实现:将BeanDefinition添加的,Spring的BeanFactory容器里,一个Map数据结构:

 

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

 

 

[java] view plain copy
 
 技术分享技术分享
  1. public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)  
  2.         throws BeanDefinitionStoreException {  
  3.   
  4.     Assert.hasText(beanName, "Bean name must not be empty");  
  5.     Assert.notNull(beanDefinition, "BeanDefinition must not be null");  
  6.   
  7.     if (beanDefinition instanceof AbstractBeanDefinition) {  
  8.         try {  
  9.             ((AbstractBeanDefinition) beanDefinition).validate();  
  10.         }  
  11.         catch (BeanDefinitionValidationException ex) {  
  12.             throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,  
  13.                     "Validation of bean definition failed", ex);  
  14.         }  
  15.     }  
  16.   
  17.     synchronized (this.beanDefinitionMap) {  
  18.         Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);  
  19.         if (oldBeanDefinition != null) {  
  20.             if (!this.allowBeanDefinitionOverriding) {  
  21.                 throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,  
  22.                         "Cannot register bean definition [" + beanDefinition + "] for bean ‘" + beanName +  
  23.                         "‘: There is already [" + oldBeanDefinition + "] bound.");  
  24.             }  
  25.             else {  
  26.                 if (this.logger.isInfoEnabled()) {  
  27.                     this.logger.info("Overriding bean definition for bean ‘" + beanName +  
  28.                             "‘: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");  
  29.                 }  
  30.             }  
  31.         }  
  32.         else {  
  33.             this.beanDefinitionNames.add(beanName);  
  34.             this.frozenBeanDefinitionNames = null;  
  35.         }  
  36.         this.beanDefinitionMap.put(beanName, beanDefinition);  
  37.   
  38.         resetBeanDefinition(beanName);  
  39.     }  
  40. }  

 

 

以上所述就是BeanFactory bf = new XmlBeanFactory(new ClassPathResource ("beans.xml"));这句代码背后的故事。

首先,ClassPathResource类封装了资源文件,作为构造函数参数来创建XmlBeanFactory。经过一系列复杂转换将XML文件转换为spring需要的数据结构~ BeanDefinition

 

对XML的解析和BeanDefinition就介绍到这,介绍的并不够绝对细致,主要是理解大意,另外也是spring源码确实比较繁杂。并且以后有了新的心得还会在这篇文章做修改补充。

 

接下来这句:Person bean = (Person) bf.getBean("person");

       代码的字面意思就是从spring容器里,获取person bean的实例对象。

这里要提到BeanFactory和ApplicationContext的区别:BeanFactory是采取延迟加载,只有当getBean的时候才会去加载、实例化这个对象。ApplicationContext则正相反,它是一次性加载所有bean。

getBean的最终实现是 AbstractBeanFactory的 doGetBean方法

 

[java] view plain copy
 
 技术分享技术分享
  1. @SuppressWarnings("unchecked")  
  2. protected <T> T doGetBean(  
  3.         final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)  
  4.         throws BeansException {  
  5.   
  6.     final String beanName = transformedBeanName(name);  
  7.     Object bean;  
  8.   
  9.     // Eagerly check singleton cache for manually registered singletons.  
  10.     Object sharedInstance = getSingleton(beanName);  
  11.     if (sharedInstance != null && args == null) {  
  12.         if (logger.isDebugEnabled()) {  
  13.             if (isSingletonCurrentlyInCreation(beanName)) {  
  14.                 logger.debug("Returning eagerly cached instance of singleton bean ‘" + beanName +  
  15.                         "‘ that is not fully initialized yet - a consequence of a circular reference");  
  16.             }  
  17.             else {  
  18.                 logger.debug("Returning cached instance of singleton bean ‘" + beanName + "‘");  
  19.             }  
  20.         }  
  21.         bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);  
  22.     }  
  23.   
  24.     else {  
  25.         // Fail if we‘re already creating this bean instance:  
  26.         // We‘re assumably within a circular reference.  
  27.         if (isPrototypeCurrentlyInCreation(beanName)) {  
  28.             throw new BeanCurrentlyInCreationException(beanName);  
  29.         }  
  30.   
  31.         // Check if bean definition exists in this factory.  
  32.         BeanFactory parentBeanFactory = getParentBeanFactory();  
  33.         if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {  
  34.             // Not found -> check parent.  
  35.             String nameToLookup = originalBeanName(name);  
  36.             if (args != null) {  
  37.                 // Delegation to parent with explicit args.  
  38.                 return (T) parentBeanFactory.getBean(nameToLookup, args);  
  39.             }  
  40.             else {  
  41.                 // No args -> delegate to standard getBean method.  
  42.                 return parentBeanFactory.getBean(nameToLookup, requiredType);  
  43.             }  
  44.         }  
  45.   
  46.         if (!typeCheckOnly) {  
  47.             markBeanAsCreated(beanName);  
  48.         }  
  49.   
  50.         final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);  
  51.         checkMergedBeanDefinition(mbd, beanName, args);  
  52.   
  53.         // Guarantee initialization of beans that the current bean depends on.  
  54.         String[] dependsOn = mbd.getDependsOn();  
  55.         if (dependsOn != null) {  
  56.             for (String dependsOnBean : dependsOn) {  
  57.                 getBean(dependsOnBean);  
  58.                 registerDependentBean(dependsOnBean, beanName);  
  59.             }  
  60.         }  
  61.   
  62.         // Create bean instance.  
  63.         if (mbd.isSingleton()) {  
  64.             sharedInstance = getSingleton(beanName, new ObjectFactory() {  
  65.                 public Object getObject() throws BeansException {  
  66.                     try {  
  67.                         return createBean(beanName, mbd, args);  
  68.                     }  
  69.                     catch (BeansException ex) {  
  70.                         // Explicitly remove instance from singleton cache: It might have been put there  
  71.                         // eagerly by the creation process, to allow for circular reference resolution.  
  72.                         // Also remove any beans that received a temporary reference to the bean.  
  73.                         destroySingleton(beanName);  
  74.                         throw ex;  
  75.                     }  
  76.                 }  
  77.             });  
  78.             bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);  
  79.         }  
  80.   
  81.         else if (mbd.isPrototype()) {  
  82.             // It‘s a prototype -> create a new instance.  
  83.             Object prototypeInstance = null;  
  84.             try {  
  85.                 beforePrototypeCreation(beanName);  
  86.                 prototypeInstance = createBean(beanName, mbd, args);  
  87.             }  
  88.             finally {  
  89.                 afterPrototypeCreation(beanName);  
  90.             }  
  91.             bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);  
  92.         }  
  93.   
  94.         else {  
  95.             String scopeName = mbd.getScope();  
  96.             final Scope scope = this.scopes.get(scopeName);  
  97.             if (scope == null) {  
  98.                 throw new IllegalStateException("No Scope registered for scope ‘" + scopeName + "‘");  
  99.             }  
  100.             try {  
  101.                 Object scopedInstance = scope.get(beanName, new ObjectFactory() {  
  102.                     public Object getObject() throws BeansException {  
  103.                         beforePrototypeCreation(beanName);  
  104.                         try {  
  105.                             return createBean(beanName, mbd, args);  
  106.                         }  
  107.                         finally {  
  108.                             afterPrototypeCreation(beanName);  
  109.                         }  
  110.                     }  
  111.                 });  
  112.                 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);  
  113.             }  
  114.             catch (IllegalStateException ex) {  
  115.                 throw new BeanCreationException(beanName,  
  116.                         "Scope ‘" + scopeName + "‘ is not active for the current thread; " +  
  117.                         "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",  
  118.                         ex);  
  119.             }  
  120.         }  
  121.     }  
  122.   
  123.     // Check if required type matches the type of the actual bean instance.  
  124.     if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {  
  125.         throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());  
  126.     }  
  127.     return (T) bean;  
  128. }  


看这个代码英文注释就明白了

 

1、Eagerly check singleton cache for manually registered singletons.

2、Check if bean definition exists in this factory.Not found -> check parent.(当前BeanFactory不存在,则通过递归,向上寻找。parentBeanFactory是XmlBeanFactory的成员变量。)

3、Guarantee initialization of beans that the current bean depends on.(生成依赖bean)

4、Create bean instance.(创建bean)(创建bean的过程会查看是singleton还是prototype,如果是singleton是单例模式,只会被创建一次,prototype则每次getBean相当于new一次。代码中首先通过Object sharedInstance = getSingleton(beanName);根据bean名称获取单例对象,若为空再创建);

 

 

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

 

通过注解理解其意义:

// Make sure bean class is actually resolved at this point.(确保bean类此时已被分解)
resolveBeanClass(mbd, beanName);

// Prepare method overrides.(准备实现接口的方法)

mbd.prepareMethodOverrides();

// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.(如果可能的话,返回一个代理而不是实例的对象)
Object bean = resolveBeforeInstantiation(beanName, mbd);

最后这里才是真正核心的实例化bean的方法:

Object beanInstance = doCreateBean(beanName, mbd, args);

doCreateBean中有两个重要的方法,一个是createBeanInstance,用于实例化bean。

另一个是这句populateBean(beanName, mbd, instanceWrapper);这个方法用于依赖关系的处理过程。

 

 

[java] view plain copy
 
 技术分享技术分享
  1. /** 
  2.  * Actually create the specified bean. Pre-creation processing has already happened 
  3.  * at this point, e.g. checking <code>postProcessBeforeInstantiation</code> callbacks. 
  4.  * <p>Differentiates between default bean instantiation, use of a 
  5.  * factory method, and autowiring a constructor. 
  6.  * @param beanName the name of the bean 
  7.  * @param mbd the merged bean definition for the bean 
  8.  * @param args arguments to use if creating a prototype using explicit arguments to a 
  9.  * static factory method. This parameter must be <code>null</code> except in this case. 
  10.  * @return a new instance of the bean 
  11.  * @throws BeanCreationException if the bean could not be created 
  12.  * @see #instantiateBean 
  13.  * @see #instantiateUsingFactoryMethod 
  14.  * @see #autowireConstructor 
  15.  */  
  16. protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {  
  17.     // Instantiate the bean.  
  18.     BeanWrapper instanceWrapper = null;  
  19.     if (mbd.isSingleton()) {  
  20.         instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);  
  21.     }  
  22.     if (instanceWrapper == null) {  
  23.         instanceWrapper = createBeanInstance(beanName, mbd, args);  
  24.     }  
  25.     final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);  
  26.     Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);  
  27.   
  28.     // Allow post-processors to modify the merged bean definition.  
  29.     synchronized (mbd.postProcessingLock) {  
  30.         if (!mbd.postProcessed) {  
  31.             applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);  
  32.             mbd.postProcessed = true;  
  33.         }  
  34.     }  
  35.   
  36.     // Eagerly cache singletons to be able to resolve circular references  
  37.     // even when triggered by lifecycle interfaces like BeanFactoryAware.  
  38.     boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&  
  39.             isSingletonCurrentlyInCreation(beanName));  
  40.     if (earlySingletonExposure) {  
  41.         if (logger.isDebugEnabled()) {  
  42.             logger.debug("Eagerly caching bean ‘" + beanName +  
  43.                     "‘ to allow for resolving potential circular references");  
  44.         }  
  45.         addSingletonFactory(beanName, new ObjectFactory() {  
  46.             public Object getObject() throws BeansException {  
  47.                 return getEarlyBeanReference(beanName, mbd, bean);  
  48.             }  
  49.         });  
  50.     }  
  51.   
  52.     // Initialize the bean instance.  
  53.     Object exposedObject = bean;  
  54.     try {  
  55.         populateBean(beanName, mbd, instanceWrapper);  
  56.         if (exposedObject != null) {  
  57.             exposedObject = initializeBean(beanName, exposedObject, mbd);  
  58.         }  
  59.     }  
  60.     catch (Throwable ex) {  
  61.         if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {  
  62.             throw (BeanCreationException) ex;  
  63.         }  
  64.         else {  
  65.             throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);  
  66.         }  
  67.     }  
  68.   
  69.     if (earlySingletonExposure) {  
  70.         Object earlySingletonReference = getSingleton(beanName, false);  
  71.         if (earlySingletonReference != null) {  
  72.             if (exposedObject == bean) {  
  73.                 exposedObject = earlySingletonReference;  
  74.             }  
  75.             else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {  
  76.                 String[] dependentBeans = getDependentBeans(beanName);  
  77.                 Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);  
  78.                 for (String dependentBean : dependentBeans) {  
  79.                     if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {  
  80.                         actualDependentBeans.add(dependentBean);  
  81.                     }  
  82.                 }  
  83.                 if (!actualDependentBeans.isEmpty()) {  
  84.                     throw new BeanCurrentlyInCreationException(beanName,  
  85.                             "Bean with name ‘" + beanName + "‘ has been injected into other beans [" +  
  86.                             StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +  
  87.                             "] in its raw version as part of a circular reference, but has eventually been " +  
  88.                             "wrapped. This means that said other beans do not use the final version of the " +  
  89.                             "bean. This is often the result of over-eager type matching - consider using " +  
  90.                             "‘getBeanNamesOfType‘ with the ‘allowEagerInit‘ flag turned off, for example.");  
  91.                 }  
  92.             }  
  93.         }  
  94.     }  
  95.   
  96.     // Register bean as disposable.  
  97.     try {  
  98.         registerDisposableBeanIfNecessary(beanName, bean, mbd);  
  99.     }  
  100.     catch (BeanDefinitionValidationException ex) {  
  101.         throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);  
  102.     }  
  103.   
  104.     return exposedObject;  
  105. }  


这里面createBeanInstance方法用于实例化bean。下面可以看到实例化的bean的方式不止一种,有工厂方法方式,也有构造方法方式。主要根据BeanDefinition中的信息。

 

 

[java] view plain copy
 
 技术分享技术分享
  1. /** 
  2.  * Create a new instance for the specified bean, using an appropriate instantiation strategy: 
  3.  * factory method, constructor autowiring, or simple instantiation. 
  4.  * @param beanName the name of the bean 
  5.  * @param mbd the bean definition for the bean 
  6.  * @param args arguments to use if creating a prototype using explicit arguments to a 
  7.  * static factory method. It is invalid to use a non-null args value in any other case. 
  8.  * @return BeanWrapper for the new instance 
  9.  * @see #instantiateUsingFactoryMethod 
  10.  * @see #autowireConstructor 
  11.  * @see #instantiateBean 
  12.  */  
  13. protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {  
  14.     // Make sure bean class is actually resolved at this point.  
  15.     Class beanClass = resolveBeanClass(mbd, beanName);  
  16.   
  17.     if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {  
  18.         throw new BeanCreationException(mbd.getResourceDescription(), beanName,  
  19.                 "Bean class isn‘t public, and non-public access not allowed: " + beanClass.getName());  
  20.     }  
  21.   
  22.     if (mbd.getFactoryMethodName() != null)  {  
  23.         return instantiateUsingFactoryMethod(beanName, mbd, args);  
  24.     }  
  25.   
  26.     // Shortcut when re-creating the same bean...  
  27.     boolean resolved = false;  
  28.     boolean autowireNecessary = false;  
  29.     if (args == null) {  
  30.         synchronized (mbd.constructorArgumentLock) {  
  31.             if (mbd.resolvedConstructorOrFactoryMethod != null) {  
  32.                 resolved = true;  
  33.                 autowireNecessary = mbd.constructorArgumentsResolved;  
  34.             }  
  35.         }  
  36.     }  
  37.     if (resolved) {  
  38.         if (autowireNecessary) {  
  39.             return autowireConstructor(beanName, mbd, null, null);  
  40.         }  
  41.         else {  
  42.             return instantiateBean(beanName, mbd);  
  43.         }  
  44.     }  
  45.   
  46.     // Need to determine the constructor...  
  47.     Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);  
  48.     if (ctors != null ||  
  49.             mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||  
  50.             mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {  
  51.         return autowireConstructor(beanName, mbd, ctors, args);  
  52.     }  
  53.   
  54.     // No special handling: simply use no-arg constructor.  
  55.     return instantiateBean(beanName, mbd);  
  56. }  

工厂方法模式:

 

 

[java] view plain copy
 
 技术分享技术分享
  1. /** 
  2.  * Instantiate the bean using a named factory method. The method may be static, if the 
  3.  * bean definition parameter specifies a class, rather than a "factory-bean", or 
  4.  * an instance variable on a factory object itself configured using Dependency Injection. 
  5.  * <p>Implementation requires iterating over the static or instance methods with the 
  6.  * name specified in the RootBeanDefinition (the method may be overloaded) and trying 
  7.  * to match with the parameters. We don‘t have the types attached to constructor args, 
  8.  * so trial and error is the only way to go here. The explicitArgs array may contain 
  9.  * argument values passed in programmatically via the corresponding getBean method. 
  10.  * @param beanName the name of the bean 
  11.  * @param mbd the merged bean definition for the bean 
  12.  * @param explicitArgs argument values passed in programmatically via the getBean 
  13.  * method, or <code>null</code> if none (-> use constructor argument values from bean definition) 
  14.  * @return a BeanWrapper for the new instance 
  15.  */  
  16. public BeanWrapper instantiateUsingFactoryMethod(final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) {  
  17.     BeanWrapperImpl bw = new BeanWrapperImpl();  
  18.     this.beanFactory.initBeanWrapper(bw);  
  19.   
  20.     Object factoryBean;  
  21.     Class factoryClass;  
  22.     boolean isStatic;  
  23.   
  24.     String factoryBeanName = mbd.getFactoryBeanName();  
  25.     if (factoryBeanName != null) {  
  26.         if (factoryBeanName.equals(beanName)) {  
  27.             throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,  
  28.                     "factory-bean reference points back to the same bean definition");  
  29.         }  
  30.         factoryBean = this.beanFactory.getBean(factoryBeanName);  
  31.         if (factoryBean == null) {  
  32.             throw new BeanCreationException(mbd.getResourceDescription(), beanName,  
  33.                     "factory-bean ‘" + factoryBeanName + "‘ returned null");  
  34.         }  
  35.         factoryClass = factoryBean.getClass();  
  36.         isStatic = false;  
  37.     }  
  38.     else {  
  39.         // It‘s a static factory method on the bean class.  
  40.         if (!mbd.hasBeanClass()) {  
  41.             throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,  
  42.                     "bean definition declares neither a bean class nor a factory-bean reference");  
  43.         }  
  44.         factoryBean = null;  
  45.         factoryClass = mbd.getBeanClass();  
  46.         isStatic = true;  
  47.     }  
  48.   
  49.     Method factoryMethodToUse = null;  
  50.     ArgumentsHolder argsHolderToUse = null;  
  51.     Object[] argsToUse = null;  
  52.   
  53.     if (explicitArgs != null) {  
  54.         argsToUse = explicitArgs;  
  55.     }  
  56.     else {  
  57.         Object[] argsToResolve = null;  
  58.         synchronized (mbd.constructorArgumentLock) {  
  59.             factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;  
  60.             if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {  
  61.                 // Found a cached factory method...  
  62.                 argsToUse = mbd.resolvedConstructorArguments;  
  63.                 if (argsToUse == null) {  
  64.                     argsToResolve = mbd.preparedConstructorArguments;  
  65.                 }  
  66.             }  
  67.         }  
  68.         if (argsToResolve != null) {  
  69.             argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve);  
  70.         }  
  71.     }  
  72.   
  73.     if (factoryMethodToUse == null || argsToUse == null) {  
  74.         // Need to determine the factory method...  
  75.         // Try all methods with this name to see if they match the given arguments.  
  76.         factoryClass = ClassUtils.getUserClass(factoryClass);  
  77.         Method[] rawCandidates;  
  78.   
  79.         final Class factoryClazz = factoryClass;  
  80.         if (System.getSecurityManager() != null) {  
  81.             rawCandidates = AccessController.doPrivileged(new PrivilegedAction<Method[]>() {  
  82.                 public Method[] run() {  
  83.                     return (mbd.isNonPublicAccessAllowed() ?  
  84.                             ReflectionUtils.getAllDeclaredMethods(factoryClazz) : factoryClazz.getMethods());  
  85.                 }  
  86.             });  
  87.         }  
  88.         else {  
  89.             rawCandidates = (mbd.isNonPublicAccessAllowed() ?  
  90.                     ReflectionUtils.getAllDeclaredMethods(factoryClazz) : factoryClazz.getMethods());  
  91.         }  
  92.           
  93.         List<Method> candidateSet = new ArrayList<Method>();  
  94.         for (Method candidate : rawCandidates) {  
  95.             if (Modifier.isStatic(candidate.getModifiers()) == isStatic &&  
  96.                     candidate.getName().equals(mbd.getFactoryMethodName()) &&  
  97.                     mbd.isFactoryMethod(candidate)) {  
  98.                 candidateSet.add(candidate);  
  99.             }  
  100.         }  
  101.         Method[] candidates = candidateSet.toArray(new Method[candidateSet.size()]);  
  102.         AutowireUtils.sortFactoryMethods(candidates);  
  103.   
  104.         ConstructorArgumentValues resolvedValues = null;  
  105.         boolean autowiring = (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);  
  106.         int minTypeDiffWeight = Integer.MAX_VALUE;  
  107.         Set<Method> ambiguousFactoryMethods = null;  
  108.   
  109.         int minNrOfArgs;  
  110.         if (explicitArgs != null) {  
  111.             minNrOfArgs = explicitArgs.length;  
  112.         }  
  113.         else {  
  114.             // We don‘t have arguments passed in programmatically, so we need to resolve the  
  115.             // arguments specified in the constructor arguments held in the bean definition.  
  116.             ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();  
  117.             resolvedValues = new ConstructorArgumentValues();  
  118.             minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);  
  119.         }  
  120.   
  121.         List<Exception> causes = null;  
  122.   
  123.         for (int i = 0; i < candidates.length; i++) {  
  124.             Method candidate = candidates[i];  
  125.             Class[] paramTypes = candidate.getParameterTypes();  
  126.   
  127.             if (paramTypes.length >= minNrOfArgs) {  
  128.                 ArgumentsHolder argsHolder;  
  129.   
  130.                 if (resolvedValues != null) {  
  131.                     // Resolved constructor arguments: type conversion and/or autowiring necessary.  
  132.                     try {  
  133.                         String[] paramNames = null;  
  134.                         ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();  
  135.                         if (pnd != null) {  
  136.                             paramNames = pnd.getParameterNames(candidate);  
  137.                         }  
  138.                         argsHolder = createArgumentArray(  
  139.                                 beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);  
  140.                     }  
  141.                     catch (UnsatisfiedDependencyException ex) {  
  142.                         if (this.beanFactory.logger.isTraceEnabled()) {  
  143.                             this.beanFactory.logger.trace("Ignoring factory method [" + candidate +  
  144.                                     "] of bean ‘" + beanName + "‘: " + ex);  
  145.                         }  
  146.                         if (i == candidates.length - 1 && argsHolderToUse == null) {  
  147.                             if (causes != null) {  
  148.                                 for (Exception cause : causes) {  
  149.                                     this.beanFactory.onSuppressedException(cause);  
  150.                                 }  
  151.                             }  
  152.                             throw ex;  
  153.                         }  
  154.                         else {  
  155.                             // Swallow and try next overloaded factory method.  
  156.                             if (causes == null) {  
  157.                                 causes = new LinkedList<Exception>();  
  158.                             }  
  159.                             causes.add(ex);  
  160.                             continue;  
  161.                         }  
  162.                     }  
  163.                 }  
  164.   
  165.                 else {  
  166.                     // Explicit arguments given -> arguments length must match exactly.  
  167.                     if (paramTypes.length != explicitArgs.length) {  
  168.                         continue;  
  169.                     }  
  170.                     argsHolder = new ArgumentsHolder(explicitArgs);  
  171.                 }  
  172.   
  173.                 int typeDiffWeight = (mbd.isLenientConstructorResolution() ?  
  174.                         argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));  
  175.                 // Choose this factory method if it represents the closest match.  
  176.                 if (typeDiffWeight < minTypeDiffWeight) {  
  177.                     factoryMethodToUse = candidate;  
  178.                     argsHolderToUse = argsHolder;  
  179.                     argsToUse = argsHolder.arguments;  
  180.                     minTypeDiffWeight = typeDiffWeight;  
  181.                     ambiguousFactoryMethods = null;  
  182.                 }  
  183.                 else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight) {  
  184.                     if (ambiguousFactoryMethods == null) {  
  185.                         ambiguousFactoryMethods = new LinkedHashSet<Method>();  
  186.                         ambiguousFactoryMethods.add(factoryMethodToUse);  
  187.                     }  
  188.                     ambiguousFactoryMethods.add(candidate);  
  189.                 }  
  190.             }  
  191.         }  
  192.   
  193.         if (factoryMethodToUse == null) {  
  194.             boolean hasArgs = (resolvedValues.getArgumentCount() > 0);  
  195.             String argDesc = "";  
  196.             if (hasArgs) {  
  197.                 List<String> argTypes = new ArrayList<String>();  
  198.                 for (ValueHolder value : resolvedValues.getIndexedArgumentValues().values()) {  
  199.                     String argType = (value.getType() != null ?  
  200.                             ClassUtils.getShortName(value.getType()) : value.getValue().getClass().getSimpleName());  
  201.                     argTypes.add(argType);  
  202.                 }  
  203.                 argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);  
  204.             }  
  205.             throw new BeanCreationException(mbd.getResourceDescription(), beanName,  
  206.                     "No matching factory method found: " +  
  207.                     (mbd.getFactoryBeanName() != null ?  
  208.                         "factory bean ‘" + mbd.getFactoryBeanName() + "‘; " : "") +  
  209.                     "factory method ‘" + mbd.getFactoryMethodName() + "(" + argDesc + ")‘. " +  
  210.                     "Check that a method with the specified name " +  
  211.                     (hasArgs ? "and arguments " : "") +  
  212.                     "exists and that it is " +  
  213.                     (isStatic ? "static" : "non-static") + ".");  
  214.         }  
  215.         else if (void.class.equals(factoryMethodToUse.getReturnType())) {  
  216.             throw new BeanCreationException(mbd.getResourceDescription(), beanName,  
  217.                     "Invalid factory method ‘" + mbd.getFactoryMethodName() +  
  218.                     "‘: needs to have a non-void return type!");  
  219.         }  
  220.         else if (ambiguousFactoryMethods != null && !mbd.isLenientConstructorResolution()) {  
  221.             throw new BeanCreationException(mbd.getResourceDescription(), beanName,  
  222.                     "Ambiguous factory method matches found in bean ‘" + beanName + "‘ " +  
  223.                     "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +  
  224.                     ambiguousFactoryMethods);  
  225.         }  
  226.   
  227.         if (explicitArgs == null && argsHolderToUse != null) {  
  228.             argsHolderToUse.storeCache(mbd, factoryMethodToUse);  
  229.         }  
  230.     }  
  231.   
  232.     try {  
  233.         Object beanInstance;  
  234.   
  235.         if (System.getSecurityManager() != null) {  
  236.             final Object fb = factoryBean;  
  237.             final Method factoryMethod = factoryMethodToUse;  
  238.             final Object[] args = argsToUse;  
  239.             beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {  
  240.                 public Object run() {  
  241.                     return beanFactory.getInstantiationStrategy().instantiate(  
  242.                             mbd, beanName, beanFactory, fb, factoryMethod, args);  
  243.                 }  
  244.             }, beanFactory.getAccessControlContext());  
  245.         }  
  246.         else {  
  247.             beanInstance = beanFactory.getInstantiationStrategy().instantiate(  
  248.                     mbd, beanName, beanFactory, factoryBean, factoryMethodToUse, argsToUse);  
  249.         }  
  250.           
  251.         if (beanInstance == null) {  
  252.             return null;  
  253.         }  
  254.         bw.setWrappedInstance(beanInstance);  
  255.         return bw;  
  256.     }  
  257.     catch (Throwable ex) {  
  258.         throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);  
  259.     }  
  260. }  

 

构造函数方式:

[java] view plain copy
 
 技术分享技术分享
  1. /** 
  2.  * "autowire constructor" (with constructor arguments by type) behavior. 
  3.  * Also applied if explicit constructor argument values are specified, 
  4.  * matching all remaining arguments with beans from the bean factory. 
  5.  * <p>This corresponds to constructor injection: In this mode, a Spring 
  6.  * bean factory is able to host components that expect constructor-based 
  7.  * dependency resolution. 
  8.  * @param beanName the name of the bean 
  9.  * @param mbd the merged bean definition for the bean 
  10.  * @param chosenCtors chosen candidate constructors (or <code>null</code> if none) 
  11.  * @param explicitArgs argument values passed in programmatically via the getBean method, 
  12.  * or <code>null</code> if none (-> use constructor argument values from bean definition) 
  13.  * @return a BeanWrapper for the new instance 
  14.  */  
  15. public BeanWrapper autowireConstructor(  
  16.         final String beanName, final RootBeanDefinition mbd, Constructor[] chosenCtors, final Object[] explicitArgs) {  
  17.   
  18.     BeanWrapperImpl bw = new BeanWrapperImpl();  
  19.     this.beanFactory.initBeanWrapper(bw);  
  20.   
  21.     Constructor constructorToUse = null;  
  22.     ArgumentsHolder argsHolderToUse = null;  
  23.     Object[] argsToUse = null;  
  24.   
  25.     if (explicitArgs != null) {  
  26.         argsToUse = explicitArgs;  
  27.     }  
  28.     else {  
  29.         Object[] argsToResolve = null;  
  30.         synchronized (mbd.constructorArgumentLock) {  
  31.             constructorToUse = (Constructor) mbd.resolvedConstructorOrFactoryMethod;  
  32.             if (constructorToUse != null && mbd.constructorArgumentsResolved) {  
  33.                 // Found a cached constructor...  
  34.                 argsToUse = mbd.resolvedConstructorArguments;  
  35.                 if (argsToUse == null) {  
  36.                     argsToResolve = mbd.preparedConstructorArguments;  
  37.                 }  
  38.             }  
  39.         }  
  40.         if (argsToResolve != null) {  
  41.             argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);  
  42.         }  
  43.     }  
  44.   
  45.     if (constructorToUse == null) {  
  46.         // Need to resolve the constructor.  
  47.         boolean autowiring = (chosenCtors != null ||  
  48.                 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);  
  49.         ConstructorArgumentValues resolvedValues = null;  
  50.   
  51.         int minNrOfArgs;  
  52.         if (explicitArgs != null) {  
  53.             minNrOfArgs = explicitArgs.length;  
  54.         }  
  55.         else {  
  56.             ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();  
  57.             resolvedValues = new ConstructorArgumentValues();  
  58.             minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);  
  59.         }  
  60.   
  61.         // Take specified constructors, if any.  
  62.         Constructor[] candidates = chosenCtors;  
  63.         if (candidates == null) {  
  64.             Class beanClass = mbd.getBeanClass();  
  65.             try {  
  66.                 candidates = (mbd.isNonPublicAccessAllowed() ?  
  67.                         beanClass.getDeclaredConstructors() : beanClass.getConstructors());  
  68.             }  
  69.             catch (Throwable ex) {  
  70.                 throw new BeanCreationException(mbd.getResourceDescription(), beanName,  
  71.                         "Resolution of declared constructors on bean Class [" + beanClass.getName() +  
  72.                                 "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);  
  73.             }  
  74.         }  
  75.         AutowireUtils.sortConstructors(candidates);  
  76.         int minTypeDiffWeight = Integer.MAX_VALUE;  
  77.         Set<Constructor> ambiguousConstructors = null;  
  78.         List<Exception> causes = null;  
  79.   
  80.         for (int i = 0; i < candidates.length; i++) {  
  81.             Constructor<?> candidate = candidates[i];  
  82.             Class[] paramTypes = candidate.getParameterTypes();  
  83.   
  84.             if (constructorToUse != null && argsToUse.length > paramTypes.length) {  
  85.                 // Already found greedy constructor that can be satisfied ->  
  86.                 // do not look any further, there are only less greedy constructors left.  
  87.                 break;  
  88.             }  
  89.             if (paramTypes.length < minNrOfArgs) {  
  90.                 continue;  
  91.             }  
  92.   
  93.             ArgumentsHolder argsHolder;  
  94.             if (resolvedValues != null) {  
  95.                 try {  
  96.                     String[] paramNames = null;  
  97.                     if (constructorPropertiesAnnotationAvailable) {  
  98.                         paramNames = ConstructorPropertiesChecker.evaluateAnnotation(candidate, paramTypes.length);  
  99.                     }  
  100.                     if (paramNames == null) {  
  101.                         ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();  
  102.                         if (pnd != null) {  
  103.                             paramNames = pnd.getParameterNames(candidate);  
  104.                         }  
  105.                     }  
  106.                     argsHolder = createArgumentArray(  
  107.                             beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);  
  108.                 }  
  109.                 catch (UnsatisfiedDependencyException ex) {  
  110.                     if (this.beanFactory.logger.isTraceEnabled()) {  
  111.                         this.beanFactory.logger.trace(  
  112.                                 "Ignoring constructor [" + candidate + "] of bean ‘" + beanName + "‘: " + ex);  
  113.                     }  
  114.                     if (i == candidates.length - 1 && constructorToUse == null) {  
  115.                         if (causes != null) {  
  116.                             for (Exception cause : causes) {  
  117.                                 this.beanFactory.onSuppressedException(cause);  
  118.                             }  
  119.                         }  
  120.                         throw ex;  
  121.                     }  
  122.                     else {  
  123.                         // Swallow and try next constructor.  
  124.                         if (causes == null) {  
  125.                             causes = new LinkedList<Exception>();  
  126.                         }  
  127.                         causes.add(ex);  
  128.                         continue;  
  129.                     }  
  130.                 }  
  131.             }  
  132.             else {  
  133.                 // Explicit arguments given -> arguments length must match exactly.  
  134.                 if (paramTypes.length != explicitArgs.length) {  
  135.                     continue;  
  136.                 }  
  137.                 argsHolder = new ArgumentsHolder(explicitArgs);  
  138.             }  
  139.   
  140.             int typeDiffWeight = (mbd.isLenientConstructorResolution() ?  
  141.                     argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));  
  142.             // Choose this constructor if it represents the closest match.  
  143.             if (typeDiffWeight < minTypeDiffWeight) {  
  144.                 constructorToUse = candidate;  
  145.                 argsHolderToUse = argsHolder;  
  146.                 argsToUse = argsHolder.arguments;  
  147.                 minTypeDiffWeight = typeDiffWeight;  
  148.                 ambiguousConstructors = null;  
  149.             }  
  150.             else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {  
  151.                 if (ambiguousConstructors == null) {  
  152.                     ambiguousConstructors = new LinkedHashSet<Constructor>();  
  153.                     ambiguousConstructors.add(constructorToUse);  
  154.                 }  
  155.                 ambiguousConstructors.add(candidate);  
  156.             }  
  157.         }  
  158.   
  159.         if (constructorToUse == null) {  
  160.             throw new BeanCreationException(mbd.getResourceDescription(), beanName,  
  161.                     "Could not resolve matching constructor " +  
  162.                     "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");  
  163.         }  
  164.         else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {  
  165.             throw new BeanCreationException(mbd.getResourceDescription(), beanName,  
  166.                     "Ambiguous constructor matches found in bean ‘" + beanName + "‘ " +  
  167.                     "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +  
  168.                     ambiguousConstructors);  
  169.         }  
  170.   
  171.         if (explicitArgs == null) {  
  172.             argsHolderToUse.storeCache(mbd, constructorToUse);  
  173.         }  
  174.     }  
  175.   
  176.     try {  
  177.         Object beanInstance;  
  178.   
  179.         if (System.getSecurityManager() != null) {  
  180.             final Constructor ctorToUse = constructorToUse;  
  181.             final Object[] argumentsToUse = argsToUse;  
  182.             beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {  
  183.                 public Object run() {  
  184.                     return beanFactory.getInstantiationStrategy().instantiate(  
  185.                             mbd, beanName, beanFactory, ctorToUse, argumentsToUse);  
  186.                 }  
  187.             }, beanFactory.getAccessControlContext());  
  188.         }  
  189.         else {  
  190.             beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(  
  191.                     mbd, beanName, this.beanFactory, constructorToUse, argsToUse);  
  192.         }  
  193.           
  194.         bw.setWrappedInstance(beanInstance);  
  195.         return bw;  
  196.     }  
  197.     catch (Throwable ex) {  
  198.         throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);  
  199.     }  
  200. }  

采用默认构造函数方式(这也是spring默认的形式)主要看看这个的代码:

 

 

[java] view plain copy
 
 技术分享技术分享
  1. /** 
  2.  * Instantiate the given bean using its default constructor. 
  3.  * @param beanName the name of the bean 
  4.  * @param mbd the bean definition for the bean 
  5.  * @return BeanWrapper for the new instance 
  6.  */  
  7. protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {  
  8.     try {  
  9.         Object beanInstance;  
  10.         final BeanFactory parent = this;  
  11.         if (System.getSecurityManager() != null) {  
  12.             beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {  
  13.                 public Object run() {  
  14.                     return getInstantiationStrategy().instantiate(mbd, beanName, parent);  
  15.                 }  
  16.             }, getAccessControlContext());  
  17.         }  
  18.         else {  
  19.             beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);  
  20.         }  
  21.         BeanWrapper bw = new BeanWrapperImpl(beanInstance);  
  22.         initBeanWrapper(bw);  
  23.         return bw;  
  24.     }  
  25.     catch (Throwable ex) {  
  26.         throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);  
  27.     }  
  28. }  

 

继续跟踪比较核心的getInstantiationStrategy().instantiate(mbd, beanName, parent):

 

[java] view plain copy
 
 技术分享技术分享
  1. /** 
  2.  * Simple object instantiation strategy for use in a BeanFactory. 
  3.  * 
  4.  * <p>Does not support Method Injection, although it provides hooks for subclasses 
  5.  * to override to add Method Injection support, for example by overriding methods. 
  6.  * 
  7.  * @author Rod Johnson 
  8.  * @author Juergen Hoeller 
  9.  * @since 1.1 
  10.  */  
  11. public class SimpleInstantiationStrategy implements InstantiationStrategy {  
  12.   
  13.     public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {  
  14.         // Don‘t override the class with CGLIB if no overrides.  
  15.         if (beanDefinition.getMethodOverrides().isEmpty()) {  
  16.             Constructor<?> constructorToUse;  
  17.             synchronized (beanDefinition.constructorArgumentLock) {  
  18.                 constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;  
  19.                 if (constructorToUse == null) {  
  20.                     final Class clazz = beanDefinition.getBeanClass();  
  21.                     if (clazz.isInterface()) {  
  22.                         throw new BeanInstantiationException(clazz, "Specified class is an interface");  
  23.                     }  
  24.                     try {  
  25.                         if (System.getSecurityManager() != null) {  
  26.                             constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() {  
  27.                                 public Constructor run() throws Exception {  
  28.                                     return clazz.getDeclaredConstructor((Class[]) null);  
  29.                                 }  
  30.                             });  
  31.                         }  
  32.                         else {  
  33.                             constructorToUse =  clazz.getDeclaredConstructor((Class[]) null);  
  34.                         }  
  35.                         beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;  
  36.                     }  
  37.                     catch (Exception ex) {  
  38.                         throw new BeanInstantiationException(clazz, "No default constructor found", ex);  
  39.                     }  
  40.                 }  
  41.             }  
  42.             return BeanUtils.instantiateClass(constructorToUse);  
  43.         }  
  44.         else {  
  45.             // Must generate CGLIB subclass.  
  46.             return instantiateWithMethodInjection(beanDefinition, beanName, owner);  
  47.         }  
  48.     }  

最后一句return instantiateWithMethodInjection(beanDefinition, beanName, owner);便是采用CGLIB的方式。上面的代码BeanUtils.instantiateClass(constructorToUse);是使用构造器或生成对象的工厂方法来实例化。

 

cglib代码包结构

(是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。Hibernate用它来实现PO(Persistent Object 持久化对象)字节码的动态生成。)
  • core (核心代码)
    • EmitUtils
    • ReflectUtils
    • KeyFactory
    • ClassEmitter/CodeEmitter
    • NamingPolicy/DefaultNamingPolicy
    • GeneratorStrategy/DefaultGeneratorStrategy
    • DebuggingClassWriter
    • ClassGenerator/AbstractClassGenerator
  • beans (bean操作类)
    • BeanCopier
    • BulkBean
    • BeanMap
    • ImmutableBean
    • BeanGenerator
  • reflect
    • FastClass
  • proxy
    • MethodInterceptor , Dispatcher, LazyLoader , ProxyRefDispatcher , NoOp , FixedValue , InvocationHandler(提供和jdk proxy的功能)
    • Enhancer
    • CallbackGenerator
    • Callback
    • CallbackFilter
  • util
    • StringSwitcher
    • ParallelSorter
  • transform

 

 

 

继续跟踪具体的cglib实例化bean的代码:

 

[java] view plain copy
 
 技术分享技术分享
  1. /** 
  2.  * Create a new instance of a dynamically generated subclasses implementing the 
  3.  * required lookups. 
  4.  * @param ctor constructor to use. If this is <code>null</code>, use the 
  5.  * no-arg constructor (no parameterization, or Setter Injection) 
  6.  * @param args arguments to use for the constructor. 
  7.  * Ignored if the ctor parameter is <code>null</code>. 
  8.  * @return new instance of the dynamically generated class 
  9.  */  
  10. public Object instantiate(Constructor ctor, Object[] args) {  
  11.     Enhancer enhancer = new Enhancer();  
  12.     enhancer.setSuperclass(this.beanDefinition.getBeanClass());  
  13.     enhancer.setCallbackFilter(new CallbackFilterImpl());  
  14.     enhancer.setCallbacks(new Callback[] {  
  15.             NoOp.INSTANCE,  
  16.             new LookupOverrideMethodInterceptor(),  
  17.             new ReplaceOverrideMethodInterceptor()  
  18.     });  
  19.   
  20.     return (ctor == null) ?   
  21.             enhancer.create() :   
  22.             enhancer.create(ctor.getParameterTypes(), args);  
  23. }  


跟踪一下BeanUtils.instantiateClass(constructorToUse);

 

 

[java] view plain copy
 
 技术分享技术分享
  1. /** 
  2.  * Convenience method to instantiate a class using the given constructor. 
  3.  * As this method doesn‘t try to load classes by name, it should avoid 
  4.  * class-loading issues. 
  5.  * <p>Note that this method tries to set the constructor accessible 
  6.  * if given a non-accessible (that is, non-public) constructor. 
  7.  * @param ctor the constructor to instantiate 
  8.  * @param args the constructor arguments to apply 
  9.  * @return the new instance 
  10.  * @throws BeanInstantiationException if the bean cannot be instantiated 
  11.  */  
  12. public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {  
  13.     Assert.notNull(ctor, "Constructor must not be null");  
  14.     try {  
  15.         ReflectionUtils.makeAccessible(ctor);  
  16.         return ctor.newInstance(args);  
  17.     }  
  18.     catch (InstantiationException ex) {  
  19.         throw new BeanInstantiationException(ctor.getDeclaringClass(),  
  20.                 "Is it an abstract class?", ex);  
  21.     }  
  22.     catch (IllegalAccessException ex) {  
  23.         throw new BeanInstantiationException(ctor.getDeclaringClass(),  
  24.                 "Is the constructor accessible?", ex);  
  25.     }  
  26.     catch (IllegalArgumentException ex) {  
  27.         throw new BeanInstantiationException(ctor.getDeclaringClass(),  
  28.                 "Illegal arguments for constructor", ex);  
  29.     }  
  30.     catch (InvocationTargetException ex) {  
  31.         throw new BeanInstantiationException(ctor.getDeclaringClass(),  
  32.                 "Constructor threw exception", ex.getTargetException());  
  33.     }  
  34. }  


用到了Reflection类,是使用了反射。

 

 

[java] view plain copy
 
 技术分享技术分享
  1. /** 
  2.  * Uses the constructor represented by this {@code Constructor} object to 
  3.  * create and initialize a new instance of the constructor‘s 
  4.  * declaring class, with the specified initialization parameters. 
  5.  * Individual parameters are automatically unwrapped to match 
  6.  * primitive formal parameters, and both primitive and reference 
  7.  * parameters are subject to method invocation conversions as necessary. 
  8.  * 
  9.  * <p>If the number of formal parameters required by the underlying constructor 
  10.  * is 0, the supplied {@code initargs} array may be of length 0 or null. 
  11.  * 
  12.  * <p>If the constructor‘s declaring class is an inner class in a 
  13.  * non-static context, the first argument to the constructor needs 
  14.  * to be the enclosing instance; see section 15.9.3 of 
  15.  * <cite>The Java™ Language Specification</cite>. 
  16.  * 
  17.  * <p>If the required access and argument checks succeed and the 
  18.  * instantiation will proceed, the constructor‘s declaring class 
  19.  * is initialized if it has not already been initialized. 
  20.  * 
  21.  * <p>If the constructor completes normally, returns the newly 
  22.  * created and initialized instance. 
  23.  * 
  24.  * @param initargs array of objects to be passed as arguments to 
  25.  * the constructor call; values of primitive types are wrapped in 
  26.  * a wrapper object of the appropriate type (e.g. a {@code float} 
  27.  * in a {@link java.lang.Float Float}) 
  28.  * 
  29.  * @return a new object created by calling the constructor 
  30.  * this object represents 
  31.  * 
  32.  * @exception IllegalAccessException    if this {@code Constructor} object 
  33.  *              is enforcing Java language access control and the underlying 
  34.  *              constructor is inaccessible. 
  35.  * @exception IllegalArgumentException  if the number of actual 
  36.  *              and formal parameters differ; if an unwrapping 
  37.  *              conversion for primitive arguments fails; or if, 
  38.  *              after possible unwrapping, a parameter value 
  39.  *              cannot be converted to the corresponding formal 
  40.  *              parameter type by a method invocation conversion; if 
  41.  *              this constructor pertains to an enum type. 
  42.  * @exception InstantiationException    if the class that declares the 
  43.  *              underlying constructor represents an abstract class. 
  44.  * @exception InvocationTargetException if the underlying constructor 
  45.  *              throws an exception. 
  46.  * @exception ExceptionInInitializerError if the initialization provoked 
  47.  *              by this method fails. 
  48.  */  
  49. @CallerSensitive  
  50. public T newInstance(Object ... initargs)  
  51.     throws InstantiationException, IllegalAccessException,  
  52.            IllegalArgumentException, InvocationTargetException  
  53. {  
  54.     if (!override) {  
  55.         if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {  
  56.             Class<?> caller = Reflection.getCallerClass();  
  57.             checkAccess(caller, clazz, null, modifiers);  
  58.         }  
  59.     }  
  60.     if ((clazz.getModifiers() & Modifier.ENUM) != 0)  
  61.         throw new IllegalArgumentException("Cannot reflectively create enum objects");  
  62.     ConstructorAccessor ca = constructorAccessor;   // read volatile  
  63.     if (ca == null) {  
  64.         ca = acquireConstructorAccessor();  
  65.     }  
  66.     return (T) ca.newInstance(initargs);  
  67. }  



 

之后终于看到了populateBean这个方法,之前也说过,这是用来处理依赖关系的。在AbstractAutowireCapableBeanFactory类中:

 

[java] view plain copy
 
 技术分享技术分享
  1. /** 
  2.  * Populate the bean instance in the given BeanWrapper with the property values 
  3.  * from the bean definition. 
  4.  * @param beanName the name of the bean 
  5.  * @param mbd the bean definition for the bean 
  6.  * @param bw BeanWrapper with bean instance 
  7.  */  
  8. protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {  
  9.     PropertyValues pvs = mbd.getPropertyValues();  
  10.   
  11.     if (bw == null) {  
  12.         if (!pvs.isEmpty()) {  
  13.             throw new BeanCreationException(  
  14.                     mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");  
  15.         }  
  16.         else {  
  17.             // Skip property population phase for null instance.  
  18.             return;  
  19.         }  
  20.     }  
  21.   
  22.     // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the  
  23.     // state of the bean before properties are set. This can be used, for example,  
  24.     // to support styles of field injection.  
  25.     boolean continueWithPropertyPopulation = true;  
  26.   
  27.     if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {  
  28.         for (BeanPostProcessor bp : getBeanPostProcessors()) {  
  29.             if (bp instanceof InstantiationAwareBeanPostProcessor) {  
  30.                 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;  
  31.                 if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {  
  32.                     continueWithPropertyPopulation = false;  
  33.                     break;  
  34.                 }  
  35.             }  
  36.         }  
  37.     }  
  38.   
  39.     if (!continueWithPropertyPopulation) {  
  40.         return;  
  41.     }  
  42.   
  43.     if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||  
  44.             mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {  
  45.         MutablePropertyValues newPvs = new MutablePropertyValues(pvs);  
  46.   
  47.         // Add property values based on autowire by name if applicable.  
  48.         if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {  
  49.             autowireByName(beanName, mbd, bw, newPvs);  
  50.         }  
  51.   
  52.         // Add property values based on autowire by type if applicable.  
  53.         if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {  
  54.             autowireByType(beanName, mbd, bw, newPvs);  
  55.         }  
  56.   
  57.         pvs = newPvs;  
  58.     }  
  59.   
  60.     boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();  
  61.     boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);  
  62.   
  63.     if (hasInstAwareBpps || needsDepCheck) {  
  64.         PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);  
  65.         if (hasInstAwareBpps) {  
  66.             for (BeanPostProcessor bp : getBeanPostProcessors()) {  
  67.                 if (bp instanceof InstantiationAwareBeanPostProcessor) {  
  68.                     InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;  
  69.                     pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);  
  70.                     if (pvs == null) {  
  71.                         return;  
  72.                     }  
  73.                 }  
  74.             }  
  75.         }  
  76.         if (needsDepCheck) {  
  77.             checkDependencies(beanName, mbd, filteredPds, pvs);  
  78.         }  
  79.     }  
  80.   
  81.     applyPropertyValues(beanName, mbd, bw, pvs);  
  82. }  

设断点单步跟踪,可知PropertyValues pvs = mbd.getPropertyValues();这句是获取该bean的所有属性。

 

真正核心的是最后这句,其中PropertyValues pvs作为其参数:

 

[java] view plain copy
 
 技术分享技术分享
  1. /** 
  2.  * Apply the given property values, resolving any runtime references 
  3.  * to other beans in this bean factory. Must use deep copy, so we 
  4.  * don‘t permanently modify this property. 
  5.  * @param beanName the bean name passed for better exception information 
  6.  * @param mbd the merged bean definition 
  7.  * @param bw the BeanWrapper wrapping the target object 
  8.  * @param pvs the new property values 
  9.  */  
  10. protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {  
  11.     if (pvs == null || pvs.isEmpty()) {  
  12.         return;  
  13.     }  
  14.   
  15.     MutablePropertyValues mpvs = null;  
  16.     List<PropertyValue> original;  
  17.       
  18.     if (System.getSecurityManager()!= null) {  
  19.         if (bw instanceof BeanWrapperImpl) {  
  20.             ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());  
  21.         }  
  22.     }  
  23.   
  24.     if (pvs instanceof MutablePropertyValues) {  
  25.         mpvs = (MutablePropertyValues) pvs;  
  26.         if (mpvs.isConverted()) {  
  27.             // Shortcut: use the pre-converted values as-is.  
  28.             try {  
  29.                 bw.setPropertyValues(mpvs);  
  30.                 return;  
  31.             }  
  32.             catch (BeansException ex) {  
  33.                 throw new BeanCreationException(  
  34.                         mbd.getResourceDescription(), beanName, "Error setting property values", ex);  
  35.             }  
  36.         }  
  37.         original = mpvs.getPropertyValueList();  
  38.     }  
  39.     else {  
  40.         original = Arrays.asList(pvs.getPropertyValues());  
  41.     }  
  42.   
  43.     TypeConverter converter = getCustomTypeConverter();  
  44.     if (converter == null) {  
  45.         converter = bw;  
  46.     }  
  47.     BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);  
  48.   
  49.     // Create a deep copy, resolving any references for values.  
  50.     List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());  
  51.     boolean resolveNecessary = false;  
  52.     for (PropertyValue pv : original) {  
  53.         if (pv.isConverted()) {  
  54.             deepCopy.add(pv);  
  55.         }  
  56.         else {  
  57.             String propertyName = pv.getName();  
  58.             Object originalValue = pv.getValue();  
  59.             Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);  
  60.             Object convertedValue = resolvedValue;  
  61.             boolean convertible = bw.isWritableProperty(propertyName) &&  
  62.                     !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);  
  63.             if (convertible) {  
  64.                 convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);  
  65.             }  
  66.             // Possibly store converted value in merged bean definition,  
  67.             // in order to avoid re-conversion for every created bean instance.  
  68.             if (resolvedValue == originalValue) {  
  69.                 if (convertible) {  
  70.                     pv.setConvertedValue(convertedValue);  
  71.                 }  
  72.                 deepCopy.add(pv);  
  73.             }  
  74.             else if (convertible && originalValue instanceof TypedStringValue &&  
  75.                     !((TypedStringValue) originalValue).isDynamic() &&  
  76.                     !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {  
  77.                 pv.setConvertedValue(convertedValue);  
  78.                 deepCopy.add(pv);  
  79.             }  
  80.             else {  
  81.                 resolveNecessary = true;  
  82.                 deepCopy.add(new PropertyValue(pv, convertedValue));  
  83.             }  
  84.         }  
  85.     }  
  86.     if (mpvs != null && !resolveNecessary) {  
  87.         mpvs.setConverted();  
  88.     }  
  89.   
  90.     // Set our (possibly massaged) deep copy.  
  91.     try {  
  92.         bw.setPropertyValues(new MutablePropertyValues(deepCopy));  
  93.     }  
  94.     catch (BeansException ex) {  
  95.         throw new BeanCreationException(  
  96.                 mbd.getResourceDescription(), beanName, "Error setting property values", ex);  
  97.     }  
  98. }  
  99.   
  100. /** 
  101.  * Convert the given value for the specified target property. 
  102.  */  
  103. private Object convertForProperty(Object value, String propertyName, BeanWrapper bw, TypeConverter converter) {  
  104.     if (converter instanceof BeanWrapperImpl) {  
  105.         return ((BeanWrapperImpl) converter).convertForProperty(value, propertyName);  
  106.     }  
  107.     else {  
  108.         PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);  
  109.         MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);  
  110.         return converter.convertIfNecessary(value, pd.getPropertyType(), methodParam);  
  111.     }  
  112. }  

这个方法很长,其内在逻辑却也不难。主要是对传进来的PropertyValues pvs参数的每一项做一个解析过程,而BeanWrapper bw参数包装着前面实例化的bean实例对象。
技术分享

 

而BeanDefinition mbd这个参数,也就是BeanDefinition,在这里只用于抛出异常信息,没什么大用。

看代码for (PropertyValue pv : original) {}循环遍历PropertyValues,循环过程解析每一个字段:Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue),最后bw.setPropertyValues(new MutablePropertyValues(deepCopy));这句将之前得到的结果set进我们要处理的实例化对象;

 

[java] view plain copy
 
 技术分享技术分享
  1. /** 
  2.  * Given a PropertyValue, return a value, resolving any references to other 
  3.  * beans in the factory if necessary. The value could be: 
  4.  * <li>A BeanDefinition, which leads to the creation of a corresponding 
  5.  * new bean instance. Singleton flags and names of such "inner beans" 
  6.  * are always ignored: Inner beans are anonymous prototypes. 
  7.  * <li>A RuntimeBeanReference, which must be resolved. 
  8.  * <li>A ManagedList. This is a special collection that may contain 
  9.  * RuntimeBeanReferences or Collections that will need to be resolved. 
  10.  * <li>A ManagedSet. May also contain RuntimeBeanReferences or 
  11.  * Collections that will need to be resolved. 
  12.  * <li>A ManagedMap. In this case the value may be a RuntimeBeanReference 
  13.  * or Collection that will need to be resolved. 
  14.  * <li>An ordinary object or <code>null</code>, in which case it‘s left alone. 
  15.  * @param argName the name of the argument that the value is defined for 
  16.  * @param value the value object to resolve 
  17.  * @return the resolved object 
  18.  */  
  19. public Object resolveValueIfNecessary(Object argName, Object value) {  
  20.     // We must check each value to see whether it requires a runtime reference  
  21.     // to another bean to be resolved.  
  22.     if (value instanceof RuntimeBeanReference) {  
  23.         RuntimeBeanReference ref = (RuntimeBeanReference) value;  
  24.         return resolveReference(argName, ref);  
  25.     }  
  26.     else if (value instanceof RuntimeBeanNameReference) {  
  27.         String refName = ((RuntimeBeanNameReference) value).getBeanName();  
  28.         refName = String.valueOf(evaluate(refName));  
  29.         if (!this.beanFactory.containsBean(refName)) {  
  30.             throw new BeanDefinitionStoreException(  
  31.                     "Invalid bean name ‘" + refName + "‘ in bean reference for " + argName);  
  32.         }  
  33.         return refName;  
  34.     }  
  35.     else if (value instanceof BeanDefinitionHolder) {  
  36.         // Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.  
  37.         BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;  
  38.         return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());  
  39.     }  
  40.     else if (value instanceof BeanDefinition) {  
  41.         // Resolve plain BeanDefinition, without contained name: use dummy name.  
  42.         BeanDefinition bd = (BeanDefinition) value;  
  43.         return resolveInnerBean(argName, "(inner bean)", bd);  
  44.     }  
  45.     else if (value instanceof ManagedArray) {  
  46.         // May need to resolve contained runtime references.  
  47.         ManagedArray array = (ManagedArray) value;  
  48.         Class elementType = array.resolvedElementType;  
  49.         if (elementType == null) {  
  50.             String elementTypeName = array.getElementTypeName();  
  51.             if (StringUtils.hasText(elementTypeName)) {  
  52.                 try {  
  53.                     elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());  
  54.                     array.resolvedElementType = elementType;  
  55.                 }  
  56.                 catch (Throwable ex) {  
  57.                     // Improve the message by showing the context.  
  58.                     throw new BeanCreationException(  
  59.                             this.beanDefinition.getResourceDescription(), this.beanName,  
  60.                             "Error resolving array type for " + argName, ex);  
  61.                 }  
  62.             }  
  63.             else {  
  64.                 elementType = Object.class;  
  65.             }  
  66.         }  
  67.         return resolveManagedArray(argName, (List<?>) value, elementType);  
  68.     }  
  69.     else if (value instanceof ManagedList) {  
  70.         // May need to resolve contained runtime references.  
  71.         return resolveManagedList(argName, (List<?>) value);  
  72.     }  
  73.     else if (value instanceof ManagedSet) {  
  74.         // May need to resolve contained runtime references.  
  75.         return resolveManagedSet(argName, (Set<?>) value);  
  76.     }  
  77.     else if (value instanceof ManagedMap) {  
  78.         // May need to resolve contained runtime references.  
  79.         return resolveManagedMap(argName, (Map<?, ?>) value);  
  80.     }  
  81.     else if (value instanceof ManagedProperties) {  
  82.         Properties original = (Properties) value;  
  83.         Properties copy = new Properties();  
  84.         for (Map.Entry propEntry : original.entrySet()) {  
  85.             Object propKey = propEntry.getKey();  
  86.             Object propValue = propEntry.getValue();  
  87.             if (propKey instanceof TypedStringValue) {  
  88.                 propKey = evaluate((TypedStringValue) propKey);  
  89.             }  
  90.             if (propValue instanceof TypedStringValue) {  
  91.                 propValue = evaluate((TypedStringValue) propValue);  
  92.             }  
  93.             copy.put(propKey, propValue);  
  94.         }  
  95.         return copy;  
  96.     }  
  97.     else if (value instanceof TypedStringValue) {  
  98.         // Convert value to target type here.  
  99.         TypedStringValue typedStringValue = (TypedStringValue) value;  
  100.         Object valueObject = evaluate(typedStringValue);  
  101.         try {  
  102.             Class<?> resolvedTargetType = resolveTargetType(typedStringValue);  
  103.             if (resolvedTargetType != null) {  
  104.                 return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);  
  105.             }  
  106.             else {  
  107.                 return valueObject;  
  108.             }  
  109.         }  
  110.         catch (Throwable ex) {  
  111.             // Improve the message by showing the context.  
  112.             throw new BeanCreationException(  
  113.                     this.beanDefinition.getResourceDescription(), this.beanName,  
  114.                     "Error converting typed String value for " + argName, ex);  
  115.         }  
  116.     }  
  117.     else {  
  118.         return evaluate(value);  
  119.     }  
  120. }  



 

 

简单总结:

    一、容器初始化:

        1,Resource来进行资源定位

        2,spring创建工厂时(以XmlBeanFactory为例),解析xml文件,转化为document

        3,注册BeanDefinition,在BeanFactory的map数据结构里。BeanDefinition就是spring内部用来描绘bean的数据结构

        4,getBean时,依据BeanDefinition,实例化对象

        5, populateBean 处理 前面实例化的对象的依赖关系

spring源码分析(一)IoC、DI

标签:

原文地址:http://www.cnblogs.com/rixiang/p/5766828.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!