zoukankan      html  css  js  c++  java
  • spring源码分析(一)IoC、DI

    参考书籍:《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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    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 处理 前面实例化的对象的依赖关系

  • 相关阅读:
    Linux常用操作命令大全
    判断系统,是否是移动端
    一款兼容小程序和web端的框架 Kbone-API
    defer 和 async的区别
    快应用多次弹出添加到桌面的bug
    js判断一个元素是否在数组中
    css 画太极
    css3锯齿
    js 获取屏幕宽度
    js 判断div距离浏览器顶部或者底部的距离
  • 原文地址:https://www.cnblogs.com/rixiang/p/5766828.html
Copyright © 2011-2022 走看看