Spring源码学习之IOC容器实现原理(一)-DefaultListableBeanFactory

BeanFactory接口

从这个继承体系结构图来看,我们可以发现DefaultListableBeanFactory是第一个非抽象类,非接口类。实际IOC容器。所以这篇博客以DefaultListableBeanFactoryIOC容器为基准进行IOC原理解析。

一.两个重要接口

前面已经分析了BeanFactor,它的三个直接子类接口,接下来我们继续分析两个重要的接口,可以看到这两个接口也是集大成者。

首先是ConfigurableBeanFactor

1.ConfigurableBeanFactory

从名字可以看到,这是一个可以配置的接口,但是究竟在配置什么呢?

(1)接口定义

public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry

可以看到继承了HierarchicalBeanFactory和SingletonBeanRegistry两个接口。

表明实现这个接口的类都是可以分层,支持单例的IOC容器。

(2)java doc

/**
 * Configuration interface to be implemented by most bean factories. Provides
 * facilities to configure a bean factory, in addition to the bean factory
 * client methods in the {@link org.springframework.beans.factory.BeanFactory}
 * interface.
 *
 * <p>This bean factory interface is not meant to be used in normal application
 * code: Stick to {@link org.springframework.beans.factory.BeanFactory} or
 * {@link org.springframework.beans.factory.ListableBeanFactory} for typical
 * needs. This extended interface is just meant to allow for framework-internal
 * plug'n'play and for special access to bean factory configuration methods.
 */

1.这个接口被大量实现,配置了可以配置容器的方法。

2.这个接口不是常用接口,依赖于BeanFactory和ListableBeanFactory接口,只是属于框架的一部分。

(3) 源码

public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {

    String SCOPE_SINGLETON = "singleton";
    String SCOPE_PROTOTYPE = "prototype";


    /**
     * Set the parent of this bean factory.
     * <p>Note that the parent cannot be changed: It should only be set outside
     * a constructor if it isn't available at the time of factory instantiation.
     */
    //可以设置父工厂,但是值得注意的是,只能设置一次,不能改变
    void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;

    /**
     * Set the class loader to use for loading bean classes.
     * Default is the thread context class loader.
     * <p>Note that this class loader will only apply to bean definitions
     * that do not carry a resolved bean class yet. This is the case as of
     * Spring 2.0 by default: Bean definitions only carry bean class names,
     * to be resolved once the factory processes the bean definition.
     * @param beanClassLoader the class loader to use,
     * or {@code null} to suggest the default class loader
     */
    //配置ClassLoader,只是应用于Bean definition
    void setBeanClassLoader(ClassLoader beanClassLoader);

    /**
     * Return this factory's class loader for loading bean classes.
     */
    ClassLoader getBeanClassLoader();
    
    void setTempClassLoader(ClassLoader tempClassLoader);
    ClassLoader getTempClassLoader();

    /**
     * Set whether to cache bean metadata such as given bean definitions
     * (in merged fashion) and resolved bean classes. Default is on.
     * <p>Turn this flag off to enable hot-refreshing of bean definition objects
     * and in particular bean classes. If this flag is off, any creation of a bean
     * instance will re-query the bean class loader for newly resolved classes.
     */
    /// 设置、是否缓存元数据,如果false,那么每次请求实例,都会从类加载器重新加载(热加载),这里还不太懂
    void setCacheBeanMetadata(boolean cacheBeanMetadata);

    /**
     * Return whether to cache bean metadata such as given bean definitions
     * (in merged fashion) and resolved bean classes.
     */
    boolean isCacheBeanMetadata();

    //表达式支持,配置表达式支持器
    void setBeanExpressionResolver(BeanExpressionResolver resolver);

    BeanExpressionResolver getBeanExpressionResolver();

    //配置conversionService??转换服务?
    void setConversionService(ConversionService conversionService);
    ConversionService getConversionService();

    //配置属性编辑器
    void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar);
    void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass);

    void copyRegisteredEditorsTo(PropertyEditorRegistry registry);

    //配置类型转换器?TypeCoverter
    void setTypeConverter(TypeConverter typeConverter);
    
    TypeConverter getTypeConverter();

    //字符串处理器?
    void addEmbeddedValueResolver(StringValueResolver valueResolver);

    //处理字符串
    String resolveEmbeddedValue(String value);

    /**
     * Add a new BeanPostProcessor that will get applied to beans created
     * by this factory. To be invoked during factory configuration.
     * <p>Note: Post-processors submitted here will be applied in the order of
     * registration; any ordering semantics expressed through implementing the
     * {@link org.springframework.core.Ordered} interface will be ignored. Note
     * that autodetected post-processors (e.g. as beans in an ApplicationContext)
     * will always be applied after programmatically registered ones.
     * @param beanPostProcessor the post-processor to register
     */
    //添加后处理器
    void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);

    /**
     * Return the current number of registered BeanPostProcessors, if any.
     */
    int getBeanPostProcessorCount();


    void registerScope(String scopeName, Scope scope);

    String[] getRegisteredScopeNames();

    
    Scope getRegisteredScope(String scopeName);

    AccessControlContext getAccessControlContext();

    void copyConfigurationFrom(ConfigurableBeanFactory otherFactory);

    //注册别名依赖关系
    void registerAlias(String beanName, String alias) throws BeanDefinitionStoreException;

    void resolveAliases(StringValueResolver valueResolver);

    BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    /**
     * Determine whether the bean with the given name is a FactoryBean.
    boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException;

    void setCurrentlyInCreation(String beanName, boolean inCreation);

    boolean isCurrentlyInCreation(String beanName);

    //注册依赖Bean
    void registerDependentBean(String beanName, String dependentBeanName);

    String[] getDependentBeans(String beanName);

    
    String[] getDependenciesForBean(String beanName);

    
    void destroyBean(String beanName, Object beanInstance);

    
    void destroyScopedBean(String beanName);

    void destroySingletons();

}

好吧,好一个可配置,吓尿了有点。总的来说,还是在配置一些IOC容器,没有超出IOC容器。

总结一下,我现阶段能看懂的部分:

1.首先是两个作用领域对象,判断是否为singleton,单例还是Prototype,原型。应用于方法registerScope。这两个有啥区别??

1。 当一个bean的作用域设置为singleton, 那么Spring IOC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。换言之,当把一个bean定义设置为singleton作用域时,Spring IOC容器只会创建该bean定义的唯一实例。这个单一实例会被存储到单例缓存(singleton cache)中,并且所有针对该bean的后续请求和引用都将返回被缓存的对象实例,这里要注意的是singleton作用域和GOF设计模式中的单例是完全不同的,单例设计模式表示一个ClassLoader中只有一个class存在,而这里的singleton则表示一个容器对应一个bean,也就是说当一个bean被标识为singleton时候,spring的IOC容器中只会存在一个该bean。

2。 prototype作用域部署的bean,每一次请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)都会产生一个新的bean实例,相当与一个new的操作,对于prototype作用域的bean,有一点非常重要,那就是Spring不能对一个prototype bean的整个生命周期负责,容器在初始化、配置、装饰或者是装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法,而对prototype而言,任何配置好的析构生命周期回调方法都将不会被调用。清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源,都是客户端代码的职责。(让Spring容器释放被singleton作用域bean占用资源的一种可行方式是,通过使用bean的后置处理器,该处理器持有要被清除的bean的引用。)

参考内容

2.第二个就是setParentBeanFactory,这个方法后面会被大量使用。对应于getParentBeanFactory。

3.还有一些处理器的配置,重点关注后处理器配置,addBeanPostProcessor以及ClassLoader配置,setBeanClassLoader。

 

2.ConfigurableListableBeanFactory

(1)接口定义

public interface ConfigurableListableBeanFactory
        extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory

从这里就可以看出,ConfigurableListableBeanFactory继承了上面提到的所有接口,所以它是最后的大Boss。真正的集大成者IOC容器接口,而不再是小儿科了。

(2)java doc

/**
 * Configuration interface to be implemented by most listable bean factories.
 * In addition to {@link ConfigurableBeanFactory}, it provides facilities to
 * analyze and modify bean definitions, and to pre-instantiate singletons.
 *
 * <p>This subinterface of {@link org.springframework.beans.factory.BeanFactory}
 * is not meant to be used in normal application code: Stick to
 * {@link org.springframework.beans.factory.BeanFactory} or
 * {@link org.springframework.beans.factory.ListableBeanFactory} for typical
 * use cases. This interface is just meant to allow for framework-internal
 * plug'n'play even when needing access to bean factory configuration methods.
 */

1.对ConfigurableBeanFactory接口的扩充,提供了分析和调整Bean definition的方法。

2.依然不是常用接口?什么叫常用接口呢。并不是在实际编程应用过程中常使用的接口代码。这里的意思可能是我们向上转型建立BeanFactor时,没必要指定一个实例为该接口。可以是BeanFactory或者是ListableBeanFactory。

(3)源码

public interface ConfigurableListableBeanFactory
        extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {

    /**
     * Ignore the given dependency type for autowiring:
     * for example, String. Default is none.
     * @param type the dependency type to ignore
     */
    //忽略自动装配的依赖类型
    void ignoreDependencyType(Class<?> type);

    /**
     * Ignore the given dependency interface for autowiring.
     * <p>This will typically be used by application contexts to register
     * dependencies that are resolved in other ways, like BeanFactory through
     * BeanFactoryAware or ApplicationContext through ApplicationContextAware.
     * <p>By default, only the BeanFactoryAware interface is ignored.
     * For further types to ignore, invoke this method for each type.
     * @param ifc the dependency interface to ignore
     * @see org.springframework.beans.factory.BeanFactoryAware
     * @see org.springframework.context.ApplicationContextAware
     */
    //忽略自动装配的依赖接口
    void ignoreDependencyInterface(Class<?> ifc);

    /**
     * Register a special dependency type with corresponding autowired value.
     * <p>This is intended for factory/context references that are supposed
     * to be autowirable but are not defined as beans in the factory:
     * e.g. a dependency of type ApplicationContext resolved to the
     * ApplicationContext instance that the bean is living in.
     * <p>Note: There are no such default types registered in a plain BeanFactory,
     * not even for the BeanFactory interface itself.
     */
    //注册一个特殊的依赖类型
    //用来解决FactorBean引用来注册在容器中
    void registerResolvableDependency(Class<?> dependencyType, Object autowiredValue);

    /**
     * Determine whether the specified bean qualifies as an autowire candidate,
     * to be injected into other beans which declare a dependency of matching type.
     * <p>This method checks ancestor factories as well.
     * @param beanName the name of the bean to check
     * @param descriptor the descriptor of the dependency to resolve
     * @return whether the bean should be considered as autowire candidate
     * @throws NoSuchBeanDefinitionException if there is no bean with the given name
     */
    //决定这个Bean是否应该被其他Bean自动装配。
    boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
            throws NoSuchBeanDefinitionException;

    /**
     * Return the registered BeanDefinition for the specified bean, allowing access
     * to its property values and constructor argument value (which can be
     * modified during bean factory post-processing).
     * <p>A returned BeanDefinition object should not be a copy but the original
     * definition object as registered in the factory. This means that it should
     * be castable to a more specific implementation type, if necessary.
     * <p><b>NOTE:</b> This method does <i>not</i> consider ancestor factories.
     * It is only meant for accessing local bean definitions of this factory.
     * @param beanName the name of the bean
     * @return the registered BeanDefinition
     * @throws NoSuchBeanDefinitionException if there is no bean with the given name
     * defined in this factory
     */
    //返回对应Bean的BeanDefinition
    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    /**
     * Return a unified view over all bean names managed by this factory.
     * <p>Includes bean definition names as well as names of manually registered
     * singleton instances, with bean definition names consistently coming first,
     * analogous to how type/annotation specific retrieval of bean names works.
     * @return the composite iterator for the bean names view
     * @since 4.1.2
     * @see #containsBeanDefinition
     * @see #registerSingleton
     * @see #getBeanNamesForType
     * @see #getBeanNamesForAnnotation
     */
    //返回一个Bean名称的迭代器
    Iterator<String> getBeanNamesIterator();

    /**
     * Freeze all bean definitions, signalling that the registered bean definitions
     * will not be modified or post-processed any further.
     * <p>This allows the factory to aggressively cache bean definition metadata.
     */
    //锁定Bean配置,不在改变
    void freezeConfiguration();

    /**
     * Return whether this factory's bean definitions are frozen,
     * i.e. are not supposed to be modified or post-processed any further.
     * @return {@code true} if the factory's configuration is considered frozen
     */
    boolean isConfigurationFrozen();

    /**
     * Ensure that all non-lazy-init singletons are instantiated, also considering
     * {@link org.springframework.beans.factory.FactoryBean FactoryBeans}.
     * Typically invoked at the end of factory setup, if desired.
     * @throws BeansException if one of the singleton beans could not be created.
     * Note: This may have left the factory with some beans already initialized!
     * Call {@link #destroySingletons()} for full cleanup in this case.
     * @see #destroySingletons()
     */
    //初始化所有的单例。
    void preInstantiateSingletons() throws BeansException;

}

值得注意的方法就是可以根据Bean的名称返回BeanDefinition,以及可以可以与初始化所有单例。还有就是返回Bean Name的迭代器。

 

二. DefaultListableBeanFactory

1. 定义

public class DefaultListableBeanFactory extends

AbstractAutowireCapableBeanFactory  implements

ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable

 
只继承了一个抽象类,同时把集大成的接口ConfigurableListableBeanFactory给实现了,同时还有BeanDefinitionRegistry接口,从名字上看就知道是BeanDefinition的注册接口。

2.Java doc

/**
 * Default implementation of the
 * {@link org.springframework.beans.factory.ListableBeanFactory} and
 * {@link BeanDefinitionRegistry} interfaces: a full-fledged bean factory
 * based on bean definition objects.
 *//一个完整的,成熟的IOC容器
 * <p>Typical usage is registering all bean definitions first (possibly read
 * from a bean definition file), before accessing beans. Bean definition lookup
 * is therefore an inexpensive operation in a local bean definition table,
 * operating on pre-built bean definition metadata objects.
 *//主要作为注册Bean definition
 * <p>Can be used as a standalone bean factory, or as a superclass for custom
 * bean factories. Note that readers for specific bean definition formats are
 * typically implemented separately rather than as bean factory subclasses:
 * see for example {@link PropertiesBeanDefinitionReader} and
 * {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader}.
 *
 * <p>For an alternative implementation of the
 * {@link org.springframework.beans.factory.ListableBeanFactory} interface,
 * have a look at {@link StaticListableBeanFactory}, which manages existing
 * bean instances rather than creating new ones based on bean definitions.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller//注意这两个作者
*/

它是真正第一个可以独立的IOC容器,而且后面的ApplicationContext据说也是依据它来建立。在访问bean前,先注册所有的definition(可能从bean definition配置文件中)。使用预先建立的bean定义元数据对象,从本地的bean definition表中查询bean definition因而将不会花费太多成本。这个类的直接子类只有XMLBeanFactory,二者的唯一区别就是后者集成了处理XML形式BeanDefinition的方法。

三.IOC容器实现原理

这次先不关注源码,先首先看看它的用法,例子参考<Spring 技术内幕>

ClassPathResource res=new ClassPathResource("beans.xml");
DefaultListableBeanFactory factory=new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader=new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(res);
Performer performer=(Performer) factory.getBean("dancer");
performer.perform();

简单解释一下:

1.我们在beans.xml中定义了一个Bean,id为“dancer”,实现了Performer接口。参考自<Spring in action>例子.

2.利用Resource抽象实现类,来包装这个包含了BeanDefinition的定义信息。

3.创建一个BeanFactory,DefaultListableBeanFactory

4.创建一个载入BeanDefinition的读取器,通过回调配置给BeanFactory.

5. 从定义好好的Resource中,读取配置信息。由XmlBeanDefinitionReader完成解析,完成整个载入和注册Bean定义的过程。

6. 通过BeanFactory的getBean()方法,获取对应的Bean。这里涉及到了Bean的实例化以及依赖注入

其实这也是XmlBeanFactory的实现形式,可以参考其实现源码

public class XmlBeanFactory extends DefaultListableBeanFactory {

    private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);


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

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

}

beans.xml的定义如下所示:

xml

简单解释一下例子,Dancer类共有三个属性,一个是danceStyle,一个是name,这两个都是String类型的,另一个是partner,是Dancer类型,所以这里采用了内部类的形式。Dancer类继承了Performer接口,实现了接口的perform方法。

*******************单步调试分析****************

1.ClassPathResource res=new ClassPathResource("beans.xml");

resource

可见Resource 是对Resource文件的定位过程。提供了两个属性,一个是ClassLoader,另一个是path路径。是对输入流的一个包装。

2.DefaultListableBeanFactory factory=new DefaultListableBeanFactory();

接下来单步运行看一下IOC容器创建的过程。

(1) 可见DefaultListableBeanFactory,只是调用父类构造器

DefaultListableBeanFactory

(2)父类是AbstractAutowireCapableBeanFactory抽象容器

Image 6

额,继续上调默认构造器,同时会调用IgnoreDependencyInterface方法,查看一下这个方法,参数为Class类型。

/**
     * Ignore the given dependency interface for autowiring.
     * <p>This will typically be used by application contexts to register
     * dependencies that are resolved in other ways, like BeanFactory through
     * BeanFactoryAware or ApplicationContext through ApplicationContextAware.
     * <p>By default, only the BeanFactoryAware interface is ignored.
     * For further types to ignore, invoke this method for each type.
     * @see org.springframework.beans.factory.BeanFactoryAware
     * @see org.springframework.context.ApplicationContextAware
     */
    public void ignoreDependencyInterface(Class<?> ifc) {
        this.ignoredDependencyInterfaces.add(ifc);
    }

这个方法主要是需要自动装配时,忽略的接口类型,ignoredDependencyInterfaces是Set类型的,private final Set<Class<?>> ignoredDependencyInterfaces = new HashSet<Class<?>>();

所以在自动装配的时候,会自动忽略BeanNameAware.class,BeanFactoryAware.class,BeanClassLoaderAware.class接口类型的类。

(3)父类构造器AbstractBeanFactory,由图可知这是最顶层的抽象IOC容器

空构造器

abstractBeanFactory

(4)最后看看DefaultListableBeanFactory

DefaultListableBeanFactory1

其实这里可以发现采用大量的集合变量来保存一些涉及到的数据,所以看起来没有那么唬人。

3.XmlBeanDefinitionReader reader=new XmlBeanDefinitionReader(factory);

接下来看看回调的过程

(1)

XmlBeanDefinitionReader

可见DefaultListableBeanFactory实现了BeanDefinitionRegistry类型的接口。

(2)调用父类AbstractBeanDefinitionReader,带有参数的构造器

AbstractBeanDefinitionReader

为什么registry(也就是上面的factory)可能是ResourceLoader呢?其实这里是为ApplicationContext埋下了伏笔。

这个构造器主要干了三件事,一个是将registry绑定到factory,另外两个就是初始化ResourceLoader和environment(还不了解是干嘛的)。

 

4.reader.loadBeanDefinitions(res);

好吧,终于到了激动人心的载入BeanDefinition过程。

(1)loadBeanDefinitions(Resource resource)方法

loadBeanDefinitions

应用装饰器模式,包装Resource。

(2)然后是调用的重载方法loadBeanDefinitions(EncodedResource encodedResource)

/**
     * Load bean definitions from the specified XML file.
     * @param encodedResource the resource descriptor for the XML file,
     * allowing to specify an encoding to use for parsing the file
     * @return the number of bean definitions found
     * @throws BeanDefinitionStoreException in case of loading or parsing errors
     */
    public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
        Assert.notNull(encodedResource, "EncodedResource must not be null");
        if (logger.isInfoEnabled()) {
            logger.info("Loading XML bean definitions from " + encodedResource.getResource());
        }
        //resourcesCurrentlyBeingLoaded是ThreadLocal类型的,里面保存的是Set类型。为了保证线程安全。
        Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
        if (currentResources == null) {
            currentResources = new HashSet<EncodedResource>(4);
            this.resourcesCurrentlyBeingLoaded.set(currentResources);
        }
        //将encodeResource,资源放入存放资源的Set中
        if (!currentResources.add(encodedResource)) {
            throw new BeanDefinitionStoreException(
                    "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
        }
        try {
            //转换为输入流
            InputStream inputStream = encodedResource.getResource().getInputStream();
            try {
                //包装成InputSource类型的资源
                InputSource inputSource = new InputSource(inputStream);
                if (encodedResource.getEncoding() != null) {
                    inputSource.setEncoding(encodedResource.getEncoding());
                }
                //最终调用doLoadBeanDefinitions方法。
                return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
            }
            finally {
                inputStream.close();
            }
        }
        catch (IOException ex) {
            throw new BeanDefinitionStoreException(
                    "IOException parsing XML document from " + encodedResource.getResource(), ex);
        }
        finally {
            currentResources.remove(encodedResource);
            if (currentResources.isEmpty()) {
                this.resourcesCurrentlyBeingLoaded.remove();
            }
        }
    }
所以,每次看到的输出的载入xml bean definitions的log信息,就是来自这个方法。所以在loadBeanDefinition过程中,首先输出的信息来自这里。

log

(3) doLoadBeanDefinitions

而这个方法其实会调用doLoadDocument()方法获得Document,即W3C中说的document,即HTML文档或者XML文档等。得到的document对象并没有按照Spring规则解析。

doLoadBeanDefinitions

而通过registerBeanDefinitions,启动对BeanDefinition的详细解析过程,这个解析过程涉及到了Spring的配置规则。

(4)registerBeanDefinitions,注册Bean,通过这个方法Spring会按照Bean语义要求进行解析,并转化为容器内部的数据结构(BeanDefinition),这个过程是在registerBeanDefinitions中进行的。而这个函数属于XMLBeanDefinitionReader。

/**
     * Register the bean definitions contained in the given DOM document.
     * Called by {@code loadBeanDefinitions}.
     * <p>Creates a new instance of the parser class and invokes
     * {@code registerBeanDefinitions} on it.
     * @param doc the DOM document
     * @param resource the resource descriptor (for context information)
     * @return the number of bean definitions found
     * @throws BeanDefinitionStoreException in case of parsing errors
     * @see #loadBeanDefinitions
     * @see #setDocumentReaderClass
     * @see BeanDefinitionDocumentReader#registerBeanDefinitions
     */
    @SuppressWarnings("deprecation")
    public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
        BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
        documentReader.setEnvironment(getEnvironment());
        int countBefore = getRegistry().getBeanDefinitionCount();
        documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
        return getRegistry().getBeanDefinitionCount() - countBefore;
    }

最终会调用BeanDefinitionDocumentReader的对象documentReader的registerBeanDefinitions方法,按照Spring的Bean定义规则进行解析,同时这里可以发现这里返回的是此次注册的Bean的个数。documentReader是默认设置好的DefaultBeanDefinitionReader。

(5)documentReader.registerBeanDefinitions()

registerBeanDefinitions方法

可以看到log信息,开始”Loading bean definitions”,调用doRegisterBeanDefinitions(root)方法

(6)doRegisterBeanDefinitions()方法

/**
     * Register each bean definition within the given root {@code <beans/>} element.
     */
    protected void doRegisterBeanDefinitions(Element root) {
        // Any nested <beans> elements will cause recursion in this method. In
        // order to propagate and preserve <beans> default-* attributes correctly,
        // keep track of the current (parent) delegate, which may be null. Create
        // the new (child) delegate with a reference to the parent for fallback purposes,
        // then ultimately reset this.delegate back to its original (parent) reference.
        // this behavior emulates a stack of delegates without actually necessitating one.
        BeanDefinitionParserDelegate parent = this.delegate;
        this.delegate = createDelegate(getReaderContext(), root, parent);

        if (this.delegate.isDefaultNamespace(root)) {
            String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
            if (StringUtils.hasText(profileSpec)) {
                String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                        profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
                if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                    return;
                }
            }
        }

        preProcessXml(root);
        parseBeanDefinitions(root, this.delegate);
        postProcessXml(root);

        this.delegate = parent;
    }

好吧,还没到头,要注意这里有一个注释“

/**
     * Register each bean definition within the given root {@code <beans/>} element.
*/

”可以看出是从<beans>作为root节点进行解析。

可以看到有一个delegate对象,属于BeanDefinitionParserDelegate类型,而这个类的定义如下:

/**
* Stateful delegate class used to parse XML bean definitions.
* Intended for use by both the main parser and any extension
* {@link BeanDefinitionParser BeanDefinitionParsers} or
* {@link BeanDefinitionDecorator BeanDefinitionDecorators}.

可以看到这个类的作用主要是有状态的解析XML BeanDefinition的代理。

同时,由于每个bean可能存在层次关系,而引发递归调用,为了维护网络层次关系,采用parent属性保留其parent Bean.接下来看一下默认的delegate属性长什么样子?

delegate

可以重点看一下defaults的属性,如autowire是no,lazyInit=false。

parseBeanDefintions()将是解析BeanDefinition的最终方法?

(7)parseBeanDefinitions

/**
     * Parse the elements at the root level in the document:
     * "import", "alias", "bean".
     * @param root the DOM root element of the document
     */
    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        if (delegate.isDefaultNamespace(root)) {
            NodeList nl = root.getChildNodes();
            for (int i = 0; i < nl.getLength(); i++) {
                Node node = nl.item(i);
                if (node instanceof Element) {
                    Element ele = (Element) node;
                    if (delegate.isDefaultNamespace(ele)) {
                        parseDefaultElement(ele, delegate);
                    }
                    else {
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        }
        else {
            delegate.parseCustomElement(root);
        }
    }

该方法属于DefaultBeanDefinitionDocumentReader,即前面得到的documentReader,是处理BeanDefinition的地方,具体的委托处理交给了BeanDefinitionParseDelegate来完成。

当子node是Element类型时,将触发parseDefaultElement(ele, delegate),继续解析,-》-》

(8)parseDefaultElement

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
            importBeanDefinitionResource(ele);
        }
        else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
            processAliasRegistration(ele);
        }
        else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
            processBeanDefinition(ele, delegate);
        }
        else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
            // recurse
            doRegisterBeanDefinitions(ele);
        }
    }

根据元素类型不同,调用的注册方法不同。这里调用processBeanDefinition(ele, delegate),这就涉及到了<beans>的三个子类别<import>,<alias>,<bean>

(9)processBeanDefinition

这个方法仍然属于DefaultBeanDefinitionDocumentReader。这里具体解析Bean元素。

/**
     * Process the given bean element, parsing the bean definition
     * and registering it with the registry.
     */
    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
            try {
                // Register the final decorated instance.
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
            }
            catch (BeanDefinitionStoreException ex) {
                getReaderContext().error("Failed to register bean definition with name '" +
                        bdHolder.getBeanName() + "'", ele, ex);
            }
            // Send registration event.
            getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }
    }

这里会通过调用delegate的parseBeanDefinitionElement的方法,处理在xml文件中定义的<bean>,以及他的对应的属性。具体如下:

parseBeanDefinitionElement

parseBeanDefinitionElement2

这里可以看到bean的id,name,alias等定义的属性元素。把这些元素取出来之后,设置到生成的BeanDefinitionHolder中。

debug查看beanDefinition的信息如下,这里可以看到一些默认的设置,比如abstract=false,lazyInit=false;autowireMode=0;等同时它的class属性也在这里。

Generic bean: class [com.wly.source.spring_scoure_inspect.Dancer]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [beans.xml]

可以看到BeanDefinition可以看成是对<bean>定义的抽象,是容器中的基本数据类型,封装了Bean所需要的所有的数据。可以看出它是及其重要的。

最好包装返回成BeanDefinitionHolder。Holder for a BeanDefinition with name and aliases.
Can be registered as a placeholder for an inner bean.BeanDefinitionHolder是BeanDefinition对象的封装类,封装了BeanDefinition的BeanDefinition,名字和别名(alias)。用它来完成IOC容器的注册。

bgHolder

最后,通过

BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());完成最后的注册。

而这里通过getRegistry()方法得到的BeanDefinitionRegistry,即一开始得到的DefaultListableBeanFactory factory。这里进行回调使用,这也是为什么registerBeanDefinition方法属于BeanDefinitionReaderUtils的原因。

/**
     * Register the given bean definition with the given bean factory.
     * @param definitionHolder the bean definition including name and aliases
     * @param registry the bean factory to register with
     * @throws BeanDefinitionStoreException if registration failed
     */
public static void registerBeanDefinition(    BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)throws BeanDefinitionStoreException {

    // Register bean definition under primary name.
    String beanName = definitionHolder.getBeanName();
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

    // Register aliases for bean name, if any.
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
        }
    }
}

通过回调registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); 完成将BeanDefinition注册进入factory。到这里解析的工作就完成了,接下来就是注册的过程,而注册方法属于DefaultListableBeanFactory

(10)registry.registerBeanDefinition

//---------------------------------------------------------------------
    // Implementation of BeanDefinitionRegistry interface
    //---------------------------------------------------------------------
//由于DefaultListableBeanFactory 实现了BeanDefinitionRegistry接口,而该接口的一个重要方法就是registerBeanDefinition,来注册BeanDefinition到Factory。

    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException {

        Assert.hasText(beanName, "Bean name must not be empty");
        Assert.notNull(beanDefinition, "BeanDefinition must not be null");

        if (beanDefinition instanceof AbstractBeanDefinition) {
            try {
                ((AbstractBeanDefinition) beanDefinition).validate();
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                        "Validation of bean definition failed", ex);
            }
        }

        BeanDefinition oldBeanDefinition;
//BeanDefinitonMap是保存BeanDefinition的地方,Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
oldBeanDefinition = this.beanDefinitionMap.get(beanName); if (oldBeanDefinition != null) { if (!isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound."); } else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) { // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE if (this.logger.isWarnEnabled()) { this.logger.warn("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } else { if (this.logger.isInfoEnabled()) { this.logger.info("Overriding bean definition for bean '" + beanName + "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } } else { //将Bean的name属性放入beanDefinitionNames中,该属性是一个ArrayList
            this.beanDefinitionNames.add(beanName);
            this.manualSingletonNames.remove(beanName);
            this.frozenBeanDefinitionNames = null;
        }
//这个是registry的核心过程,其实就是将BeanDefinition放入beanDefinitionMap中的过程。键是beanname,值是BeanDefinition.
        this.beanDefinitionMap.put(beanName, beanDefinition);

        if (oldBeanDefinition != null || containsSingleton(beanName)) {
            resetBeanDefinition(beanName);
        }
    }

5.依赖注入的过程

以上过程可以看成是IOC容器初始化的过程,这个初始化过程完成的主要工作是完成BeanDefinition在IOC容器中的数据映射。而这里并没有实例化任何对象,也从来没有完成过依赖注入的过程。

依赖注入是通过getBean方法完成的,当然如果将lazy-init属性设置为true,则可以在初始化的过程中完成依赖注入,实现预实例化。

Performer performer=(Performer) factory.getBean("dancer");通过getBean获得名为“dancer”的对象,而factory现在保有的仅仅是键为“dancer”的BeanDefinition对象(保存在Map中)。

下面就一步步看看这个依赖注入,或者是IOC控制反转到底是怎么实现的。

(1)getBean(String name)

这个方法并不属于DefaultListableBeanFactory,而是属于其父类AbstractBeanFactory,这是一个抽象类,abstract类型。主要用来具体实现了BeanFactory接口。

//---------------------------------------------------------------------
    // Implementation of BeanFactory interface
    //---------------------------------------------------------------------

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

可以看到具体的调用时doGetBean(String name)方法。

(2)doGetBean(String name)

/**
     * Return an instance, which may be shared or independent, of the specified bean.
     */
    @SuppressWarnings("unchecked")
    protected <T> T doGetBean(
            final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
            throws BeansException {

        final String beanName = transformedBeanName(name);
        Object bean;

        // Eagerly check singleton cache for manually registered singletons.
// 先从缓存中获得bean,处理那些已经被创建过的单例bean,这种bean不在重复创建。
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            if (logger.isDebugEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {
            // Fail if we're already creating this bean instance:
            // We're assumably within a circular reference.
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // Check if bean definition exists in this factory.
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                String nameToLookup = originalBeanName(name);
                if (args != null) {
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }

            try {
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // Guarantee initialization of beans that the current bean depends on.
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dependsOnBean : dependsOn) {
                        if (isDependent(beanName, dependsOnBean)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
                        }
                        registerDependentBean(dependsOnBean, beanName);
                        getBean(dependsOnBean);
                    }
                }

                // Create bean instance.
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                        @Override
                        public Object getObject() throws BeansException {
                            try {
                                return createBean(beanName, mbd, args);
                            }
                            catch (BeansException ex) {
                                // Explicitly remove instance from singleton cache: It might have been put there
                                // eagerly by the creation process, to allow for circular reference resolution.
                                // Also remove any beans that received a temporary reference to the bean.
                                destroySingleton(beanName);
                                throw ex;
                            }
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

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

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

        // Check if required type matches the type of the actual bean instance.
        if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
            try {
                return getTypeConverter().convertIfNecessary(bean, requiredType);
            }
            catch (TypeMismatchException ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Failed to convert bean '" + name + "' to required type [" +
                            ClassUtils.getQualifiedName(requiredType) + "]", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        return (T) bean;
    }

1.其中getSingleton()的方法主要是从DefaultListableBeanFactory中的singletonObjects属性去get获取,其中该属性是一个ConcurrentHashMap,用来保存单例Bean实例。

2.对BeanDefinition是否存在进行检查,这里就涉及到了双亲BeanFactory,如果当前Factory中没有找到,则查找parentBeanFactory,并且沿着双亲链一直往上找。

3.注册实例化所有依赖的bean。通过registerDependentBean(dependsOnBean, beanName)注册所依赖的bean,getBean(dependsOnBean)实例化依赖的bean.这里其实存在递归的过程。

4.ObjectFactory,是一个泛型接口,只有一个方法,getObject(),返回一个实例。

5.由于Bean默认的scope是singleton,所以会通过调用getSingleton来回调createBean来产生sharedInstance。

(3)getSingleton(String beanName, ObjectFactory<?> singletonFactory)

值得注意的是ObjectFactory这里的参量命名就是singletonFactory.

singletonObject = singletonFactory.getObject();这是回调的方法函数.

而由上一步可知singletonFactory是一个匿名内部类,实现了ObjectFactory接口.其中只进行了createBean()一个步骤。

(4)createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)

这个方法属于AbstractAutowireCapableBeanFactory,而由继承图知道AbstractAutowireCapableBeanFactory继承自AbstractBeanFactory抽象类,而createBean则是AbstractBeanFactory的一个抽象方法。

createBean

通过doCreateBean方法来实例化bean,在这之前会有一些列的处理过程。

(5)doCreateBean

/**
     * Actually create the specified bean. Pre-creation processing has already happened
     * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
     * <p>Differentiates between default bean instantiation, use of a
     * factory method, and autowiring a constructor.
    */
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
        // Instantiate the bean.
       // 这个BeanWrapper是用来持有创建出来的bean对象的
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
         //createBeanInstance是真正创建bean的地方.
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
        Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

        // Allow post-processors to modify the merged bean definition.
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                mbd.postProcessed = true;
            }
        }

        // Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            if (logger.isDebugEnabled()) {
                logger.debug("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            addSingletonFactory(beanName, new ObjectFactory<Object>() {
                @Override
                public Object getObject() throws BeansException {
                    return getEarlyBeanReference(beanName, mbd, bean);
                }
            });
        }

        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                exposedObject = initializeBean(beanName, exposedObject, mbd);
            }
        }
        catch (Throwable ex) {
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
                throw (BeanCreationException) ex;
            }
            else {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
            }
        }

        if (earlySingletonExposure) {
            Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                }
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
                    for (String dependentBean : dependentBeans) {
                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }
                    if (!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName,
                                "Bean with name '" + beanName + "' has been injected into other beans [" +
                                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                                "] in its raw version as part of a circular reference, but has eventually been " +
                                "wrapped. This means that said other beans do not use the final version of the " +
                                "bean. This is often the result of over-eager type matching - consider using " +
                                "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }

        // Register bean as disposable.
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }

        return exposedObject;
    }

1.首先是BeanWrapper作为保存持有bean对象的对象

2.通过createBeanInstance()来创建bean

3.populateBean()装配Bean对象

(6)createBeanInstance

/**
 * Create a new instance for the specified bean, using an appropriate instantiation strategy:
 * factory method, constructor autowiring, or simple instantiation.
 */
//对应实例化的三种方式,通过工厂方法实例化,通过构造器,简单实例化。
    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
        // Make sure bean class is actually resolved at this point.
        Class<?> beanClass = resolveBeanClass(mbd, beanName);

        if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
        }
       //实例化方式的选择可以通过mbd的参数来决定。这里是使用工厂方法的方式实例化。
        if (mbd.getFactoryMethodName() != null)  {
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }

        // Shortcut when re-creating the same bean...
        boolean resolved = false;
        boolean autowireNecessary = false;
        if (args == null) {
            synchronized (mbd.constructorArgumentLock) {
                if (mbd.resolvedConstructorOrFactoryMethod != null) {
                    resolved = true;
                    autowireNecessary = mbd.constructorArgumentsResolved;
                }
            }
        }
        if (resolved) {
            if (autowireNecessary) {
                return autowireConstructor(beanName, mbd, null, null);
            }
            else {
                return instantiateBean(beanName, mbd);
            }
        }

        // Need to determine the constructor...
       //选择合适参数的构造器进行实例化,这里由于存在参数所以选择带有参数的构造器实例化 
       Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors != null ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
            return autowireConstructor(beanName, mbd, ctors, args);
        }

        // No special handling: simply use no-arg constructor.
       //默认无参构造器,一般采用CGLIB字节码生成器类库进行实例或者JVM的反射功能。
        return instantiateBean(beanName, mbd);
    }

(7)autowireConstructor

这里是具体应用带参数构造器实例化对象的方法,通过逐步跟进可以发现这里是通过利用反射的思想进行的,首先是确定需要的构造器以及构造器的参数,然后再通过构造器对象的newInstance方法。DefaultListableBeanFactory默认的实例化策略是采用CGLIB的方式进行。

(8)populateBean()

该方法属于AbstractAutowireCapableBeanFactory抽象类

首先如果存在自动装配类型,则按照自动装配类型进行解决自动装配的问题。分为by_Name或者By_Type。否则直接应用applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs)进行属性装配。接下来逐步跟踪applyProperty方法

(9)applyProperty()

该方法同样属于AbstractAutowireCapableBeanFactory抽象类。

/**
     * Apply the given property values, resolving any runtime references
     * to other beans in this bean factory. Must use deep copy, so we
     * don't permanently modify this property.
     * @param beanName the bean name passed for better exception information
     * @param mbd the merged bean definition
     * @param bw the BeanWrapper wrapping the target object
     * @param pvs the new property values
 */
//其中三个形参分别为bean名称,BeanDefinition,Bean实例包装类,属性对象
    protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
        if (pvs == null || pvs.isEmpty()) {
            return;
        }

        MutablePropertyValues mpvs = null;
        List<PropertyValue> original;

        if (System.getSecurityManager() != null) {
            if (bw instanceof BeanWrapperImpl) {
                ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
            }
        }

        if (pvs instanceof MutablePropertyValues) {
            mpvs = (MutablePropertyValues) pvs;
            if (mpvs.isConverted()) {
                // Shortcut: use the pre-converted values as-is.
                try {
                    bw.setPropertyValues(mpvs);
                    return;
                }
                catch (BeansException ex) {
                    throw new BeanCreationException(
                            mbd.getResourceDescription(), beanName, "Error setting property values", ex);
                }
            }
            original = mpvs.getPropertyValueList();
        }
        else {
            original = Arrays.asList(pvs.getPropertyValues());
        }

        TypeConverter converter = getCustomTypeConverter();
        if (converter == null) {
            converter = bw;
        }
        BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

        // Create a deep copy, resolving any references for values.
        //这里有一个深拷贝,对每一个属性对象建立一个副本。
        List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
        boolean resolveNecessary = false;
        for (PropertyValue pv : original) {
            if (pv.isConverted()) {
                deepCopy.add(pv);
            }
            else {
                String propertyName = pv.getName();
                Object originalValue = pv.getValue();
                Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
                Object convertedValue = resolvedValue;
                boolean convertible = bw.isWritableProperty(propertyName) &&
                        !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
                if (convertible) {
                    convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
                }
                // Possibly store converted value in merged bean definition,
                // in order to avoid re-conversion for every created bean instance.
                if (resolvedValue == originalValue) {
                    if (convertible) {
                        pv.setConvertedValue(convertedValue);
                    }
                    deepCopy.add(pv);
                }
                else if (convertible && originalValue instanceof TypedStringValue &&
                        !((TypedStringValue) originalValue).isDynamic() &&
                        !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
                    pv.setConvertedValue(convertedValue);
                    deepCopy.add(pv);
                }
                else {
                    resolveNecessary = true;
                    deepCopy.add(new PropertyValue(pv, convertedValue));
                }
            }
        }
        if (mpvs != null && !resolveNecessary) {
            mpvs.setConverted();
        }

        // Set our (possibly massaged) deep copy.
        try {
            bw.setPropertyValues(new MutablePropertyValues(deepCopy));
        }
        catch (BeansException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Error setting property values", ex);
        }
    }

这里是处理属性进行依赖注入的过程,总的来看分为如下几步:

1.获得属性对象PropertyValue,对属性对象分别进行重新解析,解析之后再放入List deepcopy中。

2.其中涉及到了类型转换的问题,采用BeanDefinitionValueResolver进行类型转换的工作。resolveValueIfNecessary()这里对于ref类型,以及内部类的问题,都有相应的实例化处理过程。

public Object resolveValueIfNecessary(Object argName, Object value) {
        // We must check each value to see whether it requires a runtime reference
        // to another bean to be resolved.
        if (value instanceof RuntimeBeanReference) {
            RuntimeBeanReference ref = (RuntimeBeanReference) value;
            return resolveReference(argName, ref);
        }
        else if (value instanceof RuntimeBeanNameReference) {
            String refName = ((RuntimeBeanNameReference) value).getBeanName();
            refName = String.valueOf(doEvaluate(refName));
            if (!this.beanFactory.containsBean(refName)) {
                throw new BeanDefinitionStoreException(
                        "Invalid bean name '" + refName + "' in bean reference for " + argName);
            }
            return refName;
        }
        else if (value instanceof BeanDefinitionHolder) {
            // Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.
            BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
            return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
        }
        else if (value instanceof BeanDefinition) {
            // Resolve plain BeanDefinition, without contained name: use dummy name.
            BeanDefinition bd = (BeanDefinition) value;
            String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR +
                    ObjectUtils.getIdentityHexString(bd);
            return resolveInnerBean(argName, innerBeanName, bd);
        }
        ...............
    }

对于ref类型会出发getBean()方法,从而引发递归依赖注入;

而对于内部匿名类,本例子中就是,则会按照BeanDefinitionHolder进行处理,应用的方法是resolveInnerBean(),而这个方法会触发DefaultListableBeanFactory中的一些列的处理内部类的方法,同样也分为register和create。

3.调用BeanWrapper的setPropertyValues()方法进行依赖注入

(10)setPropertyValues()

setPropertyValues()会依次应用setPropertyValue()逐个属性进行装配。setPropertyValue(PropertyValue pv)方法属于BeanWrapperImpl

在这个方法中,分别对Array,List,Map,以及非集合类进行注入。

以非集合类为例,如String类型,该Bean有一个String属性名为name,而这个注入的过程就是通过反射获得setter,setName(String name)方法,然后invoke()实现。

四. 总结

这可能是分析源码学习过程中最难的一次经历,当然也是最有收获最有成就感的一次学习过程。

虽然从头捋顺清楚了IOC容器的实现原理,但是不得不说好多其内在的设计模式并没有完全领会,而且Spring框架的优秀之处,其对各种细节情况的处理也没有细致分析。

而且这并不是常用的例子,最为常用的应该还是各种ApplicationContext,下一步就是ApplicationContext的分析。

posted @ 2016-03-01 10:43  Tobe程序源  阅读(7283)  评论(0编辑  收藏  举报