SpringIOC

作者: spilledyear | 来源:发表于2018-08-04 01:00 被阅读45次

    SpringIOC 博客链接

    概述

    IOC,全称"Inverse Of Control",中文意思为:控制反转。那么,这是啥意思?控制什么权限?反转给谁?第一个问题,创建对象的权限;第二个问题,反转给IOC容器。简单来讲,就是将创建对象的权限交给IOC容器,并且,在IOC中的这些对象,有一个统一的名称,叫做Bean。然后,还有个DI,全程"Dependence Injection",中文意思为依赖注入。那依赖注入又是什么?当一个Bean实例引用到了另外一个Bean实例的时候,IOC容器帮助我们创建依赖Bean实例并注入到需要依赖Bean的那个Bean中。两者结合,IOC容器就可以为我们创建各种各样的Bean了,简单来讲,我们平时所说的IOC,就是指具备了IOC和DI功能的IOC容器,有了这个IOC容器,就可以帮我们创建管理各种对象,然后我们只要拿过来用就可以了。

    那怎么用呢?我觉得造框架就像造飞机,飞机造好之后,并不是马上拉个人过来就能飞,还得培训一段时间,之后,这个人叫飞行员;框架造好之后,也不是随便塞给一个人就能用,还得培训一段时间,之后,这个人叫程序员。每一种类型的飞机操作起来可能不太一样,飞行员需要了解和学习;每一个框架都有自己的一套规则,程序员使用之前也需要相应的学习。不同的地方大概就是能造框架的程序员还算比较多,能造飞机的飞行员?Spring是一架飞机吗?我觉得把它称为一个机群更合适啊。这个机群由很多战斗机组成,但是有几架是核心的,离开它们这个机群就废了,比如spring-core、spring-bean,IOC容器就在这个核心模块里面。唧唧歪歪这么多,就是想告诉你,看这个之前先学一下IOC怎么用,至于具体怎么用,我不会,自己学啊。

    前面已经说了IOC是干嘛的,那么它是怎么实现的?它为我们创建Bean的具体流程是什么?抛开框架来讲,如果我们要实现这么一个功能,会怎么做?大概就是先读取配置文件,然后解析配置文件,然后根据解析结果创建对象吧?其实也就是这样的,不过Spring这个框架除了它本省提供的功能之外,更可贵的是它的设计,而设计这种东西,并不是你dbug一下就能理解的,也许要你要阅读源码很多遍才能体会,也许有一天你突然就明白了。反正我现在的主要目的也是弄清楚它的工作流程,至于设计这种东西,这个不能强求,慢慢体会吧。

    如果对Bean生命周期稍有了解的同学都会知道,Bean实例化的时机其实是和你所使用的工厂类有关系的。如果你使用的是DefaultListableBeanFactory,那么它的实例化时机是在第一次使用该Bean的时候。第一次使用它的时候事什么意思?比如这样:factory.getBean("simpleMethodInterceptor"),就是第一次要用到它的时候就会实例化;如果你使用的是ApplicationContext,有关于Bean实例化的时机是要分情况的:

    • 如果bean的scope是singleton的,并且lazy-init为false(默认是false,所以可以不用设置),则ApplicationContext启动的时候就实例化该Bean,并且将实例化的Bean放在一个map结构的缓存中,下次再使用该Bean的时候,直接从这个缓存中取
    • 如果bean的scope是singleton的,并且lazy-init为true,则是在第一次使用该Bean的时候进行实例化
    • 如果bean的scope是prototype的,则是在第一次使用该Bean的时候进行实例化

    可以看出,使用ApplicationContext的情况内部流程会复杂一些,但是对我们使用者而言,肯定是使用ApplicationContext更方便。接下来两种情况我都会介绍,其实很多东西都是一样,比如bean解析这一块,肯定是一样的,但我们的目的是研究其内部流程,所以先从简单的开始,简单的理解之后,复杂的理解起来也更容易了。

    这里再强调一下,本文的主要目的是分析其内部流程,如果想完完全全的弄懂其源码,还是挺困难的:一方面,你需要对Spring中的各种各样的配置非常熟悉,这样才能很快猜测出代码是什么意思;另一方面,你需要有足够多的时间和耐心去研究。源码值得读,但也不至于这样每行都揪着不放,而且代码这种东西,看第一遍和看第二遍感觉是完全不一样的。刚看一个框架的源码的时候,不要一下子就想着把它每行代码都弄得清清楚楚,了解整个框架的脉络比这更有意义,对感兴趣的地方,再去细读。

    Bean生命周期

    为什么这里会先介绍Bean的生命周期?因为Bean生命周期是IOC中非常核心的内容,这里也体现了Spring这个框架的设计能力,它为我们预留了很多的接口,让我们在bean实例化前后、初始化前后可以写入一些自己的逻辑,有些情况下,这是非常重要的。

    那么什么是bean的生命周期呢?即在我们将xml配置文件中的一个个<bean>标签解析成一个个BeanDefinition之后,我们需要根据BeanDefinition进行bean的实例化(BeanDefinition也是一个非常重要的概念,它是用来做什么的?可以这样理解:xml配置文件中的一个个标签,我们可以认为它是一种描述信息,即它描述了一个bean应该是什么样子,这个注解的效果基本是类似,然后在Spring对xml配置文件进行解析的时候,会将里面的一个个标签解析成一个个BeanDefinition对象,然后在Spring创建bean实例的时候,就直接根据BeanDefinition就可以很方便的创建bean实例的,可以认为BeanDefinition是对xml标签的一种抽象),bean的实例化的简单来讲就是new对象,但是在new对象的前后、初始化对象的前后,Spring为我们预留了非常多的接口,让我们而可以插入自己的逻辑,而整个流程下来,就可以称为bean的生命周期。

    1.根据BeanDefinition信息,实例化对象

    2.根据BeanDefinition信息,配置Bean的所有属性

    3.如果Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName,参数为Bean的id

    4.如果Bean实现BeanFactoryAware或者ApplicationContextAware接口,设置工厂setBeanFactory 或者上下文对象 setApplicationContext

    5.如果存在类实现了BeanPostProcessor接口,执行这些实现类的postProcessBeforeInitialization方法,这相当于在Bean初始化之前插入逻辑

    6.如果Bean实现InitializingBean接口, 执行afterPropertiesSet方法

    7.如果Bean指定了init-method方法,就会调用该方法。例:<bean init-method="init">

    8.如果存在类实现了BeanPostProcessor接口,执行这些实现类的postProcessAfterInitialization方法,这相当于在Bean初始化之后插入逻辑

    9.这个阶段Bean已经可以使用了,scope为singleton的Bean会被缓存在IOC容器中

    10.如果Bean实现了DisposableBean接口, 执行destroy方法。

    11.如果配置了destory-method方法,就调用该方法。例:<bean destroy-method="customerDestroy">

    这里将Bean生命周期这块内容放到最前面,是为了提前让大家对这块内容有个印象。

    BeanFactory流程

    前面我们说到,主要流程包括 状态配置文件、解析配置文件、创建Bean,那我们现在就按照这个流程来分析吧。在网上看了一些IOC源码解析的文档,大部会从这行代码开始

    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
    

    这就是我们上面说到的使用ApplicationContext方式,这是我们第二大章节要介绍的。ApplicationContext在Spring中是一个非常高级的接口了,它继承了很多接口,有非常多的方法,所以我们在使用的是时候,这么一行代码就帮我们创建好了IOC容器。使用的时候肯定很舒服了,但是一上来就用来做源码分析,不太好,里面的功能太多了,看着就怕。

    我们就按前面说到的那三个流程来解析,因为Spring中本来也就是这样做的呀,ApplicationContext只不过是为了方便我们使用而封装出的一个更高级的接口。我们先把这三个流程弄清楚,之后再来分析ApplicationContext,这样就很舒服了。

    有关于本大章节的测试代码如下:

    public class TestBeanFactory {
        public static void main(String[] args) {
            // 资源加载器
            ResourceLoader resLoaderr = new DefaultResourceLoader();
            // 获取资源
            Resource resource = resLoaderr.getResource("config.xml");
    
            // 工程实现类
            DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
            // XML解析器,将解析后的BeanDefinition 放到 factory 的Map中缓存起来
            BeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(factory);
            // 解析XML入口
            beanDefinitionReader.loadBeanDefinitions(resource);
            
            // 获取Bean实例。实际上,Bean在上面的流程中并没有实例话,只有在首次使用它的时候才会实例化
            Object o = factory.getBean("simpleMethodInterceptor");
            System.out.println(o);
    
        }
    }
    

    加载配置文件

    加载配置文件大家首先会想到什么?应该是IO流吧。Spring肯定会做封装,先不要关心这些,以下代码就会为我们加载配置文件到Resource中

    // 资源加载器
    ResourceLoader resLoaderr = new DefaultResourceLoader();
    // 获取资源
    Resource resource = resLoaderr.getResource("config.xml");
    

    有关于这两行代码,没有什么特别的东西,可以看一下getResource方法

    private final Set<ProtocolResolver> protocolResolvers = new LinkedHashSet<ProtocolResolver>(4);
    
    public Resource getResource(String location) {
        Assert.notNull(location, "Location must not be null");
    
        for (ProtocolResolver protocolResolver : this.protocolResolvers) {
            Resource resource = protocolResolver.resolve(location, this);
            if (resource != null) {
                return resource;
            }
        }
    
        // 判断是不是 "/" 开头, 例如 /aa/bb/bean.xml
        if (location.startsWith("/")) {
            return getResourceByPath(location);
        }
    
        // 判断是不是 "classpath:" 开头, 例如 classpath:aplication.xml
        else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
            return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
        }
    
        else {
            try {
                // 尝试通过URL的方式解析这个路径,在我们这个例子会抛出异常
                URL url = new URL(location);
                return new UrlResource(url);
            }
            catch (MalformedURLException ex) {
                // 在我们这个Demo中,实际会走这里
                // No URL -> resolve as resource path.
                return getResourceByPath(location);
            }
        }
    }
    

    ProtocolResolver是一个资源解析器接口,我们可以通过实现ProtocolResolver接口来自定义资源解析

    public interface ProtocolResolver {
        /**
         * Resolve the given location against the given resource loader
         * if this implementation's protocol matches.
         */
        Resource resolve(String location, ResourceLoader resourceLoader);
    
    }
    

    看一下 getResourceByPath 方法

    protected Resource getResourceByPath(String path) {
        return new ClassPathContextResource(path, getClassLoader());
    }
    
    
    protected static class ClassPathContextResource extends ClassPathResource implements ContextResource {
    
        public ClassPathContextResource(String path, ClassLoader classLoader) {
            super(path, classLoader);
        }
    }
    
    
    
    // ClassPathResource 构造方法
    public ClassPathResource(String path, ClassLoader classLoader) {
        Assert.notNull(path, "Path must not be null");
        // 将 window下的 路径符 "\\" 换成 "/"
        String pathToUse = StringUtils.cleanPath(path);
        if (pathToUse.startsWith("/")) {
            pathToUse = pathToUse.substring(1);
        }
        this.path = pathToUse;
        this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
    }
    

    解析配置文件

    有关于这一阶段的时序图

    post_002
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    // BeanDefinitionReader 就是XML解析器
    BeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(factory);
    beanDefinitionReader.loadBeanDefinitions(resource);
    

    解析配置我们这里使用了XmlBeanDefinitionReader,有关于XmlBeanDefinitionReader,创建它的时候需要指定一个BeanDefinitionRegistry对象。但是这里为什么传一个DefaultListableBeanFactory对象进去,可以看看他们的继承关系图。

    post_003

    DefaultListableBeanFactory实现了非常多的接口,其中就包括BeanFactory和 XmlBeanDefinitionReader。

    解析配置文件的入口,就在loadBeanDefinitions方法中,接收刚刚创建的Resource对象

    private final ThreadLocal<Set<EncodedResource>> resourcesCurrentlyBeingLoaded =
                new NamedThreadLocal<Set<EncodedResource>>("XML bean definition resources currently being loaded");
    
    
    public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
        // 转换成 EncodedResource
        return loadBeanDefinitions(new EncodedResource(resource));
    }
    
    public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
        Assert.notNull(encodedResource, "EncodedResource must not be null");
        if (logger.isInfoEnabled()) {
            logger.info("Loading XML bean definitions from " + encodedResource.getResource());
        }
    
        // 相当于是个缓存
        Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
        if (currentResources == null) {
            currentResources = new HashSet<EncodedResource>(4);
            this.resourcesCurrentlyBeingLoaded.set(currentResources);
        }
        if (!currentResources.add(encodedResource)) {
            throw new BeanDefinitionStoreException(
                    "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
        }
    
        try {
            // 获取到资源文件输入流
            InputStream inputStream = encodedResource.getResource().getInputStream();
            try {
                InputSource inputSource = new InputSource(inputStream);
                if (encodedResource.getEncoding() != null) {
                    inputSource.setEncoding(encodedResource.getEncoding());
                }
    
                // 开始执行真正的解析操作
                return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
            }
            finally {
                inputStream.close();
            }
        }
        catch (IOException ex) {
            throw new BeanDefinitionStoreException(
                    "IOException parsing XML document from " + encodedResource.getResource(), ex);
        }
        finally {
            currentResources.remove(encodedResource);
            if (currentResources.isEmpty()) {
                this.resourcesCurrentlyBeingLoaded.remove();
            }
        }
    }
    

    EncodedResource是用来设置编码的,即设置以什么样的编码格式读取文件,这里默认为null

    public EncodedResource(Resource resource) {
        this(resource, null, null);
    }
    
    private EncodedResource(Resource resource, String encoding, Charset charset) {
        super();
        Assert.notNull(resource, "Resource must not be null");
        this.resource = resource;
        this.encoding = encoding;
        this.charset = charset;
    }
    

    从上面的代码中我们可以发现,真正的解析逻辑在doLoadBeanDefinitions方法中。你多阅读一些代码就会发现,在Spring中,干实事的方法都是以 do 开始的。接下来分析一下doLoadBeanDefinitions方法

    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
            throws BeanDefinitionStoreException {
        try {
            // 获取xml dom树
            Document doc = doLoadDocument(inputSource, resource);
    
            // 根据dom树 注册 BeanDefinition
            return registerBeanDefinitions(doc, resource);
        }
        catch (BeanDefinitionStoreException ex) {
            throw ex;
        }
        catch (SAXParseException ex) {
            throw new XmlBeanDefinitionStoreException(resource.getDescription(),
                    "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
        }
        catch (SAXException ex) {
            throw new XmlBeanDefinitionStoreException(resource.getDescription(),
                    "XML document from " + resource + " is invalid", ex);
        }
        catch (ParserConfigurationException ex) {
            throw new BeanDefinitionStoreException(resource.getDescription(),
                    "Parser configuration exception parsing XML from " + resource, ex);
        }
        catch (IOException ex) {
            throw new BeanDefinitionStoreException(resource.getDescription(),
                    "IOException parsing XML document from " + resource, ex);
        }
        catch (Throwable ex) {
            throw new BeanDefinitionStoreException(resource.getDescription(),
                    "Unexpected exception parsing XML document from " + resource, ex);
        }
    }
    

    其实主要就两行代码,首先就是获取xml文件 dom 树,就是将xml 文件解析成一个Document对象

    public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
            ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
    
        DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
        if (logger.isDebugEnabled()) {
            logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
        }
        DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
        return builder.parse(inputSource);
    }
    

    这个解析dom没什么好说的,主要看看registerBeanDefinitions方法

    public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
        // 用于从 xml document 对象中 获取 BeanDefinition
        BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
        int countBefore = getRegistry().getBeanDefinitionCount();
        documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
        return getRegistry().getBeanDefinitionCount() - countBefore;
    }
    

    这里引出了一个新对象BeanDefinitionDocumentReader,它的主要功能就是从 document 对象中获取bean,简单来说,就是找到document dom树中的bean对象。那个方法还是有点不一样的

    BeanUtils.instantiateClass方法通过无参构造函数创建一个对象,Class.cast 方法用于将一个对象装换为类或者接口,法只能转换当前类型或其子类下的对象,只是简单进行强转。但我不知道这里为啥要这样写啊!

    protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
        return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
    }
    

    getRegistry()方法就是返回我们一开始传进去的DefaultListableBeanFactory。这行代码就是返回DefaultListableBeanFactory中beanDefinitionMap中的元素个数,beanDefinitionMap是啥?它缓存当前容器内的BeanDefinition,BeanDefinition是Bean的描述,Spring会先将 xml document 中的节点解析成一个个BeanDefinition,然后在后续阶段将BeanDefinition生成 真正的Bean。也就是说,这里是返回“此刻当前容器中的BeanDefinition个数”。

    int countBefore = getRegistry().getBeanDefinitionCount();
    

    这条return语句,代表返回本次创建的 BeanDefinition 个数

    return getRegistry().getBeanDefinitionCount() - countBefore;
    

    所以,主要的逻辑代码,在registerBeanDefinitions方法中

    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    

    createReaderContext返回一个XmlReaderContext对象,这个对象里面主要是包括一些参数吧。

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

    有关于xml命名空间处理解析器

    public NamespaceHandlerResolver getNamespaceHandlerResolver() {
        if (this.namespaceHandlerResolver == null) {
            this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
        }
        return this.namespaceHandlerResolver;
    }
    
    protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
        return new DefaultNamespaceHandlerResolver(getResourceLoader().getClassLoader());
    }
    
    /**
        * The location to look for the mapping files. Can be present in multiple JAR files.
        */
    public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";
    
    public DefaultNamespaceHandlerResolver(ClassLoader classLoader) {
        this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION);
    }
    

    大概知道有这么些东西就可以了。接下来看看 DefaultBeanDefinitionDocumentReader 中的 registerBeanDefinitions 方法具体实现

    public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
        this.readerContext = readerContext;
        logger.debug("Loading bean definitions");
        Element root = doc.getDocumentElement();
        doRegisterBeanDefinitions(root);
    }
    

    看到了吗?又是一个do开头的方法,说明这里是干实事的地方

    protected void doRegisterBeanDefinitions(Element root) {
        // parent是为了处理 <beans> 中嵌套 <beans> 的情况
        BeanDefinitionParserDelegate parent = this.delegate;
        this.delegate = createDelegate(getReaderContext(), root, parent);
    
        // 是否是默认 命名空间 "http://www.springframework.org/schema/beans"
        if (this.delegate.isDefaultNamespace(root)) {
            String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
            if (StringUtils.hasText(profileSpec)) {
                String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                        profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
                if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                    if (logger.isInfoEnabled()) {
                        logger.info("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;
    }
    

    这里又引出一个新对象BeanDefinitionParserDelegate,这是一个委托类,所有解析DOM的逻辑都交给这个类来处理。

    第一行代码就值得分析一下。Spring解析XML的时候,是以<beans></beans>为最外层标签进行解析的,但是<beans>可以嵌套 <beans>,这种情况下,外层<beans>对应的BeanDefinitionParserDelegate委托类就是里层<beans>中的parent,因为可以从parent中继承一些默认属性。下面举一个例子来说明:

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:jee="http://www.springframework.org/schema/jee"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:task="http://www.springframework.org/schema/task"
           xsi:schemaLocation="
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
            http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd">
    
        <bean id="BookInterceptor" class="aop.BookInterceptor" />   
    
        <beans>
            <bean id="simpleMethodInterceptor2" class="aop.SimpleMethodInterceptor" ></bean>
        </beans>
    
    </beans>
    

    解析最外层<beans>的时候,parent为null,这时候会创建一个BeanDefinitionParserDelegate委托类 delegate1,然后先解析 <bean id="BookInterceptor" ... /> ,解析完这个标签之后,又遇到一个<beans>,这时候又会调用doRegisterBeanDefinitions方法,将 delegate1 作为parent,同时创建一个 BeanDefinitionParserDelegate委托类 delegate2,这时候的一些默认属性会从delegate1中继承。
    这里相当于有个递归调用,遇到<beans>标签就调用doRegisterBeanDefinitionsf方法,同时将外层的委托类赋值给本次调用中的parent,如果没有外层,parent就为nulll

    BeanDefinitionParserDelegate parent = this.delegate;
    
    protected BeanDefinitionParserDelegate createDelegate(
            XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) {
        BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
        delegate.initDefaults(root, parentDelegate);
        return delegate;
    }
    
    public void initDefaults(Element root, BeanDefinitionParserDelegate parent) {
        // 设置一些默认属性
        populateDefaults(this.defaults, (parent != null ? parent.defaults : null), root);
        this.readerContext.fireDefaultsRegistered(this.defaults);
    }
    
    
    
    public static final String DEFAULT_LAZY_INIT_ATTRIBUTE = "default-lazy-init";
    public static final String DEFAULT_MERGE_ATTRIBUTE = "default-merge";
    public static final String DEFAULT_AUTOWIRE_ATTRIBUTE = "default-autowire";
    public static final String DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE = "default-dependency-check";
    public static final String DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE = "default-autowire-candidates";
    public static final String DEFAULT_INIT_METHOD_ATTRIBUTE = "default-init-method";
    public static final String DEFAULT_DESTROY_METHOD_ATTRIBUTE = "default-destroy-method";
    
    // 设置一些默认属性
    protected void populateDefaults(DocumentDefaultsDefinition defaults, DocumentDefaultsDefinition parentDefaults, Element root) {
        String lazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE);
        if (DEFAULT_VALUE.equals(lazyInit)) {
            // Potentially inherited from outer <beans> sections, otherwise falling back to false.
            lazyInit = (parentDefaults != null ? parentDefaults.getLazyInit() : FALSE_VALUE);
        }
        defaults.setLazyInit(lazyInit);
    
        String merge = root.getAttribute(DEFAULT_MERGE_ATTRIBUTE);
        if (DEFAULT_VALUE.equals(merge)) {
            // Potentially inherited from outer <beans> sections, otherwise falling back to false.
            merge = (parentDefaults != null ? parentDefaults.getMerge() : FALSE_VALUE);
        }
        defaults.setMerge(merge);
    
        String autowire = root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE);
        if (DEFAULT_VALUE.equals(autowire)) {
            // Potentially inherited from outer <beans> sections, otherwise falling back to 'no'.
            autowire = (parentDefaults != null ? parentDefaults.getAutowire() : AUTOWIRE_NO_VALUE);
        }
        defaults.setAutowire(autowire);
    
        // Don't fall back to parentDefaults for dependency-check as it's no longer supported in
        // <beans> as of 3.0. Therefore, no nested <beans> would ever need to fall back to it.
        defaults.setDependencyCheck(root.getAttribute(DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE));
    
        if (root.hasAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)) {
            defaults.setAutowireCandidates(root.getAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE));
        }
        else if (parentDefaults != null) {
            defaults.setAutowireCandidates(parentDefaults.getAutowireCandidates());
        }
    
        if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)) {
            defaults.setInitMethod(root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE));
        }
        else if (parentDefaults != null) {
            defaults.setInitMethod(parentDefaults.getInitMethod());
        }
    
        if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)) {
            defaults.setDestroyMethod(root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE));
        }
        else if (parentDefaults != null) {
            defaults.setDestroyMethod(parentDefaults.getDestroyMethod());
        }
    
        defaults.setSource(this.readerContext.extractSource(root));
    }
    

    preProcessXml 和 postProcessXml 这两个方法是空的,用户可以通过继承来添加自己的逻辑。主要是parseBeanDefinitions方法,这里面主要就是遍历DOM中的所有Element节点,即标签。如果是默认命名空间下的标签,就调用parseDefaultElement方法,如果不是默认命名空间下的标签,就调用委托类的parseCustomElement方法。其实这里主要即使委托类来实现那了,parseDefaultElement方法里面的主要逻辑也是调用了委托类的方法

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

    root 就相当于是的<beans>标签,经常会看到判断是否是命名空间,这里的命名空间指的是 "http://www.springframework.org/schema/beans",bean 和 beans 标签都属于默认命名空间。

    有关于 org.w3c.dom.Document 下的 Node,Node是一个顶层接口,它下面有几个子接口。在DOM树中,所有东西都可以叫Node,标签也是一种Node,但它实际上上叫Element。举个例子说明:

    <book price="100">
        <chineseBook>哈利波特.哈哈哈<chineseBook>
    </beans>
    

    在以上的代码片段中,price 是属性节点;哈利波特.哈哈哈 是 文本节点;<book price="100">..</book> 和 <chineseBook>哈利波特.哈哈哈<chineseBook> 是Element节点。所以,不要被Node搞晕了

    这里主要以/<bean> 标签进行说明,所以主要关注parseDefaultElement方法,可以看到,当是<beans/>标签的时候,又调用了doRegisterBeanDefinitions方法

    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    
        // <import/> 标签
        if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
            importBeanDefinitionResource(ele);
        }
    
        // <alias/> 标签
        else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
            processAliasRegistration(ele);
        }
    
        // <bean/> 标签
        else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
            processBeanDefinition(ele, delegate);
        }
    
        // <beans/> 标签 
        else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
            doRegisterBeanDefinitions(ele);
        }
    }
    

    解析<bean> 标签的processBeanDefinition方法源码如下,这里主要就是委托类BeanDefinitionParserDelegate的主场了

    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        // 返回一个 BeanDefinition 持有者
        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));
        }
    }
    

    BeanDefinitionParserDelegate # parseBeanDefinitionElement

    public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
        return parseBeanDefinitionElement(ele, null);
    }
    
    public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
        // 如果没有定义name属性,就以id属性的值作为beanName;如果定义了beanName,就以name属性的值作为beanName
        String id = ele.getAttribute(ID_ATTRIBUTE);
        String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
    
        List<String> aliases = new ArrayList<String>();
        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.isDebugEnabled()) {
                logger.debug("No XML 'id' specified - using '" + beanName +
                        "' as bean name and " + aliases + " as aliases");
            }
        }
    
        // 校验 beanName的唯一性
        if (containingBean == null) {
            checkNameUniqueness(beanName, aliases, ele);
        }
    
        // 主要的解析逻辑就是在这个方法中,解析成功返回一个 AbstractBeanDefinition;解析失败返回 null
        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.isDebugEnabled()) {
                        logger.debug("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);
    
            // 通过上面生成的 beanDefinition 构造一个 BeanDefinitionHolder
            return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
        }
    
        return null;
    }
    

    创建AbstractBeanDefinition的主要逻辑又是调用了parseBeanDefinitionElement的一个重载方法,其中有很大一部分逻辑是这是BeanDefinition属性,如果想弄的清清楚楚,还是需要花一点时间的,这里就跳过吧,只要明白:这里为BeanDefinition设置这么多属性,都是因为之后生成Bean实例的时候,需要BeanDefinition中维护的信息,BeanDefinition是生成Bean实例的根本,很重要!

    public AbstractBeanDefinition parseBeanDefinitionElement(
            Element ele, String beanName, BeanDefinition containingBean) {
    
        this.parseState.push(new BeanEntry(beanName));
    
        String className = null;
        if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
            className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
        }
    
        try {
            String parent = null;
            if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
                parent = ele.getAttribute(PARENT_ATTRIBUTE);
            }
    
            // 生成一个GenericBeanDefinition并返回,同时根据className创建一个对应的Class对象设置为GenericBeanDefinition的beanClass属性。
            AbstractBeanDefinition bd = createBeanDefinition(className, parent);
    
            // 下面这些就是有关于一些属性啥的解析,如果想弄的清清楚楚,还是需要花一点时间的,这里就跳过吧,只要明白:这里为BeanDefinition设置这么多属性,都是因为之后生成Bean实例的时候,需要BeanDefinition中维护的信息,BeanDefinition是生成Bean实例的根本,很重要!
            parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
            bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
    
            parseMetaElements(ele, bd);
            parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
            parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
    
            parseConstructorArgElements(ele, bd);
            parsePropertyElements(ele, bd);
            parseQualifierElements(ele, bd);
    
            bd.setResource(this.readerContext.getResource());
            bd.setSource(extractSource(ele));
    
            return bd;
        }
        catch (ClassNotFoundException ex) {
            error("Bean class [" + className + "] not found", ele, ex);
        }
        catch (NoClassDefFoundError err) {
            error("Class that bean class [" + className + "] depends on not found", ele, err);
        }
        catch (Throwable ex) {
            error("Unexpected failure during bean definition parsing", ele, ex);
        }
        finally {
            this.parseState.pop();
        }
    
        return null;
    }
    

    生成之后就返回到DefaultBeanDefinitionDocumentReader 中的 processBeanDefinition 方法中,然后又调用BeanDefinitionParserDelegate的decorateBeanDefinitionIfRequiredf方法进行装饰BeanDefinitionHolder

    if (bdHolder != null) {
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
      ......
    }
    

    decorateBeanDefinitionIfRequired主要实现如下,具体的不太了解

    public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) {
        return decorateBeanDefinitionIfRequired(ele, definitionHolder, null);
    }
    
    public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
            Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) {
    
        BeanDefinitionHolder finalDefinition = definitionHolder;
    
        //装饰自定义属性
        // Decorate based on custom attributes first.
        NamedNodeMap attributes = ele.getAttributes();
        for (int i = 0; i < attributes.getLength(); i++) {
            Node node = attributes.item(i);
            finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
        }
    
        //装饰自定义标签
        // Decorate based on custom nested elements.
        NodeList children = ele.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            Node node = children.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
            }
        }
        return finalDefinition;
    }
    

    装饰完成之后,继续返回到 DefaultBeanDefinitionDocumentReader 的processBeanDefinition方法,然后注册最终的BeanDefinition。注意该方法的第二个参数,其实就是我们一开始传进去的DefaultListableBeanFactory对象,主要流程就是将当前生成的BeanDefinition放到DefaultListableBeanFactory的一个Map中缓存起来

    BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
    
    
    public static void registerBeanDefinition(
            BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
            throws BeanDefinitionStoreException {
    
        // 通过beanName注册 BeanDefinition
        String beanName = definitionHolder.getBeanName();
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    
        // 如果该bean有别名,为该bean注册别名
        String[] aliases = definitionHolder.getAliases();
        if (aliases != null) {
            for (String alias : aliases) {
                registry.registerAlias(beanName, alias);
            }
        }
    }
    

    可以具体看看DefaultListableBeanFactory对象中的registerBeanDefinition方法,大概就是将BeanDefinition放到beanDefinitionMap中缓存起来。

    /** Map of bean definition objects, keyed by bean name */
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
    
    
    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 {
                // 简单校验,检验啥 overridden 方法,不太清楚,没用过
                ((AbstractBeanDefinition) beanDefinition).validate();
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                        "Validation of bean definition failed", ex);
            }
        }
    
        BeanDefinition oldBeanDefinition;
    
        oldBeanDefinition = this.beanDefinitionMap.get(beanName);
        if (oldBeanDefinition != null) {
            // 检查该BeanDefinition是否在容器中已经存在,如果已经存在,bing且不允许覆盖已经注册的BeanDefinitio,则报错
            if (!isAllowBeanDefinitionOverriding()) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                        "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
                        "': There is already [" + oldBeanDefinition + "] bound.");
            }
            else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
                // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
                            "' with a framework-generated bean definition: replacing [" +
                            oldBeanDefinition + "] with [" + beanDefinition + "]");
                }
            }
            else if (!beanDefinition.equals(oldBeanDefinition)) {
                if (this.logger.isInfoEnabled()) {
                    this.logger.info("Overriding bean definition for bean '" + beanName +
                            "' with a different definition: replacing [" + oldBeanDefinition +
                            "] with [" + beanDefinition + "]");
                }
            }
            else {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Overriding bean definition for bean '" + beanName +
                            "' with an equivalent definition: replacing [" + oldBeanDefinition +
                            "] with [" + beanDefinition + "]");
                }
            }
    
            // 如果允许覆盖,根据 beanName,用新的 BeanDefinition 覆盖老的 BeanDefinition
            this.beanDefinitionMap.put(beanName, beanDefinition);
        }
    
        // 首次创建的 BeanDefinition
        else {
            // 检查此工厂的bean创建阶段是否已经开始?检查当前是不是已经开始实例化了?
            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<String>(this.beanDefinitionNames.size() + 1);
                    updatedDefinitions.addAll(this.beanDefinitionNames);
                    updatedDefinitions.add(beanName);
                    this.beanDefinitionNames = updatedDefinitions;
                    if (this.manualSingletonNames.contains(beanName)) {
                        Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
                        updatedSingletons.remove(beanName);
                        this.manualSingletonNames = updatedSingletons;
                    }
                }
            }
            else {
                // Still in startup registration phase
                this.beanDefinitionMap.put(beanName, beanDefinition);
                this.beanDefinitionNames.add(beanName);
                this.manualSingletonNames.remove(beanName);
            }
            this.frozenBeanDefinitionNames = null;
        }
    
        if (oldBeanDefinition != null || containsSingleton(beanName)) {
            // 如果有覆盖的情况,就刷新缓存
            resetBeanDefinition(beanName);
        }
    }
    

    最后,在DefaultBeanDefinitionDocumentReader对象的processBeanDefinition 方法中发出响应事件,通知相关监听器这个 Bean 已经被加载

    // 通过 fireComponentRegistered 方法进行通知监听器解析及注册完成工作,这里的实现只为扩展,当程序开发人员需要对注册BeanDefinition事件进行监听时,可以通过注册监听器的方式并将处理逻辑写入监听器中,目前 Spring 中并没有对此事件做任何处理。
    
    getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    

    至此,有关于解析XML文件的内容就算完事了,接着就是按照方法调用栈返回,最后返回一个该配置文件对应生成BeanDefinition个数。

    生成Bean实例

    有关于这一阶段的时序图,这个图画的不太好,凑合看一下吧,哭

    post_004

    在第一次使用该Bean的时候进行实例化

    // 获取Bean实例。实际上,Bean在上面的流程中并没有实例话,只有在首次使用它的时候才会实例化
    Object o = factory.getBean("simpleMethodInterceptor");
    System.out.println(o);
    

    DefaultListableBeanFactory 类继承了 AbstractAutowireCapableBeanFactory 抽象类,getBean方法就是在该抽象类中进行实例化的。追踪该方法可以发现,又是一个do开头的方法,说明里面就是具体逻辑了。这个方法还挺长,接下来我们分步解析

    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }
    
    protected <T> T doGetBean(
            final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
            throws BeansException {
    
        // 去除前缀 &;如果名称是别名,则跟进别名返回 name
        final String beanName = transformedBeanName(name);
        Object bean;
    
        // 据beanName从 Map缓存 中获取单例Bean实例
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            if (logger.isDebugEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            // 如果指定名称的Bean在容器中已有单态模式的Bean被创建,直接返回已经创建的Bean实例。当这个bean时FactoryBean的时候,需要特别处理
            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);
            }
    
            //对IoC容器中是否存在指定名称的BeanDefinition进行检查,首先检查是否  
    58      //能在当前的BeanFactory中获取的所需要的Bean,如果不能则委托当前容器  
    59      //的父级容器去查找,如果还是找不到则沿着容器的继承体系向父级容器查找 
            // Check if bean definition exists in this factory.
            BeanFactory parentBeanFactory = getParentBeanFactory();
            // 当前容器的父级容器存在,且当前容器中不存在指定名称的Bean  
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                // 解析指定Bean名称的原始名称 
                String nameToLookup = originalBeanName(name);
                if (args != null) {
                    // Delegation to parent with explicit args.
                    // 委派父级容器根据指定名称和显式的参数查找 
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else {
                    // No args -> delegate to standard getBean method.
                    // 委派父级容器根据指定名称和类型查找  
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }
            //typeCheckOnly 默认是false,表示是否需要进行类型验证
            if (!typeCheckOnly) {
                // 这里用于标记该bean已经被创建,其实就是将beanName 放到一个专门用来标记 Bean 是否创建的map中
                markBeanAsCreated(beanName);
            }
    
            try {
                // 将GernericBeanDefinition 转换成 RootBeanDefinition,因为xml解析之后是GernericBeanDefinition,而后续处理是针对RootBeanDefinition
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);
    
                // 获取当前Bean的依赖Bean,然后实例化依赖Bean,会递归调用
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dependsOnBean : dependsOn) {
                        if (isDependent(beanName, dependsOnBean)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
                        }
                        registerDependentBean(dependsOnBean, beanName);
                        getBean(dependsOnBean);
                    }
                }
    
                // Create bean instance.
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                       // 回调方法,创建Bean实例的逻辑就在这个方法中
                        @Override
                        public Object getObject() throws BeansException {
                            try {
                                //创建一个指定Bean实例对象,如果有父级继承,则合并子类和父类的定义
                                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的实例对象,如果时FactoryBean需要特殊处理
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
    
                // scorp 为 原型模式,每次请求都会创建一个
                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {
                        //回调beforePrototypeCreation方法,默认的功能是注册当前创建的原型对象  
                        beforePrototypeCreation(beanName);
                        //创建指定Bean对象实例 
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        /回调afterPrototypeCreation方法,默认的功能告诉IoC容器指定Bean的原型对象不再创建了  
                        afterPrototypeCreation(beanName);
                    }
    
                    //如果是FactoryBean,特殊处理
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }
    
                // scorp 为其它情况,例如 request session 
                else {
                    String scopeName = mbd.getScope();
                    final 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, new ObjectFactory<Object>() {
                            @Override
                            public Object getObject() throws BeansException {
                                beforePrototypeCreation(beanName);
                                try {
                                    return createBean(beanName, mbd, args);
                                }
                                finally {
                                    afterPrototypeCreation(beanName);
                                }
                            }
                        });
                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    }
                    catch (IllegalStateException ex) {
                        throw new BeanCreationException(beanName,
                                "Scope '" + scopeName + "' is not active for the current thread; consider " +
                                "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                                ex);
                    }
                }
            }
            catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }
    
        // 对创建的Bean实例对象进行类型检查 
        // Check if required type matches the type of the actual bean instance.
        if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
            try {
                return getTypeConverter().convertIfNecessary(bean, requiredType);
            }
            catch (TypeMismatchException ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Failed to convert bean '" + name + "' to required type [" +
                            ClassUtils.getQualifiedName(requiredType) + "]", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        return (T) bean;
    }
    

    以下主要是为了在必要时去除 & 前缀。我们知道,当我们通过factory.getBean(&+beanName) 方式获取一个Bean的时候,实际上获取的是beanFactory,而不是我们需要的那个bean

    final String beanName = transformedBeanName(name);
    

    尝试根据beanName从map缓存中获取bean

    Object sharedInstance = getSingleton(beanName);
    
    public Object getSingleton(String beanName) {
        return getSingleton(beanName, true);
    }
    
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }
    

    接下来就是一些判断,主要是处理当缓存中有bean的情况,创建新bean的时候,不走那些流程,所以直接到标记处。在开始创建bean实例之前,需要先标记一下,即将该beanName缓存到一个map中

    markBeanAsCreated(beanName);
    

    然后就是创建依赖bean

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

    如果Bean是单例模式,就先从 this.singletonObjects 缓存中获取,缓存中有则直接返回,否则创建。在下面的这堆代码中,最核心的就是 singletonFactory.getObject() 这个方法了,创建Bean实例的逻辑在在这个方法中调用的,然后还有Bean的生命周期,需要重点关注一下

    if (mbd.isSingleton()) {
        sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
            @Override
            public Object getObject() throws BeansException {
                try {
                    return createBean(beanName, mbd, args);
                }
                catch (BeansException ex) {
                    // Explicitly remove instance from singleton cache: It might have been put there
                    // eagerly by the creation process, to allow for circular reference resolution.
                    // Also remove any beans that received a temporary reference to the bean.
                    destroySingleton(beanName);
                    throw ex;
                }
            }
        });
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    }
    
    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "'beanName' must not be null");
        synchronized (this.singletonObjects) {
            // 先从缓存中获取
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName,
                            "Singleton bean creation not allowed while the singletons of this factory are in destruction " +
                            "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }
    
                // 将当前Bean设置为正在加载状态并放到缓存中,可以对循环依赖进行检查。inCreationCheckExclusions 里面应该是缓存了一些再创建Bean时需要排除的Bean?
                beforeSingletonCreation(beanName);
    
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<Exception>();
                }
                try {
    
                    // 回调方法,真正的实例化Bean逻辑。
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                }
                catch (IllegalStateException ex) {
                    // Has the singleton object implicitly appeared in the meantime ->
                    // if yes, proceed with it since the exception indicates that state.
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw ex;
                    }
                }
                catch (BeanCreationException ex) {
                    if (recordSuppressedExceptions) {
                        for (Exception suppressedException : this.suppressedExceptions) {
                            ex.addRelatedCause(suppressedException);
                        }
                    }
                    throw ex;
                }
                finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
    
                    // Bean创建完成之后,将它的正在创建状态从缓存中移除
                    afterSingletonCreation(beanName);
                }
                if (newSingleton) {
                    // 添加到缓存中
                    addSingleton(beanName, singletonObject);
                }
            }
    
            return (singletonObject != NULL_OBJECT ? singletonObject : null);
        }
    }
    

    创建Bean实例的操作就在getObject方法里面,可以看出这是一个回调方法,在这个方法内部,调用了 AbstractAutowireCapableBeanFactory 类的 createBean方法,在这方方法总,主要需要关注两个方法 resolveBeforeInstantiation 和 doCreateBean,前者是试图根据初始化前后处理器返回一个代理实例,后者即真正的创建实例逻辑

    protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
        if (logger.isDebugEnabled()) {
            logger.debug("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,根据设置的class属性或者根据className来解析class  
        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 {
            // 如果Bean配置了初始化前和初始化后的处理器,则试图返回一个需要创建Bean的代理对象,如果成功就直接返回了,下面的流程就不执行了。
            // 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);
        }
    
        // 创建Bean实例
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    
        if (logger.isDebugEnabled()) {
            logger.debug("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
    

    有关于resolveBeforeInstantiation这个方法,重点解释一下。方法体看起来很简单,如果Bean配置了初始化前和初始化后的处理器,则试图返回一个需要创建Bean的代理对象,如果成功就直接返回了,下面的流程就不执行了。我想了很久才明白到它这里说的代理是什么意思,这里确实要结合AOP这一块的内容。简单从方法体上来看,一个就是在实例化前调用InstantiationAwareBeanPostProcessor是实现类的postProcessBeforeInstantiation方法;在实例化后,调用BeanPostProcessor实现类的postProcessAfterInitialization方法,就相当于是给我们预留的两个修改Bean信息的入口,这是没有什么疑问的。但这里为什么要扯到什么代理呢?这是因为如果我们用了AOP的时候,是需要为一些Bean生成代理类类,resolveBeforeInstantiation方法中就想到了这种情况。因为如果需要为某个Bean生成代理对象的话,在调用BeanPostProcessor是实现类的postProcessAfterInitialization方法之后,代理类就已经生成了,而我们需要的就是代理对象,就没必要再执行下面的实例化、初始化的流程了。

    protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            // Make sure bean class is actually resolved at this point.
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                Class<?> targetType = determineTargetType(beanName, mbd);
                if (targetType != null) {
                    bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    if (bean != null) {
                        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                }
            }
            mbd.beforeInstantiationResolved = (bean != null);
        }
        return bean;
    }
    
    // 实例化前
    protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName)
            throws BeansException {
    
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
                if (result != null) {
                    return result;
                }
            }
        }
        return null;
    }
    
    // 实例化后 但是这个方法调用不是应该再初始化后吗,为什么在这里调用。可是如果不在这里调用,那就没办法为生成的代理对象处理了,不太懂
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException {
    
        Object result = existingBean;
        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            result = beanProcessor.postProcessAfterInitialization(result, beanName);
            if (result == null) {
                return result;
            }
        }
        return result;
    }
    

    接下来就是创建Bean实例的doCreateBean方法,里面又有很多的逻辑,分很多步骤,每个步骤都很繁琐。

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
        // 实例化之前,将BeanDefinition转换为Wrapper
        // Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            // 根据指定Bean使用对应的策略创建新的实例,如:构造函数、工厂方法、简单初始化
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
    
        final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
        Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
    
        // 允许 MergedBeanDefinitionPostProcessors 实现类修改 Bean 的定义信息,Bean合并后的处理
        // Allow post-processors to modify the merged bean definition.
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                mbd.postProcessed = true;
            }
        }
    
        // 涉及到循环依赖,看不太懂
        // Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            if (logger.isDebugEnabled()) {
                logger.debug("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            addSingletonFactory(beanName, new ObjectFactory<Object>() {
                @Override
                public Object getObject() throws BeansException {
                    // 针对 SmartInstantiationAwareBeanPostProcessor 实现类,不太清楚想要干嘛
                    return getEarlyBeanReference(beanName, mbd, bean);
                }
            });
        }
    
        // 准备初始化Bean了
        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            // 将各个属性值注入Bean中,可能存在依赖于其它Bean的属性,会递归调用
            populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
    
                // 调用初始化方法,比如 init-method
                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);
    
            // earlySingletonReference只有在检测到有循环依赖的情况下才会不为空
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                }
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
                    for (String dependentBean : dependentBeans) {
                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }
    
                    // actualDependentBeans 不为空表示当前的Bean创建后其依赖的Bean却没有创建完成,也就是说存在循环依赖
                    if (!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName,
                                "Bean with name '" + beanName + "' has been injected into other beans [" +
                                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                                "] in its raw version as part of a circular reference, but has eventually been " +
                                "wrapped. This means that said other beans do not use the final version of the " +
                                "bean. This is often the result of over-eager type matching - consider using " +
                                "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }
    
        // Register bean as disposable.
        try {
            // 注册 Bean销毁方法
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }
    
        return exposedObject;
    }
    

    在Spring中解决循环依赖对单例有效,而对于prototype的bean,Spring没有好的解决办法,唯一要做的就是抛出异常。假如A含有B的属性,B又含有A的属性,这就形成了一个循环依赖,此时如果A和B都是单例,那么在Spring中的处理方式就是在创建B的时候,涉及自动注入A的步骤时,并不是直接去再次创建A,而是通过放入缓存的ObjectFactory来创建实例,这样就解决了循环依赖的问题。

    接下来看看createBeanInstance方法,这个方法里面很复杂,我就省略了一些代码,看看最关键实例化那个步骤的处理。首先判断BeanDefinition.getMethodOverrides()为空也就是用户没有使用replace或者lookup的配置方法,那么直接使用反射的技术;如果有配置这两个方法,就是用CGLIB进行动态代理,因为可以在创建代理的同时将动态方法织入代理类中。

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
        ......
        return instantiateBean(beanName, mbd);
        ......
    }
    
    protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
        try {
            Object beanInstance;
            final BeanFactory parent = this;
            if (System.getSecurityManager() != null) {
                beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    @Override
                    public Object run() {
                        return getInstantiationStrategy().instantiate(mbd, beanName, parent);
                    }
                }, getAccessControlContext());
            }
            else {
                beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
            }
            BeanWrapper bw = new BeanWrapperImpl(beanInstance);
            initBeanWrapper(bw);
            return bw;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
        }
    }
    
    @Override
    public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
        // Don't override the class with CGLIB if no overrides.
        if (bd.getMethodOverrides().isEmpty()) {
            Constructor<?> constructorToUse;
            synchronized (bd.constructorArgumentLock) {
                constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
                if (constructorToUse == null) {
                    final Class<?> clazz = bd.getBeanClass();
                    if (clazz.isInterface()) {
                        throw new BeanInstantiationException(clazz, "Specified class is an interface");
                    }
                    try {
                        if (System.getSecurityManager() != null) {
                            constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
                                @Override
                                public Constructor<?> run() throws Exception {
                                    return clazz.getDeclaredConstructor((Class[]) null);
                                }
                            });
                        }
                        else {
                            constructorToUse =  clazz.getDeclaredConstructor((Class[]) null);
                        }
                        bd.resolvedConstructorOrFactoryMethod = constructorToUse;
                    }
                    catch (Throwable ex) {
                        throw new BeanInstantiationException(clazz, "No default constructor found", ex);
                    }
                }
            }
            return BeanUtils.instantiateClass(constructorToUse);
        }
        else {
            // Must generate CGLIB subclass.
            return instantiateWithMethodInjection(bd, beanName, owner);
        }
    }
    

    有关于属性填充这一块内容就略过了,直接看初始化方法initializeBean吧

    protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    invokeAwareMethods(beanName, bean);
                    return null;
                }
            }, getAccessControlContext());
        }
        else {
            // 对特殊Bean处理:Aware、BeanClassLoaderAware、BeanFactoryAware
            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;
    }
    
    private void invokeAwareMethods(final String beanName, final Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware) bean).setBeanName(beanName);
            }
            if (bean instanceof BeanClassLoaderAware) {
                ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
            }
            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
            }
        }
    }
    
    // 初始化之前,会调用所有BeanPostProcessor所有实现类的postProcessBeforeInitialization方法
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
            throws BeansException {
    
        Object result = existingBean;
        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            result = beanProcessor.postProcessBeforeInitialization(result, beanName);
            if (result == null) {
                return result;
            }
        }
        return result;
    }
    
    // 初始化之后,会调用所有BeanPostProcessor所有实现类的postProcessAfterInitialization方法
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException {
    
        Object result = existingBean;
        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            result = beanProcessor.postProcessAfterInitialization(result, beanName);
            if (result == null) {
                return result;
            }
        }
        return result;
    }
    

    Spring中提供了一些Aware相关接口,比如BeanFacrotyAware、ApplicationContextAware、ResourceLoaderAware、ServletContextAware等,实现这些Aware接口的Bean在被初始化前可以获得一些资源,例如实现BeanFacrotyAware的Bean在初始化后,Spring容器会注入BeanFactory的实例。

    然后就是激活自定义init方法invokeInitMethods。客户定制的初始化方法除了我们熟知的init-method方法之外,还可以让Bean实现InitializingBean接口,并在afterPropertiesSet方法中实现自定义初始化逻辑

    protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
            throws Throwable {
    
        // 先检查是否实现了InitializingBean接口,实现了就调用afterPropertiesSet方法      
        boolean isInitializingBean = (bean instanceof InitializingBean);
        if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
            if (logger.isDebugEnabled()) {
                logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
            }
            if (System.getSecurityManager() != null) {
                try {
                    AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                        @Override
                        public Object run() throws Exception {
                            ((InitializingBean) bean).afterPropertiesSet();
                            return null;
                        }
                    }, getAccessControlContext());
                }
                catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            }
            else {
                ((InitializingBean) bean).afterPropertiesSet();
            }
        }
    
        if (mbd != null) {
            String initMethodName = mbd.getInitMethodName();
            if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                    !mbd.isExternallyManagedInitMethod(initMethodName)) {
                // 调用自定义初始化方法 就是 method.invoke(bean)
                invokeCustomInitMethod(beanName, bean, mbd);
            }
        }
    }
    

    registerDisposableBeanIfNecessary用于 注册 Bean销毁方法。除了可以配置属性destory-method外,还可以通过实现DestructionAwareBeanpostprocessor接口来统一处理Bean的销毁方法

    protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
        AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
        if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
            if (mbd.isSingleton()) {
                // 单例模式下注册需要销毁的Bean,此方法中会处理实现DisposableBean接口的Bean,b并且对所有Bean使用 DestructionAwareBeanpostprocessor 是实现类 处理
                registerDisposableBean(beanName,
                        new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
            }
            else {
                // A bean with a custom scope...
                Scope scope = this.scopes.get(mbd.getScope());
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
                }
                scope.registerDestructionCallback(beanName,
                        new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
            }
        }
    }
    

    到这里,一个Bean身上该发生的基本上都介绍了,也包括Bean的生命周期,现在返回的Bean,就是我们能够正常使用的Bean了。

    ApplicationContext流程

    前面有说到过,ApplicationContext是一个非常高级的接口,实现了非常多的接口,可以看看它的继承关系图,很庞大

    post_005

    这一大章节我们主要以ClassPathXmlApplicationContext为切入点,测试代码如下:

    public class TestApplicationContext {
        public static void main(String[] args) {
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("config.xml");
    
            Object o = applicationContext.getBean("simpleMethodInterceptor");
            System.out.println(o);
    
        }
    }
    

    入口

    ClassPathXmlApplicationContext构造函数非常简单,为application contex设置好文件路径后,直接就调用了refresh方法,该方法中几乎包含了ApplicationContext中的所有功能

    public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
        this(new String[] {configLocation}, true, null);
    }
    
    public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
            throws BeansException {
    
        super(parent);
        setConfigLocations(configLocations);
    
        if (refresh) {
            // 容器初始化入口
            refresh();
        }
    }
    
    // 为application contex 设置配置文件路径
    public void setConfigLocations(String... locations) {
        if (locations != null) {
            Assert.noNullElements(locations, "Config locations must not be null");
            this.configLocations = new String[locations.length];
            for (int i = 0; i < locations.length; i++) {
                this.configLocations[i] = resolvePath(locations[i]).trim();
            }
        }
        else {
            this.configLocations = null;
        }
    }
    
    
    // 以下是抽象类的 AbstractApplicationContext 的方法
    public AbstractApplicationContext(ApplicationContext parent) {
        this();
        setParent(parent);
    }
    public AbstractApplicationContext() {
        this.resourcePatternResolver = getResourcePatternResolver();
    }
    // 创建一个资源解析器?
    protected ResourcePatternResolver getResourcePatternResolver() {
        return new PathMatchingResourcePatternResolver(this);
    }
    
    public void setParent(ApplicationContext parent) {
        this.parent = parent;
        if (parent != null) {
            Environment parentEnvironment = parent.getEnvironment();
            if (parentEnvironment instanceof ConfigurableEnvironment) {
                getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
            }
        }
    }
    

    refresh的默认实现在AbstractApplicationContext抽象类中,它是一个模板方法,refresh方法的作用是:在创建IoC容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在refresh之后使用的是新建立起来的IoC容器。refresh的作用类似于对IoC容器的重启,在新建立好的容器中对容器进行初始化,对Bean定义资源进行载入

    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // 调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识  
            prepareRefresh();
    
            // 初始化beanFactory,并读取解析XML配置文件
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
            // 对BeanFactory各种填充,例如类加载器、事件处理器等
            prepareBeanFactory(beanFactory);
    
            try {
                // 子类覆盖方法做额外的处理
                postProcessBeanFactory(beanFactory);
    
                // 激活各种BeanFactory处理器
                invokeBeanFactoryPostProcessors(beanFactory);
    
                // 注册 拦截Bean创建的Beanc处理器,这里只是注册,起作用是在调用getBean方法的时候
                registerBeanPostProcessors(beanFactory);
    
                // 为上下文初始化Message源,即国际化处理
                initMessageSource();
    
                // 初始化消息广播器,并插入 'applicationEventMulticaster" Bean中
                initApplicationEventMulticaster();
    
                // 留给子类来初始化其它的Bean
                onRefresh();
    
                // 在注册的Bean中查找Listener Bean,注册到消息广播中
                registerListeners();
    
                // 初始化剩下的单实例(非惰性)
                finishBeanFactoryInitialization(beanFactory);
    
                // 完成刷新过程,通知生命周期处理器 lifecycleProcessor 刷新过程,同时发布ContextRefreshEvent通知别人
                finishRefresh();
            }
    
            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }
    
                // 销毁以创建的单态Bean
                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();
    
                // 取消refresh操作,重置容器的同步标识
                // Reset 'active' flag.
                cancelRefresh(ex);
    
                // Propagate exception to caller.
                throw ex;
            }
    
            finally {
                // 重置Spring 的常见核心缓存
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }
    

    obtainFreshBeanFactory

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        // 初始化BeanFactory,并进行xml文件读取解析,并将得到的BeanFactory记录在当前实体的属性中
        refreshBeanFactory();
    
        // 返回当前实体的 BeanFactory 属性
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }
    
    
    // AbstractRefreshableApplicationContext # refreshBeanFactory
    protected final void refreshBeanFactory() throws BeansException {
    
        // 如果beanFactory 存在,就先销毁,然后再重新创建
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            // 创建 DefaultListableBeanFactory
            DefaultListableBeanFactory beanFactory = createBeanFactory();
    
            // 为序列号指定id
            beanFactory.setSerializationId(getId());
    
            //定制BeanFactory,设置相关属性,包括是否允许覆盖同名称的不同定义的对象以及循环依赖,以及设置@Autowired 、 @Qualifier 注解解析器 QualifierAnnotationAutowireCandidateResolver
            customizeBeanFactory(beanFactory);
    
            // 初始化DocumentReader,并进行XML文件读取解析
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }
    

    AbstractXmlApplicationContext # loadBeanDefinitions

    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        // 老面孔
        // Create a new XmlBeanDefinitionReader for the given BeanFactory.
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    
        // Configure the bean definition reader with this context's
        // resource loading environment.
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
    
        // 这是设置啥?可以覆盖
        // Allow a subclass to provide custom initialization of the reader,
        // then proceed with actually loading the bean definitions.
        initBeanDefinitionReader(beanDefinitionReader);
    
    
        loadBeanDefinitions(beanDefinitionReader);
    
    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
        Resource[] configResources = getConfigResources();
        if (configResources != null) {
            reader.loadBeanDefinitions(configResources);
        }
        String[] configLocations = getConfigLocations();
        if (configLocations != null) {
            reader.loadBeanDefinitions(configLocations);
        }
    }
    
    public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
        Assert.notNull(resources, "Resource array must not be null");
        int counter = 0;
        for (Resource resource : resources) {
            counter += loadBeanDefinitions(resource);
        }
        return counter;
    }
    
    // 到这里就完全和我们上面介绍的 Bean解析一模一样了
    public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
        return loadBeanDefinitions(new EncodedResource(resource));
    }
    

    先消化一下,以后再写吧,待续。。。

    有很多很多内容都是直接跳过的,可以看到Spring对Bean处理这一块真的是太复杂了,不过主要的流程也基本上清楚了,也许看第二遍的似乎就会舒服很多了。

    相关文章

      网友评论

        本文标题:SpringIOC

        本文链接:https://www.haomeiwen.com/subject/ildpvftx.html