• Spring技术与内幕IoC实现(二)


    1. 简介

    IOC:Inversion of Control 也称为依赖倒置原理(Dependency Inversion Principle):对象依赖关系的管理被反转了,对象之间的依赖关系由IoC容器进行管理,并且IoC完成对象的注入。

    SpringIoC:包含了最为基本的IoC容器BeanFactory的接口与实现。比如XmlBeanFactory 就是一个最基本的BeanFactory(IoC容器)。BeanFactory是一个简单容器系列,只实现了容器基本的功能;另一个是ApplicationContext 上下文,它作为容器的高级形态存在,继承自BeanFactory并增加了许多面向框架的特性,同时对应用环境作了许多适配。

    BeanFactory源码如下:

    package org.springframework.beans.factory;
    
    import org.springframework.beans.BeansException;
    import org.springframework.core.ResolvableType;
    import org.springframework.lang.Nullable;
    
    public interface BeanFactory {
        String FACTORY_BEAN_PREFIX = "&";
    
        Object getBean(String var1) throws BeansException;
    
        <T> T getBean(String var1, Class<T> var2) throws BeansException;
    
        Object getBean(String var1, Object... var2) throws BeansException;
    
        <T> T getBean(Class<T> var1) throws BeansException;
    
        <T> T getBean(Class<T> var1, Object... var2) throws BeansException;
    
        <T> ObjectProvider<T> getBeanProvider(Class<T> var1);
    
        <T> ObjectProvider<T> getBeanProvider(ResolvableType var1);
    
        boolean containsBean(String var1);
    
        boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
    
        boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
    
        boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;
    
        boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;
    
        @Nullable
        Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
    
        @Nullable
        Class<?> getType(String var1, boolean var2) throws NoSuchBeanDefinitionException;
    
        String[] getAliases(String var1);
    }

        在Spring提供的基本Ioc容器的接口定义和实现的基础上,Spring通过定义BeanDefinition来管理基于Spring的应用中的各种对象以及它们之间的相互依赖关系。BeanDefinition抽象了我们对Bean

    的定义,是让容器起作用的主要数据类型。BeanDefinition中维持了Bean是否是单例、是否Primary、是否Lazy等属性。源码如下:

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by FernFlower decompiler)
    //
    
    package org.springframework.beans.factory.config;
    
    import org.springframework.beans.BeanMetadataElement;
    import org.springframework.beans.MutablePropertyValues;
    import org.springframework.core.AttributeAccessor;
    import org.springframework.core.ResolvableType;
    import org.springframework.lang.Nullable;
    
    public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
        String SCOPE_SINGLETON = "singleton";
        String SCOPE_PROTOTYPE = "prototype";
        int ROLE_APPLICATION = 0;
        int ROLE_SUPPORT = 1;
        int ROLE_INFRASTRUCTURE = 2;
    
        void setParentName(@Nullable String var1);
    
        @Nullable
        String getParentName();
    
        void setBeanClassName(@Nullable String var1);
    
        @Nullable
        String getBeanClassName();
    
        void setScope(@Nullable String var1);
    
        @Nullable
        String getScope();
    
        void setLazyInit(boolean var1);
    
        boolean isLazyInit();
    
        void setDependsOn(@Nullable String... var1);
    
        @Nullable
        String[] getDependsOn();
    
        void setAutowireCandidate(boolean var1);
    
        boolean isAutowireCandidate();
    
        void setPrimary(boolean var1);
    
        boolean isPrimary();
    
        void setFactoryBeanName(@Nullable String var1);
    
        @Nullable
        String getFactoryBeanName();
    
        void setFactoryMethodName(@Nullable String var1);
    
        @Nullable
        String getFactoryMethodName();
    
        ConstructorArgumentValues getConstructorArgumentValues();
    
        default boolean hasConstructorArgumentValues() {
            return !this.getConstructorArgumentValues().isEmpty();
        }
    
        MutablePropertyValues getPropertyValues();
    
        default boolean hasPropertyValues() {
            return !this.getPropertyValues().isEmpty();
        }
    
        void setInitMethodName(@Nullable String var1);
    
        @Nullable
        String getInitMethodName();
    
        void setDestroyMethodName(@Nullable String var1);
    
        @Nullable
        String getDestroyMethodName();
    
        void setRole(int var1);
    
        int getRole();
    
        void setDescription(@Nullable String var1);
    
        @Nullable
        String getDescription();
    
        ResolvableType getResolvableType();
    
        boolean isSingleton();
    
        boolean isPrototype();
    
        boolean isAbstract();
    
        @Nullable
        String getResourceDescription();
    
        @Nullable
        BeanDefinition getOriginatingBeanDefinition();
    }

      在Spring具体的注入实现中,接口注入、setter注入、构造器注入是主要的注入方式。在Spring的IOC设计中,setter注入和构造器注入是主要的注入方式;相对而言,使用spring时setter注入

    是常见的注入方式,而且为了防止注入异常,spring IOC容器还提供了对特定依赖的检查。

    1. IoC容器设计

    主要类图如下:

    可以看到有两条线路:

    第一条是: BeanFactory到HierarchicalBeanFactory再到ConfigurableBeanFactory。在这条路线中,BeanFactory定义了接口的IoC容器的规范,HierarchicalBeanFactory 继承BeanFactory切增加了getParentBeanFactory方法,是的BeanFactory具备了双亲IoC容器的管理功能。在ConfigurableBeanFactory主要定义了一些对BeanFactory的配置功能,比如setParentBeanFactory 设置双亲IoC容器,通过addBeanPostProcessor 配置Bean后置处理器等。

    第二条:以ApplicationContext为主。这里主要是从BeanFactory到ListableBeanFactory,再到ApplicationContext,再到常用的ConfigurableApplicationContext或者WebApplicationContext。ApplicationCeontext通过继承MessageSource、ApplicationEventPublisher、ResourcePatternResolver 添加了许多对高级容器的特性的支持。

    1. BeanFactory应用场景以及设计原理

      用户使用容器时,可以使用转义符"&" 来得到FactoryBean 本身,用来区分FacrotyBean产生的对象和FactoryBean本身。举例来说,如果myJndiObject是一个FactoryBean,那么使用

    &myJndiObject 得到的是FactoryBean而不是myJndiObject 这个FactoryBean产生出来的对象。FactoryBean 默认是只生成工程Bean,在使用bean的时候才会生成bean。可以 SmartFactoryBean 的 isEagerInit 来进行控制,为true则在生成FactoryBean的时候调用工厂的getObject方法生成Bean。

      BeanFactory是个Factory,也就是IOC容器或对象工厂,FactoryBean是个Bean。在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。但对FactoryBean而言,这个

    Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似。

      BeanFactory提供了使用IoC容器的规范。在这个基础上,Spring还提供了一些容器的实现供开发人员使用,以XmlBeanFactory为例来说明IoC容器的设计原理。XmlBeanFactory 类图如下:

       XmlBeanFactory 继承自DefaultListableBeanFactory, DefaultListableBeanFactory 可以作为一个默认的功能完整的IoC容器来使用。XmlBeanFactory 在其基础上增加了新的功能-读取XML

    文件方式定义的BeanDefinition。其源码如下:

    public class XmlBeanFactory extends DefaultListableBeanFactory {
        private final XmlBeanDefinitionReader reader;
    
        public XmlBeanFactory(Resource resource) throws BeansException {
            this(resource, (BeanFactory)null);
        }
    
        public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
            super(parentBeanFactory);
            this.reader = new XmlBeanDefinitionReader(this);
            this.reader.loadBeanDefinitions(resource);
        }
    }

      XmlBeanFactory 构造时需要指定BeanDefinition 的信息来源,而这个信息需要封装成 Spring的Resource类来给出。从源码可以看出在构造方法中得到Resource对象以及使用这个对象来完成

    loadBeanDefinitions 的调用,这个方法也是IoC容器初始化的重要组成部分。

      编程式的IoC容器使用如下:

            ClassPathResource classPathResource = new ClassPathResource("beans.xml");
            DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
            XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory);
            xmlBeanDefinitionReader.loadBeanDefinitions(classPathResource);

    (1) 创建IoC配置文件的抽象资源,这个抽象资源包含了BeanDefinition的定义信息

    (2)创建一个BeanDefactory,这里使用默认的DefaultListableBeanDactory

    (3)创建一个载入BeanDefinition的读取器,这里使用XmlBeanDefinitionReader

    (4)从定义好的资源位置读取配置信息,具体的解析过程由XmlBeanDefinitionReader 来完成。完成整个载入和注册Bean定义之后,IoC容器就建立起来了,这个时候就可以使用IoC容器了。

    XmlBeanDefinitionReader .loadBeanDefinitions 过程如下:

    1》 交给重载的loadBeanDefinitions(EncodedResource encodedResource) 方法,方法内部获取到资源后调用doLoadBeanDefinitions 做具体的操作

      public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
            return this.loadBeanDefinitions(new EncodedResource(resource));
        }
    
        public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
            Assert.notNull(encodedResource, "EncodedResource must not be null");
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Loading XML bean definitions from " + encodedResource);
            }
    
            Set<EncodedResource> currentResources = (Set)this.resourcesCurrentlyBeingLoaded.get();
            if (currentResources == null) {
                currentResources = new HashSet(4);
                this.resourcesCurrentlyBeingLoaded.set(currentResources);
            }
    
            if (!((Set)currentResources).add(encodedResource)) {
                throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");
            } else {
                int var5;
                try {
                    InputStream inputStream = encodedResource.getResource().getInputStream();
    
                    try {
                        InputSource inputSource = new InputSource(inputStream);
                        if (encodedResource.getEncoding() != null) {
                            inputSource.setEncoding(encodedResource.getEncoding());
                        }
    
                        var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
                    } finally {
                        inputStream.close();
                    }
                } catch (IOException var15) {
                    throw new BeanDefinitionStoreException("IOException parsing XML document from " + encodedResource.getResource(), var15);
                } finally {
                    ((Set)currentResources).remove(encodedResource);
                    if (((Set)currentResources).isEmpty()) {
                        this.resourcesCurrentlyBeingLoaded.remove();
                    }
    
                }
    
                return var5;
            }
        }

    2》doLoadBeanDefinitions 方法内部先调用 doLoadDocument 先构建Document对象(XML 文档树); 然后调用registerBeanDefinitions 注册BeanDefinition信息

        protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
            try {
                Document doc = this.doLoadDocument(inputSource, resource);
                int count = this.registerBeanDefinitions(doc, resource);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Loaded " + count + " bean definitions from " + resource);
                }
    
                return count;
            } catch (BeanDefinitionStoreException var5) {
                throw var5;
            } catch (SAXParseException var6) {
                throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + var6.getLineNumber() + " in XML document from " + resource + " is invalid", var6);
            } catch (SAXException var7) {
                throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", var7);
            } catch (ParserConfigurationException var8) {
                throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, var8);
            } catch (IOException var9) {
                throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, var9);
            } catch (Throwable var10) {
                throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, var10);
            }
        }

    3》registerBeanDefinitions 方法内部先构造了BeanDefinitionDocumentReader 对象,然后交给BeanDefinitionDocumentReader 注册完BeanDefinition之后减去注册之前的数量返回结果

        public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
            BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();
            int countBefore = this.getRegistry().getBeanDefinitionCount();
            documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));
            return this.getRegistry().getBeanDefinitionCount() - countBefore;
        }

    3.1 》 getBeanDefinitionCount 是父类DefaultListableBeanFactory  的一个方法,其逻辑是返回beanDefinitionMap 的大小(这也证实了IoC的对象是存在一个Map里面)

        private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
    
        public int getBeanDefinitionCount() {
            return this.beanDefinitionMap.size();
        }

    3.2》createReaderContext 方法构造了一个XmlReaderContext 对象,用于包装注册时的上下文

        public XmlReaderContext createReaderContext(Resource resource) {
            return new XmlReaderContext(resource, this.problemReporter, this.eventListener, this.sourceExtractor, this, this.getNamespaceHandlerResolver());
        }

    3.3》DefaultBeanDefinitionDocumentReader#registerBeanDefinitions是注册BeanDefinition的重点,doRegisterBeanDefinitions 是核心方法

        public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
            this.readerContext = readerContext;
            this.doRegisterBeanDefinitions(doc.getDocumentElement());
        }

    3.3.1》doRegisterBeanDefinitions 方法如下, 核心交给parseBeanDefinitions方法

        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);
                    // We cannot use Profiles.of(...) since profile expressions are not supported
                    // in XML config. See SPR-12458 for details.
                    if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                        if (logger.isDebugEnabled()) {
                            logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                                    "] not matching: " + getReaderContext().getResource());
                        }
                        return;
                    }
                }
            }
    
            preProcessXml(root);
            parseBeanDefinitions(root, this.delegate);
            postProcessXml(root);
    
            this.delegate = parent;
        }

    3.3.2》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);
            }
        }

    3.3.3》parseDefaultElement 方法如下:BEAN_ELEMENT的"bean" 元素,对应的在org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#BEAN_ELEMENT 中维护

        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);
            }
        }

    3.3.4》 查看解析bean 元素的processBeanDefinition 方法如下

        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));
            }
        }

    第一步创建BeanDefinitionHolder 维护信息:org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionElement(org.w3c.dom.Element) 创建BeanDefinitionHolder相关信息:其实Holder就是维护了BeanDefinition信息和bean的name等信息

        /**
         * Parses the supplied {@code <bean>} element. May return {@code null}
         * if there were errors during parse. Errors are reported to the
         * {@link org.springframework.beans.factory.parsing.ProblemReporter}.
         */
        @Nullable
        public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
            return parseBeanDefinitionElement(ele, null);
        }
    
        /**
         * Parses the supplied {@code <bean>} element. May return {@code null}
         * if there were errors during parse. Errors are reported to the
         * {@link org.springframework.beans.factory.parsing.ProblemReporter}.
         */
        @Nullable
        public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
            String id = ele.getAttribute(ID_ATTRIBUTE);
            String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
    
            List<String> aliases = new ArrayList<>();
            if (StringUtils.hasLength(nameAttr)) {
                String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
                aliases.addAll(Arrays.asList(nameArr));
            }
    
            String beanName = id;
            if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
                beanName = aliases.remove(0);
                if (logger.isTraceEnabled()) {
                    logger.trace("No XML 'id' specified - using '" + beanName +
                            "' as bean name and " + aliases + " as aliases");
                }
            }
    
            if (containingBean == null) {
                checkNameUniqueness(beanName, aliases, ele);
            }
    
            AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
            if (beanDefinition != null) {
                if (!StringUtils.hasText(beanName)) {
                    try {
                        if (containingBean != null) {
                            beanName = BeanDefinitionReaderUtils.generateBeanName(
                                    beanDefinition, this.readerContext.getRegistry(), true);
                        }
                        else {
                            beanName = this.readerContext.generateBeanName(beanDefinition);
                            // Register an alias for the plain bean class name, if still possible,
                            // if the generator returned the class name plus a suffix.
                            // This is expected for Spring 1.2/2.0 backwards compatibility.
                            String beanClassName = beanDefinition.getBeanClassName();
                            if (beanClassName != null &&
                                    beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
                                    !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
                                aliases.add(beanClassName);
                            }
                        }
                        if (logger.isTraceEnabled()) {
                            logger.trace("Neither XML 'id' nor 'name' specified - " +
                                    "using generated bean name [" + beanName + "]");
                        }
                    }
                    catch (Exception ex) {
                        error(ex.getMessage(), ele);
                        return null;
                    }
                }
                String[] aliasesArray = StringUtils.toStringArray(aliases);
                return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
            }
    
            return null;
        }

    第二步交给org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerBeanDefinition进行注册,BeanDefinitionRegistry 是一开始创建的DefaultBeanFactory,在创建XmlBeanDefinitionReader 的时候维护。

        /**
         * 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。经过一圈处理加工之后最后回到org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition,源码如下:可以看到进行了一系列判断,验证是否已经存在等信息,如果不存在将BeanDefinition加入到beanDefinitionMap(ConcurrentHashMap),并且将bean的name加入到beanDefinitionNames(ArrayList)

        @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 existingDefinition = this.beanDefinitionMap.get(beanName);
            if (existingDefinition != null) {
                if (!isAllowBeanDefinitionOverriding()) {
                    throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
                }
                else if (existingDefinition.getRole() < beanDefinition.getRole()) {
                    // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
                    if (logger.isInfoEnabled()) {
                        logger.info("Overriding user-defined bean definition for bean '" + beanName +
                                "' with a framework-generated bean definition: replacing [" +
                                existingDefinition + "] with [" + beanDefinition + "]");
                    }
                }
                else if (!beanDefinition.equals(existingDefinition)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Overriding bean definition for bean '" + beanName +
                                "' with a different definition: replacing [" + existingDefinition +
                                "] with [" + beanDefinition + "]");
                    }
                }
                else {
                    if (logger.isTraceEnabled()) {
                        logger.trace("Overriding bean definition for bean '" + beanName +
                                "' with an equivalent definition: replacing [" + existingDefinition +
                                "] with [" + beanDefinition + "]");
                    }
                }
                this.beanDefinitionMap.put(beanName, beanDefinition);
            }
            else {
                if (hasBeanCreationStarted()) {
                    // Cannot modify startup-time collection elements anymore (for stable iteration)
                    synchronized (this.beanDefinitionMap) {
                        this.beanDefinitionMap.put(beanName, beanDefinition);
                        List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                        updatedDefinitions.addAll(this.beanDefinitionNames);
                        updatedDefinitions.add(beanName);
                        this.beanDefinitionNames = updatedDefinitions;
                        removeManualSingletonName(beanName);
                    }
                }
                else {
                    // Still in startup registration phase
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                    this.beanDefinitionNames.add(beanName);
                    removeManualSingletonName(beanName);
                }
                this.frozenBeanDefinitionNames = null;
            }
    
            if (existingDefinition != null || containsSingleton(beanName)) {
                resetBeanDefinition(beanName);
            }
            else if (isConfigurationFrozen()) {
                clearByTypeCache();
            }
        }

    第三步发布注册事件。

    2.ApplicationContext应用场景

     ApplicationContext 在 BeanFactory 的基础上扩展了以下几点:

    (1) 支持不同的信息源。 扩展了MessageSource接口,扩展的功能可以指出国际化。

    (2) 访问资源。继承了ResourcePatternResolver。这样我们可以从不同的地方获取Bean定义信息。

    (3) 支持应用事件。继承了ApplicationEventPublisher接口,从而在上下文中引入了事件机制。这些事件和Bean的生命周期的结合为Bean管理提供了遍历。

    以 AnnotationConfigApplicationContext 为例子说明其简单的注册过程。

    编程式的过程如下:

            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainApp.class);
            UserService bean = applicationContext.getBean(UserService.class);
            String s = bean.method1();
            System.out.println(s);

    其实只要第一行代码就已经完成了IoC的创建。

    简答分析下其过程:

    1》AnnotationConfigApplicationContext 构造方法中也是先创建了一个Reader、一个Scanner。接着调用自身的register 方法、refresh方法

        private final AnnotatedBeanDefinitionReader reader;
    
        private final ClassPathBeanDefinitionScanner scanner;
    
        /**
         * Create a new AnnotationConfigApplicationContext, deriving bean definitions
         * from the given component classes and automatically refreshing the context.
         * @param componentClasses one or more component classes &mdash; for example,
         * {@link Configuration @Configuration} classes
         */
        public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
            this();
            register(componentClasses);
            refresh();
        }
    
        /**
         * Create a new AnnotationConfigApplicationContext that needs to be populated
         * through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
         */
        public AnnotationConfigApplicationContext() {
            this.reader = new AnnotatedBeanDefinitionReader(this);
            this.scanner = new ClassPathBeanDefinitionScanner(this);
        }

    2》org.springframework.context.annotation.AnnotationConfigApplicationContext#register 方法如下: 其实也是调用reader将自身注册进去

        @Override
        public void register(Class<?>... componentClasses) {
            Assert.notEmpty(componentClasses, "At least one component class must be specified");
            this.reader.register(componentClasses);
        }

     2.1》org.springframework.context.annotation.AnnotatedBeanDefinitionReader#register 代码如下: 最终也是到 doRegisterBean 方法

        /**
         * Register one or more component classes to be processed.
         * <p>Calls to {@code register} are idempotent; adding the same
         * component class more than once has no additional effect.
         * @param componentClasses one or more component classes,
         * e.g. {@link Configuration @Configuration} classes
         */
        public void register(Class<?>... componentClasses) {
            for (Class<?> componentClass : componentClasses) {
                registerBean(componentClass);
            }
        }
    
        /**
         * Register a bean from the given bean class, deriving its metadata from
         * class-declared annotations.
         * @param beanClass the class of the bean
         */
        public void registerBean(Class<?> beanClass) {
            doRegisterBean(beanClass, null, null, null);
        }
    
        /**
         * Register a bean from the given bean class, deriving its metadata from
         * class-declared annotations.
         * @param beanClass the class of the bean
         * @param instanceSupplier a callback for creating an instance of the bean
         * (may be {@code null})
         * @param name an explicit name for the bean
         * @param qualifiers specific qualifier annotations to consider, if any,
         * in addition to qualifiers at the bean class level
         * @param definitionCustomizers one or more callbacks for customizing the
         * factory's {@link BeanDefinition}, e.g. setting a lazy-init or primary flag
         * @since 5.0
         */
        <T> void doRegisterBean(Class<T> beanClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
                @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
    
            AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
            if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
                return;
            }
    
            abd.setInstanceSupplier(instanceSupplier);
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
            abd.setScope(scopeMetadata.getScopeName());
            String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
    
            AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
            if (qualifiers != null) {
                for (Class<? extends Annotation> qualifier : qualifiers) {
                    if (Primary.class == qualifier) {
                        abd.setPrimary(true);
                    }
                    else if (Lazy.class == qualifier) {
                        abd.setLazyInit(true);
                    }
                    else {
                        abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                    }
                }
            }
            for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
                customizer.customize(abd);
            }
    
            BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
            definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
            BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
        }

    doRegisterBean 方法的核心是

    2.1.1》new AnnotatedGenericBeanDefinition(beanClass); 建一个AnnotatedGenericBeanDefinition 对象,AnnotatedGenericBeanDefinition 构造方法内部读取了类的一些注解信息并封装到metadata属性中,其实就是一个BeanDefinition对象。之后设置一些数据,生成beanName。

    2.2.2》AnnotationConfigUtils.processCommonDefinitionAnnotations(abd) 处理类上的注解信息,如下: 主要是处理类上的一些注解然后记录到上面生成的AnnotatedGenericBeanDefinition 对象中

        public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
            processCommonDefinitionAnnotations(abd, abd.getMetadata());
        }
    
        static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
            AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
            if (lazy != null) {
                abd.setLazyInit(lazy.getBoolean("value"));
            }
            else if (abd.getMetadata() != metadata) {
                lazy = attributesFor(abd.getMetadata(), Lazy.class);
                if (lazy != null) {
                    abd.setLazyInit(lazy.getBoolean("value"));
                }
            }
    
            if (metadata.isAnnotated(Primary.class.getName())) {
                abd.setPrimary(true);
            }
            AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
            if (dependsOn != null) {
                abd.setDependsOn(dependsOn.getStringArray("value"));
            }
    
            AnnotationAttributes role = attributesFor(metadata, Role.class);
            if (role != null) {
                abd.setRole(role.getNumber("value").intValue());
            }
            AnnotationAttributes description = attributesFor(metadata, Description.class);
            if (description != null) {
                abd.setDescription(description.getString("value"));
            }
        }

    2.2.3》接下来就同上面XmlBeanFactory逻辑一样:创建BeanDefinitionHolder 对象

    2.2.4》AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry)  主要是判断类的@Scope的proxyMode 的属性,如果不是DEFAULT、NO 会根据设置生成对应的代理对象,也就是说改变 definitionHolder  的引用。org.springframework.context.annotation.Scope 的proxyMode 可以指定为IoC容器是否生成代理对象,如果生成代理对象,会在下面注册BeanDefnition时注册两个对象,一个源对象、一个代理对象。org.springframework.context.annotation.AnnotationConfigUtils#applyScopedProxyMode 源码如下:

        static BeanDefinitionHolder applyScopedProxyMode(
                ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
    
            ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
            if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
                return definition;
            }
            boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
            return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
        }

    2.2.4.1》如果不是NO的话会生成Proxy,org.springframework.context.annotation.ScopedProxyCreator#createScopedProxy 源码如下:

        public static BeanDefinitionHolder createScopedProxy(
                BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) {
    
            return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass);
        }

    2.2.4.2》org.springframework.aop.scope.ScopedProxyUtils#createScopedProxy源码如下:

        /**
         * Generate a scoped proxy for the supplied target bean, registering the target
         * bean with an internal name and setting 'targetBeanName' on the scoped proxy.
         * @param definition the original bean definition
         * @param registry the bean definition registry
         * @param proxyTargetClass whether to create a target class proxy
         * @return the scoped proxy definition
         * @see #getTargetBeanName(String)
         * @see #getOriginalBeanName(String)
         */
        public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
                BeanDefinitionRegistry registry, boolean proxyTargetClass) {
    
            String originalBeanName = definition.getBeanName();
            BeanDefinition targetDefinition = definition.getBeanDefinition();
            String targetBeanName = getTargetBeanName(originalBeanName);
    
            // Create a scoped proxy definition for the original bean name,
            // "hiding" the target bean in an internal target definition.
            RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
            proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName));
            proxyDefinition.setOriginatingBeanDefinition(targetDefinition);
            proxyDefinition.setSource(definition.getSource());
            proxyDefinition.setRole(targetDefinition.getRole());
    
            proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
            if (proxyTargetClass) {
                targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
                // ScopedProxyFactoryBean's "proxyTargetClass" default is TRUE, so we don't need to set it explicitly here.
            }
            else {
                proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
            }
    
            // Copy autowire settings from original bean definition.
            proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
            proxyDefinition.setPrimary(targetDefinition.isPrimary());
            if (targetDefinition instanceof AbstractBeanDefinition) {
                proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
            }
    
            // The target bean should be ignored in favor of the scoped proxy.
            targetDefinition.setAutowireCandidate(false);
            targetDefinition.setPrimary(false);
    
            // Register the target bean as separate bean in the factory.
            registry.registerBeanDefinition(targetBeanName, targetDefinition);
    
            // Return the scoped proxy definition as primary bean definition
            // (potentially an inner bean).
            return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
        }

    这里的逻辑大致是:

    (1)根据源beanName生成targetName的规则如下:

        private static final String TARGET_NAME_PREFIX = "scopedTarget.";
        public static String getTargetBeanName(String originalBeanName) {
            return TARGET_NAME_PREFIX + originalBeanName;
        }

    (2) 接下来就是创建一个RootBeanDefinition 对象,并且记录原来的BeanDefinition信息以及代理Definition信息

    RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);

    这行代码主要是将BeanDefinition的class设置为ScopedProxyFactoryBean,  ScopedProxyFactoryBean 是一个FactoryBean,是一个生产Bean的工厂。可以猜出来是一个生产代理对象的工厂。源码如下:

    /*
     * Copyright 2002-2018 the original author or authors.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      https://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package org.springframework.aop.scope;
    
    import java.lang.reflect.Modifier;
    
    import org.springframework.aop.framework.AopInfrastructureBean;
    import org.springframework.aop.framework.ProxyConfig;
    import org.springframework.aop.framework.ProxyFactory;
    import org.springframework.aop.support.DelegatingIntroductionInterceptor;
    import org.springframework.aop.target.SimpleBeanTargetSource;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.BeanFactoryAware;
    import org.springframework.beans.factory.FactoryBean;
    import org.springframework.beans.factory.FactoryBeanNotInitializedException;
    import org.springframework.beans.factory.config.ConfigurableBeanFactory;
    import org.springframework.lang.Nullable;
    import org.springframework.util.Assert;
    import org.springframework.util.ClassUtils;
    
    /**
     * Convenient proxy factory bean for scoped objects.
     *
     * <p>Proxies created using this factory bean are thread-safe singletons
     * and may be injected into shared objects, with transparent scoping behavior.
     *
     * <p>Proxies returned by this class implement the {@link ScopedObject} interface.
     * This presently allows for removing the corresponding object from the scope,
     * seamlessly creating a new instance in the scope on next access.
     *
     * <p>Please note that the proxies created by this factory are
     * <i>class-based</i> proxies by default. This can be customized
     * through switching the "proxyTargetClass" property to "false".
     *
     * @author Rod Johnson
     * @author Juergen Hoeller
     * @since 2.0
     * @see #setProxyTargetClass
     */
    @SuppressWarnings("serial")
    public class ScopedProxyFactoryBean extends ProxyConfig
            implements FactoryBean<Object>, BeanFactoryAware, AopInfrastructureBean {
    
        /** The TargetSource that manages scoping. */
        private final SimpleBeanTargetSource scopedTargetSource = new SimpleBeanTargetSource();
    
        /** The name of the target bean. */
        @Nullable
        private String targetBeanName;
    
        /** The cached singleton proxy. */
        @Nullable
        private Object proxy;
    
    
        /**
         * Create a new ScopedProxyFactoryBean instance.
         */
        public ScopedProxyFactoryBean() {
            setProxyTargetClass(true);
        }
    
    
        /**
         * Set the name of the bean that is to be scoped.
         */
        public void setTargetBeanName(String targetBeanName) {
            this.targetBeanName = targetBeanName;
            this.scopedTargetSource.setTargetBeanName(targetBeanName);
        }
    
        @Override
        public void setBeanFactory(BeanFactory beanFactory) {
            if (!(beanFactory instanceof ConfigurableBeanFactory)) {
                throw new IllegalStateException("Not running in a ConfigurableBeanFactory: " + beanFactory);
            }
            ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanFactory;
    
            this.scopedTargetSource.setBeanFactory(beanFactory);
    
            ProxyFactory pf = new ProxyFactory();
            pf.copyFrom(this);
            pf.setTargetSource(this.scopedTargetSource);
    
            Assert.notNull(this.targetBeanName, "Property 'targetBeanName' is required");
            Class<?> beanType = beanFactory.getType(this.targetBeanName);
            if (beanType == null) {
                throw new IllegalStateException("Cannot create scoped proxy for bean '" + this.targetBeanName +
                        "': Target type could not be determined at the time of proxy creation.");
            }
            if (!isProxyTargetClass() || beanType.isInterface() || Modifier.isPrivate(beanType.getModifiers())) {
                pf.setInterfaces(ClassUtils.getAllInterfacesForClass(beanType, cbf.getBeanClassLoader()));
            }
    
            // Add an introduction that implements only the methods on ScopedObject.
            ScopedObject scopedObject = new DefaultScopedObject(cbf, this.scopedTargetSource.getTargetBeanName());
            pf.addAdvice(new DelegatingIntroductionInterceptor(scopedObject));
    
            // Add the AopInfrastructureBean marker to indicate that the scoped proxy
            // itself is not subject to auto-proxying! Only its target bean is.
            pf.addInterface(AopInfrastructureBean.class);
    
            this.proxy = pf.getProxy(cbf.getBeanClassLoader());
        }
    
    
        @Override
        public Object getObject() {
            if (this.proxy == null) {
                throw new FactoryBeanNotInitializedException();
            }
            return this.proxy;
        }
    
        @Override
        public Class<?> getObjectType() {
            if (this.proxy != null) {
                return this.proxy.getClass();
            }
            return this.scopedTargetSource.getTargetClass();
        }
    
        @Override
        public boolean isSingleton() {
            return true;
        }
    
    }

    (3) 下面代码

            // Copy autowire settings from original bean definition.
            proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
            proxyDefinition.setPrimary(targetDefinition.isPrimary());
            if (targetDefinition instanceof AbstractBeanDefinition) {
                proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
            }
    
            // The target bean should be ignored in favor of the scoped proxy.
            targetDefinition.setAutowireCandidate(false);
            targetDefinition.setPrimary(false);

    将autowireCandidate 属性和Primary 属性置为目标definition的属性,然后将目标beanDefinition的autowireCandidate  属性和Primary属性置为false。

    autowireCandidate  为false,容器在查找自动装配对象时,将不考虑该bean,即该bean不会被作为其它bean自动装配的候选者,但该bean本身还是可以使用自动装配来注入其它bean的。

    Primary 属性很好理解,是否作为主对象。也就是如果默认会切换代理对象为Primary对象,原来的对象Primary为false。

    (4)下面代码注册目标对象,beanName为 "scopedTarget." + 原来的BeanName

            // Register the target bean as separate bean in the factory.
            registry.registerBeanDefinition(targetBeanName, targetDefinition);

    (5) 然后返回代理BeanDefinition,beanName为原来的BeanName。

    return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases())

    (6) 也就是用原来默认的beanName获取到的是代理对象,用"scopeTarget."+默认beanName 获取的是目标对象。如果目标对象是Primary主对象,代理对象会代替其成为Primary对象。

    2.2.3 》最后调用如下方法注册Bean, registry 就是创建的AnnotationConfigApplicationContext 对象

    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);

    2.2.3.1》org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerBeanDefinition 方法同上,调用具体的工厂注册Bean和别名

        /**
         * 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);
                }
            }
        }

    2.2.3.2》最终会交给org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition 方法来注册Bean

        @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 existingDefinition = this.beanDefinitionMap.get(beanName);
            if (existingDefinition != null) {
                if (!isAllowBeanDefinitionOverriding()) {
                    throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
                }
                else if (existingDefinition.getRole() < beanDefinition.getRole()) {
                    // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
                    if (logger.isInfoEnabled()) {
                        logger.info("Overriding user-defined bean definition for bean '" + beanName +
                                "' with a framework-generated bean definition: replacing [" +
                                existingDefinition + "] with [" + beanDefinition + "]");
                    }
                }
                else if (!beanDefinition.equals(existingDefinition)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Overriding bean definition for bean '" + beanName +
                                "' with a different definition: replacing [" + existingDefinition +
                                "] with [" + beanDefinition + "]");
                    }
                }
                else {
                    if (logger.isTraceEnabled()) {
                        logger.trace("Overriding bean definition for bean '" + beanName +
                                "' with an equivalent definition: replacing [" + existingDefinition +
                                "] with [" + beanDefinition + "]");
                    }
                }
                this.beanDefinitionMap.put(beanName, beanDefinition);
            }
            else {
                if (hasBeanCreationStarted()) {
                    // Cannot modify startup-time collection elements anymore (for stable iteration)
                    synchronized (this.beanDefinitionMap) {
                        this.beanDefinitionMap.put(beanName, beanDefinition);
                        List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                        updatedDefinitions.addAll(this.beanDefinitionNames);
                        updatedDefinitions.add(beanName);
                        this.beanDefinitionNames = updatedDefinitions;
                        removeManualSingletonName(beanName);
                    }
                }
                else {
                    // Still in startup registration phase
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                    this.beanDefinitionNames.add(beanName);
                    removeManualSingletonName(beanName);
                }
                this.frozenBeanDefinitionNames = null;
            }
    
            if (existingDefinition != null || containsSingleton(beanName)) {
                resetBeanDefinition(beanName);
            }
            else if (isConfigurationFrozen()) {
                clearByTypeCache();
            }
        }

    3》 上面将主类注入到了IoC中,接下来就是 refresh(); 方法注入其他业务Bean。 接下来这个才是IoC的核心入口,标记着IoC容器创建的开始。具体来说,启动包括BeanDefinition的Resource定位(BeanDefinition的定位)、载入(将Bean封装成BeanDefinition以及BeanDefinitionHolder)、注册(将BeanDefinition注入到一个ConcurrentHashMap)三个基本过程。分别对应BeanDefinitionReader、BeanDefinitionLoader、BeanDefinitionRegistry。

    注意这里的过程只是IoC容器的初始化,不包含Bean依赖注入的实现。在SpringIoC的设计中,Bean定义的载入和依赖注入是两个独立的过程。依赖注入一般发生在应用第一次通过getBean向容器索要Bean的时候。这里设计到Lazy 注解的使用。一般情况下,Spring容器在启动时会创建所有的Bean对象,使用@Lazy注解可以将Bean对象的创建延迟到第一次使用Bean的时候。@Lazy也可以解决许多循环依赖的问题。

    org.springframework.context.support.AbstractApplicationContext#refresh 源码如下:

        @Override
        public void refresh() throws BeansException, IllegalStateException {
            synchronized (this.startupShutdownMonitor) {
                // Prepare this context for refreshing.
                prepareRefresh();
    
                // Tell the subclass to refresh the internal bean factory.
                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
                // 装备BeanFactory以及环境信息.
                prepareBeanFactory(beanFactory);
    
                try {
                    // 设置Bean的后置处理.
                    postProcessBeanFactory(beanFactory);
    
                    // 调用BeanFactory的后处理器. 这些后处理器是在Bean定义中向容器注册的
                    invokeBeanFactoryPostProcessors(beanFactory);
    
                    // 注册Bean的后处理器,在Bean创建过程中调用.
                    registerBeanPostProcessors(beanFactory);
    
                    // Initialize message source for this context.
                    initMessageSource();
    
                    // Initialize event multicaster for this context.
                    initApplicationEventMulticaster();
    
                    // Initialize other special beans in specific context subclasses.
                    onRefresh();
    
                    // Check for listener beans and register them.
                    registerListeners();
    
                    // 实例化所有的(non-lazy-init)单件==也就是创建Bean的操作是在这一步进行的
                    finishBeanFactoryInitialization(beanFactory);
    
                    // 发布容器事件,结束refresh过程
                    finishRefresh();
                }
    
                catch (BeansException ex) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("Exception encountered during context initialization - " +
                                "cancelling refresh attempt: " + ex);
                    }
    
                    // Destroy already created singletons to avoid dangling resources.
                    destroyBeans();
    
                    // Reset 'active' flag.
                    cancelRefresh(ex);
    
                    // Propagate exception to caller.
                    throw ex;
                }
    
                finally {
                    // Reset common introspection caches in Spring's core, since we
                    // might not ever need metadata for singleton beans anymore...
                    resetCommonCaches();
                }
            }
        }

    3.1》prepareRefresh 这个方法没什么,就是简单的记录了开始时间以及准备前提环境

    3.2》obtainFreshBeanFactory();  判断是否有工厂

        /**
         * Tell the subclass to refresh the internal bean factory.
         * @return the fresh BeanFactory instance
         * @see #refreshBeanFactory()
         * @see #getBeanFactory()
         */
        protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
            refreshBeanFactory();
            return getBeanFactory();
        }

    3.2.1》 refreshBeanFactory方法是继承下来的org.springframework.context.support.GenericApplicationContext#refreshBeanFactory

    3.3》 prepareBeanFactory(beanFactory); 是提前处理BeanFactory的环境信息等

    3.4》invokeBeanFactoryPostProcessors 是核心所在,这里是调用BeanFactory的后处理器。是在注入之后,实例化之前调用,因此可以用于动态的注入BeanDefinition信息。是从父类AbstractApplicationContext继承下来的一个方法,org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors:

        /**
         * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
         * respecting explicit order if given.
         * <p>Must be called before singleton instantiation.
         */
        protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
            PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    
            // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
            // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
            if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
                beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
                beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
            }
        }

    3.4.1 org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors方法如下:

        public static void invokeBeanFactoryPostProcessors(
                ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    
            // 保存所有后置处理器bean名称的集合
            Set<String> processedBeans = new HashSet<>();
    
            // 判断beanFactory 是否是BeanDefinitionRegistry
            // 当是BeanDefinitionRegistry 时 将beanFactoryPostProcessors 分为BeanFactoryPostProcessor集合与BeanDefinitionRegistryPostProcessor集合
            if (beanFactory instanceof BeanDefinitionRegistry) {
                BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
                List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
                List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
    
                for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                    if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                        BeanDefinitionRegistryPostProcessor registryProcessor =
                                (BeanDefinitionRegistryPostProcessor) postProcessor;
                        // 当前postProcessor为BeanDefinitionRegistryPostProcessor时执行postProcessBeanDefinitionRegistry方法
                        registryProcessor.postProcessBeanDefinitionRegistry(registry);
                        registryProcessors.add(registryProcessor);
                    }
                    else {
                        regularPostProcessors.add(postProcessor);
                    }
                }
    
                // Do not initialize FactoryBeans here: We need to leave all regular beans
                // uninitialized to let the bean factory post-processors apply to them!
                // Separate between BeanDefinitionRegistryPostProcessors that implement
                // PriorityOrdered, Ordered, and the rest.
                List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
    
                // 首先在容器中查找实现了PriorityOrdered接口的的BeanDefinitionRegistryPostProcessors(bean定义注册后置处理器)名称
                // 将查找到的名称集合放置到processedBeans中,以及将后置处理器添加到集合currentRegistryProcessors中
                // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
                String[] postProcessorNames =
                        beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                for (String ppName : postProcessorNames) {
                    if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                        processedBeans.add(ppName);
                    }
                }
                sortPostProcessors(currentRegistryProcessors, beanFactory);
                registryProcessors.addAll(currentRegistryProcessors);
                // 遍历循环执行currentRegistryProcessors集合中的bean定义注册后置处理器
                invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
                // 清空currentRegistryProcessors集合
                currentRegistryProcessors.clear();
    
                // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                for (String ppName : postProcessorNames) {
                    if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                        processedBeans.add(ppName);
                    }
                }
                sortPostProcessors(currentRegistryProcessors, beanFactory);
                registryProcessors.addAll(currentRegistryProcessors);
                invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
                currentRegistryProcessors.clear();
    
                // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
                boolean reiterate = true;
                while (reiterate) {
                    reiterate = false;
                    postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                    for (String ppName : postProcessorNames) {
                        if (!processedBeans.contains(ppName)) {
                            currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                            processedBeans.add(ppName);
                            reiterate = true;
                        }
                    }
                    sortPostProcessors(currentRegistryProcessors, beanFactory);
                    registryProcessors.addAll(currentRegistryProcessors);
                    invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
                    currentRegistryProcessors.clear();
                }
    
                // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
                invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
                invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
            }
    
            else {
                // Invoke factory processors registered with the context instance.
                invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
            }
    
            // Do not initialize FactoryBeans here: We need to leave all regular beans
            // uninitialized to let the bean factory post-processors apply to them!
            String[] postProcessorNames =
                    beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    
            // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
            // Ordered, and the rest.
            List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
            List<String> orderedPostProcessorNames = new ArrayList<>();
            List<String> nonOrderedPostProcessorNames = new ArrayList<>();
            for (String ppName : postProcessorNames) {
                if (processedBeans.contains(ppName)) {
                    // skip - already processed in first phase above
                }
                else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
                }
                else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                    orderedPostProcessorNames.add(ppName);
                }
                else {
                    nonOrderedPostProcessorNames.add(ppName);
                }
            }
    
            // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
            sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
            invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
    
            // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
            List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
            for (String postProcessorName : orderedPostProcessorNames) {
                orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
            }
            sortPostProcessors(orderedPostProcessors, beanFactory);
            invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
    
            // Finally, invoke all other BeanFactoryPostProcessors.
            List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
            for (String postProcessorName : nonOrderedPostProcessorNames) {
                nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
            }
            invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
    
            // Clear cached merged bean definitions since the post-processors might have
            // modified the original metadata, e.g. replacing placeholders in values...
            beanFactory.clearMetadataCache();
        }

    根据传入beanFactory类型可分为两部分:我们着重看beanFactory是BeanDefinitionRegistry类型时的流程

    1. 遍历传入后置处理器集合查找类型为BeanDefinitionRegistryPostProcessor的后置处理器,调用后置处理器的postProcessBeanDefinitionRegistry方法
    2. 在容器中查找所有的实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor集合,对后置处理器集合排序,遍历,执行后置处理的postProcessBeanDefinitionRegistry方法

        /**
         * Invoke the given BeanDefinitionRegistryPostProcessor beans.
         */
        private static void invokeBeanDefinitionRegistryPostProcessors(
                Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
    
            for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
                postProcessor.postProcessBeanDefinitionRegistry(registry);
            }
        }

    3.在容器中查找所有实现了Ordered接口的BeanDefinitionRegistryPostProcessor集合,对后置处理器集合排序,遍历,执行后置处理的postProcessBeanDefinitionRegistry方法。
    4.在容器中查找其它(未实现排序接口)的BeanDefinitionRegistryPostProcessor并添加到集合nonOrderedPostProcessors中,对后置处理器集合排序,遍历,执行后置处理的postProcessBeanDefinitionRegistry方法
    5.当前所有的BeanDefinitionRegistryPostProcessor处理器的方法postProcessBeanDefinitionRegistry 执行完毕后,执行其父类postProcessBeanFactory方法
    6. 执行所有非BeanDefinitionRegistryPostProcessor类型的后置处理器的postProcessBeanFactory方法

    3.4.2》 上面会获取到org.springframework.context.annotation.ConfigurationClassPostProcessor 并添加到currentRegistryProcessors , 然后调用invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

        /**
         * Invoke the given BeanDefinitionRegistryPostProcessor beans.
         */
        private static void invokeBeanDefinitionRegistryPostProcessors(
                Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
    
            for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
                postProcessor.postProcessBeanDefinitionRegistry(registry);
            }
        }

    3.4.3》 接下来就是调用org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry

        /**
         * Derive further bean definitions from the configuration classes in the registry.
         */
        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
            int registryId = System.identityHashCode(registry);
            if (this.registriesPostProcessed.contains(registryId)) {
                throw new IllegalStateException(
                        "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
            }
            if (this.factoriesPostProcessed.contains(registryId)) {
                throw new IllegalStateException(
                        "postProcessBeanFactory already called on this post-processor against " + registry);
            }
            this.registriesPostProcessed.add(registryId);
    
            processConfigBeanDefinitions(registry);
        }

    3.4.4》org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions 方法如下:

        /**
         * Build and validate a configuration model based on the registry of
         * {@link Configuration} classes.
         */
        public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
            List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
            String[] candidateNames = registry.getBeanDefinitionNames();
    
            for (String beanName : candidateNames) {
                BeanDefinition beanDef = registry.getBeanDefinition(beanName);
                if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
                        ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
                    }
                }
                else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                    configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
                }
            }
    
            // Return immediately if no @Configuration classes were found
            if (configCandidates.isEmpty()) {
                return;
            }
    
            // Sort by previously determined @Order value, if applicable
            configCandidates.sort((bd1, bd2) -> {
                int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
                int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
                return Integer.compare(i1, i2);
            });
    
            // Detect any custom bean name generation strategy supplied through the enclosing application context
            SingletonBeanRegistry sbr = null;
            if (registry instanceof SingletonBeanRegistry) {
                sbr = (SingletonBeanRegistry) registry;
                if (!this.localBeanNameGeneratorSet) {
                    BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
                    if (generator != null) {
                        this.componentScanBeanNameGenerator = generator;
                        this.importBeanNameGenerator = generator;
                    }
                }
            }
    
            if (this.environment == null) {
                this.environment = new StandardEnvironment();
            }
    
            // Parse each @Configuration class
            ConfigurationClassParser parser = new ConfigurationClassParser(
                    this.metadataReaderFactory, this.problemReporter, this.environment,
                    this.resourceLoader, this.componentScanBeanNameGenerator, registry);
    
            Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
            Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
            do {
                parser.parse(candidates);
                parser.validate();
    
                Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
                configClasses.removeAll(alreadyParsed);
    
                // Read the model and create bean definitions based on its content
                if (this.reader == null) {
                    this.reader = new ConfigurationClassBeanDefinitionReader(
                            registry, this.sourceExtractor, this.resourceLoader, this.environment,
                            this.importBeanNameGenerator, parser.getImportRegistry());
                }
                this.reader.loadBeanDefinitions(configClasses);
                alreadyParsed.addAll(configClasses);
    
                candidates.clear();
                if (registry.getBeanDefinitionCount() > candidateNames.length) {
                    String[] newCandidateNames = registry.getBeanDefinitionNames();
                    Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
                    Set<String> alreadyParsedClasses = new HashSet<>();
                    for (ConfigurationClass configurationClass : alreadyParsed) {
                        alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
                    }
                    for (String candidateName : newCandidateNames) {
                        if (!oldCandidateNames.contains(candidateName)) {
                            BeanDefinition bd = registry.getBeanDefinition(candidateName);
                            if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                                    !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                                candidates.add(new BeanDefinitionHolder(bd, candidateName));
                            }
                        }
                    }
                    candidateNames = newCandidateNames;
                }
            }
            while (!candidates.isEmpty());
    
            // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
            if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
                sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
            }
    
            if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
                // Clear cache in externally provided MetadataReaderFactory; this is a no-op
                // for a shared cache since it'll be cleared by the ApplicationContext.
                ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
            }
        }

    (1) 这里的重点是先判断是否是包含配置类。 ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory) 方法。 其中可以作为配置的注解包括:

            candidateIndicators.add(Component.class.getName());
            candidateIndicators.add(ComponentScan.class.getName());
            candidateIndicators.add(Import.class.getName());
            candidateIndicators.add(ImportResource.class.getName());

     我们在主类打了@ComponentScan 注解,所以会被处理。 这里也了解到为什么@SpringBootApplication 注解加了@ComponentScan 注解。 而且@ComponentScan 注解可以指定许多属性,重要的包括是否Lazy,scopedProxy 上面是否使用代理等信息。

    (2) 第二步就是创建一个name生成器,然后创建一个 ConfigurationClassParser, 从名字就可以看出来是解析配置用的。然后调用parser.parse(candidates); 解析出信息存入ConfigurationClass。这个里面有几个重要的方法:org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>)

        public void parse(Set<BeanDefinitionHolder> configCandidates) {
            for (BeanDefinitionHolder holder : configCandidates) {
                BeanDefinition bd = holder.getBeanDefinition();
                try {
                    if (bd instanceof AnnotatedBeanDefinition) {
                        parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
                    }
                    else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
                        parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
                    }
                    else {
                        parse(bd.getBeanClassName(), holder.getBeanName());
                    }
                }
                catch (BeanDefinitionStoreException ex) {
                    throw ex;
                }
                catch (Throwable ex) {
                    throw new BeanDefinitionStoreException(
                            "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
                }
            }
    
            this.deferredImportSelectorHandler.process();
        }

    注解扫描走的是org.springframework.context.annotation.ConfigurationClassParser#parse(org.springframework.core.type.AnnotationMetadata, java.lang.String)

        protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
            processConfigurationClass(new ConfigurationClass(metadata, beanName));
        }

    接着调用下面方法

        protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
            if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
                return;
            }
    
            ConfigurationClass existingClass = this.configurationClasses.get(configClass);
            if (existingClass != null) {
                if (configClass.isImported()) {
                    if (existingClass.isImported()) {
                        existingClass.mergeImportedBy(configClass);
                    }
                    // Otherwise ignore new imported config class; existing non-imported class overrides it.
                    return;
                }
                else {
                    // Explicit bean definition found, probably replacing an import.
                    // Let's remove the old one and go with the new one.
                    this.configurationClasses.remove(configClass);
                    this.knownSuperclasses.values().removeIf(configClass::equals);
                }
            }
    
            // Recursively process the configuration class and its superclass hierarchy.
            SourceClass sourceClass = asSourceClass(configClass);
            do {
                sourceClass = doProcessConfigurationClass(configClass, sourceClass);
            }
            while (sourceClass != null);
    
            this.configurationClasses.put(configClass, configClass);
        }

    接着就是核心的扫描以及维护信息

        protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
                throws IOException {
    
            if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
                // Recursively process any member (nested) classes first
                processMemberClasses(configClass, sourceClass);
            }
    
            // Process any @PropertySource annotations
            for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
                    sourceClass.getMetadata(), PropertySources.class,
                    org.springframework.context.annotation.PropertySource.class)) {
                if (this.environment instanceof ConfigurableEnvironment) {
                    processPropertySource(propertySource);
                }
                else {
                    logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                            "]. Reason: Environment must implement ConfigurableEnvironment");
                }
            }
    
            // Process any @ComponentScan annotations
            Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
                    sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
            if (!componentScans.isEmpty() &&
                    !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
                for (AnnotationAttributes componentScan : componentScans) {
                    // The config class is annotated with @ComponentScan -> perform the scan immediately
                    Set<BeanDefinitionHolder> scannedBeanDefinitions =
                            this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                    // Check the set of scanned definitions for any further config classes and parse recursively if needed
                    for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                        BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                        if (bdCand == null) {
                            bdCand = holder.getBeanDefinition();
                        }
                        if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                            parse(bdCand.getBeanClassName(), holder.getBeanName());
                        }
                    }
                }
            }
    
            // Process any @Import annotations
            processImports(configClass, sourceClass, getImports(sourceClass), true);
    
            // Process any @ImportResource annotations
            AnnotationAttributes importResource =
                    AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
            if (importResource != null) {
                String[] resources = importResource.getStringArray("locations");
                Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
                for (String resource : resources) {
                    String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
                    configClass.addImportedResource(resolvedResource, readerClass);
                }
            }
    
            // Process individual @Bean methods
            Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
            for (MethodMetadata methodMetadata : beanMethods) {
                configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
            }
    
            // Process default methods on interfaces
            processInterfaces(configClass, sourceClass);
    
            // Process superclass, if any
            if (sourceClass.getMetadata().hasSuperClass()) {
                String superclass = sourceClass.getMetadata().getSuperClassName();
                if (superclass != null && !superclass.startsWith("java") &&
                        !this.knownSuperclasses.containsKey(superclass)) {
                    this.knownSuperclasses.put(superclass, configClass);
                    // Superclass found, return its annotation metadata and recurse
                    return sourceClass.getSuperClass();
                }
            }
    
            // No superclass -> processing is complete
            return null;
        }

    这里会处理一些注解信息,包含@Import等信息,其中org.springframework.context.annotation.ComponentScanAnnotationParser#parse处理@ComponentScan注解,源码如下:

        public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
            ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
                    componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
    
            Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
            boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
            scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
                    BeanUtils.instantiateClass(generatorClass));
    
            ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
            if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
                scanner.setScopedProxyMode(scopedProxyMode);
            }
            else {
                Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
                scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
            }
    
            scanner.setResourcePattern(componentScan.getString("resourcePattern"));
    
            for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
                for (TypeFilter typeFilter : typeFiltersFor(filter)) {
                    scanner.addIncludeFilter(typeFilter);
                }
            }
            for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
                for (TypeFilter typeFilter : typeFiltersFor(filter)) {
                    scanner.addExcludeFilter(typeFilter);
                }
            }
    
            boolean lazyInit = componentScan.getBoolean("lazyInit");
            if (lazyInit) {
                scanner.getBeanDefinitionDefaults().setLazyInit(true);
            }
    
            Set<String> basePackages = new LinkedHashSet<>();
            String[] basePackagesArray = componentScan.getStringArray("basePackages");
            for (String pkg : basePackagesArray) {
                String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
                        ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
                Collections.addAll(basePackages, tokenized);
            }
            for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
                basePackages.add(ClassUtils.getPackageName(clazz));
            }
         // 取不到值取当前配置类的包名为扫描的包
    if (basePackages.isEmpty()) { basePackages.add(ClassUtils.getPackageName(declaringClass)); } scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) { @Override protected boolean matchClassName(String className) { return declaringClass.equals(className); } }); return scanner.doScan(StringUtils.toStringArray(basePackages)); } protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>(); for (String basePackage : basePackages) { Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) { ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (candidate instanceof AbstractBeanDefinition) { postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }

    findCandidateComponents(basePackage)是继承下来的方法:org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#findCandidateComponents。扫描包下的所有类并进行判断,满足则加到BanDefinition集合中

        /**
         * Scan the class path for candidate components.
         * @param basePackage the package to check for annotated classes
         * @return a corresponding Set of autodetected bean definitions
         */
        public Set<BeanDefinition> findCandidateComponents(String basePackage) {
            if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
                return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
            }
            else {
                return scanCandidateComponents(basePackage);
            }
        }
    
        private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
            Set<BeanDefinition> candidates = new LinkedHashSet<>();
            try {
                // packageSearchPath = classpath*:qz/**/*.class
                String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                        resolveBasePackage(basePackage) + '/' + this.resourcePattern;
                // getResourcePatternResolver() 是 AnnotationConfigApplicationContext。  获取到包下的所有的类
                Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
    
                boolean traceEnabled = logger.isTraceEnabled();
                boolean debugEnabled = logger.isDebugEnabled();
                // 判断类是否满足条件,@Component 等注解信息,满足则加入集合
                for (Resource resource : resources) {
                    if (traceEnabled) {
                        logger.trace("Scanning " + resource);
                    }
                    if (resource.isReadable()) {
                        try {
                            MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                            if (isCandidateComponent(metadataReader)) {
                                ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                                sbd.setSource(resource);
                                if (isCandidateComponent(sbd)) {
                                    if (debugEnabled) {
                                        logger.debug("Identified candidate component class: " + resource);
                                    }
                                    candidates.add(sbd);
                                }
                                else {
                                    if (debugEnabled) {
                                        logger.debug("Ignored because not a concrete top-level class: " + resource);
                                    }
                                }
                            }
                            else {
                                if (traceEnabled) {
                                    logger.trace("Ignored because not matching any filter: " + resource);
                                }
                            }
                        }
                        catch (Throwable ex) {
                            throw new BeanDefinitionStoreException(
                                    "Failed to read candidate component class: " + resource, ex);
                        }
                    }
                    else {
                        if (traceEnabled) {
                            logger.trace("Ignored because not readable: " + resource);
                        }
                    }
                }
            }
            catch (IOException ex) {
                throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
            }
            return candidates;
        }

    (3)第三步就是创建reader之后loadBeanDefinitions加载BeanDefinition信息,调用org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitions 遍历配置文件

        /**
         * Read {@code configurationModel}, registering bean definitions
         * with the registry based on its contents.
         */
        public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
            TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
            for (ConfigurationClass configClass : configurationModel) {
                loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
            }
        }
    
        /**
         * Read a particular {@link ConfigurationClass}, registering bean definitions
         * for the class itself and all of its {@link Bean} methods.
         */
        private void loadBeanDefinitionsForConfigurationClass(
                ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
    
            if (trackedConditionEvaluator.shouldSkip(configClass)) {
                String beanName = configClass.getBeanName();
                if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
                    this.registry.removeBeanDefinition(beanName);
                }
                this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
                return;
            }
    
            if (configClass.isImported()) {
                registerBeanDefinitionForImportedConfigurationClass(configClass);
            }
            for (BeanMethod beanMethod : configClass.getBeanMethods()) {
                loadBeanDefinitionsForBeanMethod(beanMethod);
            }
    
            loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
            loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
        }

     3.5 接下来调用初始化国际资源、事件等

    3.6》调用 finishBeanFactoryInitialization(beanFactory); 创建非lazy的对象。org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization源码如下:

        protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
            // Initialize conversion service for this context.
            if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
                    beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
                beanFactory.setConversionService(
                        beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
            }
    
            // Register a default embedded value resolver if no bean post-processor
            // (such as a PropertyPlaceholderConfigurer bean) registered any before:
            // at this point, primarily for resolution in annotation attribute values.
            if (!beanFactory.hasEmbeddedValueResolver()) {
                beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
            }
    
            // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
            String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
            for (String weaverAwareName : weaverAwareNames) {
                getBean(weaverAwareName);
            }
    
            // Stop using the temporary ClassLoader for type matching.
            beanFactory.setTempClassLoader(null);
    
            // Allow for caching all bean definition metadata, not expecting further changes.
            beanFactory.freezeConfiguration();
    
            // Instantiate all remaining (non-lazy-init) singletons.
            beanFactory.preInstantiateSingletons();
        }

    3.6.1》 最后调用在org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons 方法上(IoC容器中对象的创建),逻辑如下:

        public void preInstantiateSingletons() throws BeansException {
            if (logger.isTraceEnabled()) {
                logger.trace("Pre-instantiating singletons in " + this);
            }
    
            // Iterate over a copy to allow for init methods which in turn register new bean definitions.
            // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
            List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    
            // Trigger initialization of all non-lazy singleton beans...
            for (String beanName : beanNames) {
                RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
                // 不是抽象类,是单例且不lazy才进行下面操作
                if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                    // 如果是FactoryBean
                    if (isFactoryBean(beanName)) {
                        // & + beanName  组成的名称 生成FactoryBean对象
                        Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                        if (bean instanceof FactoryBean) {
                            FactoryBean<?> factory = (FactoryBean<?>) bean;
                            boolean isEagerInit;
                            if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                                isEagerInit = AccessController.doPrivileged(
                                        (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
                                        getAccessControlContext());
                            }
                            else {
                                isEagerInit = (factory instanceof SmartFactoryBean &&
                                        ((SmartFactoryBean<?>) factory).isEagerInit());
                            }
                            // 是SmartFactoryBean且isEagerInit为true生成factory对象自身的时候生成bean
                            if (isEagerInit) {
                                getBean(beanName);
                            }
                        }
                    }
                    else {
                        getBean(beanName);
                    }
                }
            }
    
            // Trigger post-initialization callback for all applicable beans...
            for (String beanName : beanNames) {
                Object singletonInstance = getSingleton(beanName);
                if (singletonInstance instanceof SmartInitializingSingleton) {
                    SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
                    if (System.getSecurityManager() != null) {
                        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                            smartSingleton.afterSingletonsInstantiated();
                            return null;
                        }, getAccessControlContext());
                    }
                    else {
                        smartSingleton.afterSingletonsInstantiated();
                    }
                }
            }
        }

     3.6.2 》 上面代码在调用 getBean(beanName) 时候会生成对象:org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String) 源码如下:

        @Override
        public Object getBean(String name) throws BeansException {
            return doGetBean(name, null, null, false);
        }
    
        /**
         * Return an instance, which may be shared or independent, of the specified bean.
         * @param name the name of the bean to retrieve
         * @param requiredType the required type of the bean to retrieve
         * @param args arguments to use when creating a bean instance using explicit arguments
         * (only applied when creating a new instance as opposed to retrieving an existing one)
         * @param typeCheckOnly whether the instance is obtained for a type check,
         * not for actual use
         * @return an instance of the bean
         * @throws BeansException if the bean could not be created
         */
        @SuppressWarnings("unchecked")
        protected <T> T doGetBean(
                String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
                throws BeansException {
    
            String beanName = transformedBeanName(name);
            Object bean;
    
            // Eagerly check singleton cache for manually registered singletons.
            Object sharedInstance = getSingleton(beanName);
            if (sharedInstance != null && args == null) {
                if (logger.isTraceEnabled()) {
                    if (isSingletonCurrentlyInCreation(beanName)) {
                        logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                                "' that is not fully initialized yet - a consequence of a circular reference");
                    }
                    else {
                        logger.trace("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 (parentBeanFactory instanceof AbstractBeanFactory) {
                        return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                                nameToLookup, requiredType, args, typeCheckOnly);
                    }
                    else if (args != null) {
                        // Delegation to parent with explicit args.
                        return (T) parentBeanFactory.getBean(nameToLookup, args);
                    }
                    else if (requiredType != null) {
                        // No args -> delegate to standard getBean method.
                        return parentBeanFactory.getBean(nameToLookup, requiredType);
                    }
                    else {
                        return (T) parentBeanFactory.getBean(nameToLookup);
                    }
                }
    
                if (!typeCheckOnly) {
                    markBeanAsCreated(beanName);
                }
    
                try {
                    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 dep : dependsOn) {
                            if (isDependent(beanName, dep)) {
                                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                            }
                            registerDependentBean(dep, beanName);
                            try {
                                getBean(dep);
                            }
                            catch (NoSuchBeanDefinitionException ex) {
                                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                            }
                        }
                    }
    
                    // Create bean instance.
                    if (mbd.isSingleton()) {
                        sharedInstance = getSingleton(beanName, () -> {
                            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);
                        }
                        // create bean
                        bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                    }
    
                    else {
                        String scopeName = mbd.getScope();
                        if (!StringUtils.hasLength(scopeName)) {
                            throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
                        }
                        Scope scope = this.scopes.get(scopeName);
                        if (scope == null) {
                            throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                        }
                        try {
                            Object scopedInstance = scope.get(beanName, () -> {
                                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 && !requiredType.isInstance(bean)) {
                try {
                    T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                    if (convertedBean == null) {
                        throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                    }
                    return convertedBean;
                }
                catch (TypeMismatchException ex) {
                    if (logger.isTraceEnabled()) {
                        logger.trace("Failed to convert bean '" + name + "' to required type '" +
                                ClassUtils.getQualifiedName(requiredType) + "'", ex);
                    }
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
            }
            return (T) bean;
        }

    解释上面逻辑:

    (1)  处理beanName, 根据是否是& 工厂名称处理

    (2) getSingleton从缓存中获取对象。org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)

        protected Object getSingleton(String beanName, boolean allowEarlyReference) {
            // Quick check for existing instance without full singleton lock
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    synchronized (this.singletonObjects) {
                        // Consistent creation of early reference within full singleton lock
                        singletonObject = this.singletonObjects.get(beanName);
                        if (singletonObject == null) {
                            singletonObject = this.earlySingletonObjects.get(beanName);
                            if (singletonObject == null) {
                                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                                if (singletonFactory != null) {
                                    singletonObject = singletonFactory.getObject();
                                    this.earlySingletonObjects.put(beanName, singletonObject);
                                    this.singletonFactories.remove(beanName);
                                }
                            }
                        }
                    }
                }
            }
            return singletonObject;
        }

    (3) 根据单例模式和多里模式进行判断之后创建对象,单例模式创建对象的逻辑如下:

                    // Create bean instance.
                    if (mbd.isSingleton()) {
                        sharedInstance = getSingleton(beanName, () -> {
                            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);
                    }

    创建对象是父类的方法:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])。  创建对象的流程也比较繁琐。从最后一个initializeBean 方法可以看到调用其前置后置处理器。

        /**
         * Central method of this class: creates a bean instance,
         * populates the bean instance, applies post-processors, etc.
         * @see #doCreateBean
         */
        @Override
        protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                throws BeanCreationException {
    
            if (logger.isTraceEnabled()) {
                logger.trace("Creating instance of bean '" + beanName + "'");
            }
            RootBeanDefinition mbdToUse = mbd;
    
            // Make sure bean class is actually resolved at this point, and
            // clone the bean definition in case of a dynamically resolved Class
            // which cannot be stored in the shared merged bean definition.
            Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
            if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
                mbdToUse = new RootBeanDefinition(mbd);
                mbdToUse.setBeanClass(resolvedClass);
            }
    
            // Prepare method overrides.
            try {
                mbdToUse.prepareMethodOverrides();
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                        beanName, "Validation of method overrides failed", ex);
            }
    
            try {
                // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
                Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
                if (bean != null) {
                    return bean;
                }
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                        "BeanPostProcessor before instantiation of bean failed", ex);
            }
    
            try {
                Object beanInstance = doCreateBean(beanName, mbdToUse, args);
                if (logger.isTraceEnabled()) {
                    logger.trace("Finished creating instance of bean '" + beanName + "'");
                }
                return beanInstance;
            }
            catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
                // A previously detected exception with proper bean creation context already,
                // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
                throw ex;
            }
            catch (Throwable ex) {
                throw new BeanCreationException(
                        mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
            }
        }
    
        /**
         * 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.
         * @param beanName the name of the bean
         * @param mbd the merged bean definition for the bean
         * @param args explicit arguments to use for constructor or factory method invocation
         * @return a new instance of the bean
         * @throws BeanCreationException if the bean could not be created
         * @see #instantiateBean
         * @see #instantiateUsingFactoryMethod
         * @see #autowireConstructor
         */
        protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                throws BeanCreationException {
    
            // Instantiate the bean.
            BeanWrapper instanceWrapper = null;
            if (mbd.isSingleton()) {
                instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
            }
            if (instanceWrapper == null) {
                instanceWrapper = createBeanInstance(beanName, mbd, args);
            }
            Object bean = instanceWrapper.getWrappedInstance();
            Class<?> beanType = instanceWrapper.getWrappedClass();
            if (beanType != NullBean.class) {
                mbd.resolvedTargetType = beanType;
            }
    
            // Allow post-processors to modify the merged bean definition.
            synchronized (mbd.postProcessingLock) {
                if (!mbd.postProcessed) {
                    try {
                        applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                    }
                    catch (Throwable ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Post-processing of merged bean definition failed", ex);
                    }
                    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.isTraceEnabled()) {
                    logger.trace("Eagerly caching bean '" + beanName +
                            "' to allow for resolving potential circular references");
                }
                addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
            }
    
            // Initialize the bean instance.
            Object exposedObject = bean;
            try {
                populateBean(beanName, mbd, instanceWrapper);
                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<>(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 " +
                                    "'getBeanNamesForType' 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;
        }
    
        protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                    invokeAwareMethods(beanName, bean);
                    return null;
                }, getAccessControlContext());
            }
            else {
                invokeAwareMethods(beanName, bean);
            }
    
            Object wrappedBean = bean;
            if (mbd == null || !mbd.isSynthetic()) {
                wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
            }
    
            try {
                invokeInitMethods(beanName, wrappedBean, mbd);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(
                        (mbd != null ? mbd.getResourceDescription() : null),
                        beanName, "Invocation of init method failed", ex);
            }
            if (mbd == null || !mbd.isSynthetic()) {
                wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
            }
    
            return wrappedBean;
        }

    doCreateBean 方法的 addSingletonFactory 方法会将对象工厂和对象加入缓存。

    加下来就是研究依赖注入,@Autowired 的自注入机制。

    补充: BeanFactoryPostProcessor 可以对bean的定义(配置元数据)进行处理, 他是在注册数据之后实例化数据之前被调用的,因此可以用于修改BeanDefinition的信息, 如果有多个,可以通过Order定义其顺序。例如:

    package qz;
    
    import jdk.nashorn.internal.runtime.logging.Logger;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanDefinition;
    import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
    import org.springframework.stereotype.Component;
    
    import java.util.Arrays;
    
    /**
     * @author: 乔利强
     * @date: 2021/2/9 21:49
     * @description:
     */
    @Component
    public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
            System.out.println("beanDefinitionNames:" + Arrays.toString(beanDefinitionNames));
    
            // 可以获取到BeanDefinition 做一些处理
            BeanDefinition userService = beanFactory.getBeanDefinition("userService");
            String scope = userService.getScope();
            System.out.println(scope);
        }
    }

    另外创建一个Service注入IoC:

    package qz;
    
    import org.springframework.stereotype.Component;
    
    import javax.annotation.PostConstruct;
    
    @Component
    //@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
    //@Lazy
    public class UserService {
    
        public UserService() {
            System.out.println("=============UserService=====");
        }
    
        public String method1() {
            System.out.println("method1");
            return "method1";
        }
    
        @PostConstruct
        public void post() {
            System.out.println("post=============");
        }
    }

    结果:(可以看出是在实例化之前,注入之后调用的)

    beanDefinitionNames:[org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.event.internalEventListenerProcessor, org.springframework.context.event.internalEventListenerFactory, mainApp, myBeanFactoryPostProcessor, userService]
    singleton
    =============UserService=====
    post=============

    补充:还有一个是 BeanFactoryPostProcessor 的子接口 BeanDefinitionRegistryPostProcessor,这个会在 BeanFactoryPostProcessor 之前被调用,用于动态的注入beanDefition信息,参考org.springframework.context.annotation.ConfigurationClassPostProcessor,测试如下:

    package qz;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
    import org.springframework.stereotype.Component;
    
    /**
     * @author: 乔利强
     * @date: 2021/2/10 10:29
     * @description:
     */
    @Component
    public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    
        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
            System.out.println("MyBeanDefinitionRegistryPostProcessor postProcessBeanDefinitionRegistry");
        }
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            System.out.println("MyBeanDefinitionRegistryPostProcessor postProcessBeanFactory");
        }
    }

    结果:

    MyBeanDefinitionRegistryPostProcessor postProcessBeanDefinitionRegistry
    MyBeanDefinitionRegistryPostProcessor postProcessBeanFactory
    beanDefinitionNames:[org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.event.internalEventListenerProcessor, org.springframework.context.event.internalEventListenerFactory, mainApp, myBeanDefinitionRegistryPostProcessor, myBeanFactoryPostProcessor, userService]
    singleton
    =============UserService=====
    post=============

     补充:根据包名获取所有的类资源:AnnotationConfigApplicationContext 本身实现了ResourceLoader接口

            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
            Resource[] resource = applicationContext.getResources("classpath*:qz/**/*.class");
            System.out.println(Arrays.toString(resource));

    补充: ListableBeanFactory 接口继承自BeanFactory 接口,扩展了许多有用的方法,

    根据类型获取beanname
    org.springframework.beans.factory.ListableBeanFactory#getBeanNamesForType(org.springframework.core.ResolvableType)
    根据类型获取beanName和bean
    org.springframework.beans.factory.ListableBeanFactory#getBeansOfType(java.lang.Class<T>)
    根据注解获取beanNames
    org.springframework.beans.factory.ListableBeanFactory#getBeanNamesForAnnotation
    根据注解获取beanNames和bean
    org.springframework.beans.factory.ListableBeanFactory#getBeansWithAnnotation

     并且在 DefaultListableBeanFactory 类中都给出了默认实现。比如:

            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(App.class);
            // 根据类型获取其beanNames
            String[] beanNamesForType = applicationContext.getBeanNamesForType(UserDao.class);
            System.out.println(Arrays.toString(beanNamesForType));
            // 根据类型获取其beanNames和bean
            Map<String, UserDao> beansOfType = applicationContext.getBeansOfType(UserDao.class);
            System.out.println(beansOfType);
            // 获取带有某个注解的beanName和bean
            Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(Anno1.class);
            System.out.println(beansWithAnnotation);

    补充:IoC refresh 方法最后还有一个方法:这个方法主要调用:org.springframework.context.Lifecycle 接口在spring容器加载和初始化完毕执行一些操作, 其执行过程如下:

                    // Last step: publish corresponding event.
                    finishRefresh();

    调用org.springframework.context.support.AbstractApplicationContext#finishRefresh

    调用org.springframework.context.support.DefaultLifecycleProcessor#onRefresh

    调用org.springframework.context.support.DefaultLifecycleProcessor#startBeans

    调用org.springframework.context.support.DefaultLifecycleProcessor.LifecycleGroup#start

    调用org.springframework.context.support.DefaultLifecycleProcessor#doStart

    比如:

    package cn.qz.user;
    
    import org.springframework.context.SmartLifecycle;
    import org.springframework.stereotype.Component;
    
    @Component
    public class MyLifecyle implements SmartLifecycle {
    
        private Boolean isRunning = false;
    
        @Override
        public boolean isAutoStartup() {
            return true;
        }
    
        @Override
        public void stop(Runnable callback) {
            callback.run();
        }
    
        @Override
        public void start() {
            System.out.println("SmartLifecycleImpl is starting ....");
            isRunning = true;
        }
    
        @Override
        public void stop() {
            System.out.println("SmartLifecycleImpl is stopped.");
        }
        /**
         * 执行start()方法前会用它来判断是否执行,返回为true时,start()方法不执行
         */
        @Override
        public boolean isRunning() {
            return isRunning;
        }
    
        @Override
        public int getPhase() {
            return 0;
        }
    
    }
    【当你用心写完每一篇博客之后,你会发现它比你用代码实现功能更有成就感!】
  • 相关阅读:
    TFS的安装
    反射发出动态类型介绍(上)
    搭建基于SSI(struts2,spring,ibatis)的javaEE开发环境
    国内各大互联网公司相关技术站点2.0版
    第三部分 静态链接(一)
    谁删除了某个表
    迷你MVVM框架 avalonjs 0.85发布
    POJ 2367 Genealogical tree
    修改进程占用内存SetProcessWorkingSetSize函数(多篇相关文章值得学习)
    使用TWebBrowser时存在内存泄漏问题的解决方案(使用SetProcessWorkingSetSize函数,或者修改OleCtrls.pas源码解决问题)
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/14392323.html
Copyright © 2020-2023  润新知