zoukankan      html  css  js  c++  java
  • 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的分析。

  • 相关阅读:
    SpringBoot Rabbitmq接收消息
    SpringBoot Rabbitmq发送消息
    Rabbitmq 介绍
    Eureka 使用Spring cloud config 管理中心启动
    Spring Cloud Config 搭建Config 服务
    Eureka 向Server中注册服务
    Eureka 配置
    给定一些分割符,给定一个待分割的字符串,打印出分割之后最长的字符串
    给定N个整数,乱序,分行打印每个数字和其位置
    给定一个整数,求它的二进制表示中有多少个1
  • 原文地址:https://www.cnblogs.com/ToBeAProgrammer/p/5230065.html
Copyright © 2011-2022 走看看