Spring 4.3 源码分析之 IOC 基本容器启动

1. IOC 容器启动之猜测

在进行分析 Spring 容器启动时, 我们先歪歪一下, Spring 容器启动到底做了什么事情, 有什么好特别

1. 定位描述 Bean 依赖关系的 Xml 文件地址, 创建 DocumentBuilder 对象, 并将xml解析成 Document 
2. 通过 DefaultBeanDefinitionDocumentReader 及 BeanDefinitionParserDelegate 进行解析 XML中的每个节点 --> BeanDefinition
3. 将 2 中解析的 BeanDefinition 注册到容器中
4. 有了上面 Bean 定义的信息, 接着就可以通过 BeanFactory.getBean() 方法来创建+获取 Bean
5. 在创建之前若系统中有 BeanFactoryBeanPostProcessor, 则将 BeanFactoryBeanPostProcessor 对 容器中的 BeanDefinition 进行一些修饰(比如将 BeanDefinition 中的一些占位符(${}) 中的内容替换成 properties 中的内容)
6. 若容器中存在 InstantiationAwareBeanPostProcessor, 则先调用 实例化前置方法(postProcessBeforeInstantiation) 来进行生成代理对象(若配置了 customTargetSourceCreators, 则将创建对应的代理对象)
7. 通过反射来直接创建类(其实在这之前还有一部分, 查看是否类有定制的构造函数(在 SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructor), 对对对, 其实真正的用到的是 @Autowired 注解(在AutowiredAnnotationBeanPostProcessor中), 这个注解可以指定对应的构造函数)
8. 再次收集 Bean 上需要配置的信息(这部分配置的信息主要指在 Bean 的属性, 方法上设置的依赖属性), 接口MergedBeanDefinitionPostProcessor的 postProcessMergedBeanDefinition就是入口, 比如 AutowiredAnnotationBeanPostProcessor收集 @Autowired, @Value; CommonAnnotationBeanPostProcessor 收集 @Resource
9. 若当前对象是单例, 且容器允许循环引用, 则直接将刚刚生成的对象包裹在 ObjectFactory 里面, 放在singletonFactories中进行暴露(这里就是 Spring 解决循环依赖的方法)
10. 调用 InstantiationAwareBeanPostProcessor 的postProcessAfterInstantiation 方法来决定是否需要解决 xml 或通过在类属性上配置注解 的依赖属性, 若返回 false, 则直接返回
11. 解决 Bean 上配置的通过 @Autowired, @Value, @Resource 设置的依赖属性(通过 InstantiationAwareBeanPostProcessor的postProcessPropertyValues)
12. 解决 xml 上配置的依赖属性(比如 ref, property, list, map 等)
13. invoke 实现了 Aware 的接口方法, 主要是设置 BeanFactory, BeanName, BeanClassLoader 等
14. 调用 Bean 初始化方法的前置方法(注意上面是 Bean 的实例化 Instantiation, 这里是 Bean 的初始化 Initialization) postProcessBeforeInitialization <-- 其实这个方法没做什么, 其中一个比较重要的是设置一些 Aware(AoolicationContextAwareProcessor)
15. 初始化 Bean 的初始化方法, 初始化方法主要是实现 InitializaingBean 接口的 afterPropertiesSet, 与在 xml 中配置的初始化方法
16. 执行 Bean 初始化的后置方法(BeanProcessor.postProcessAfterInitialization), 这里其实是一般 AOP 实现的入口, 主要是 基于aop命名空间实现动态代理的 AspectJAwareAdvisorAutoProxyCreator 与基于 AspectJ 注解的 AnnotationAwareAspectJAutoProxyCreator (这两个在 AOP 那篇中会详述)
17. 这时 Bean 的依赖属性已经设置好了, 该生成代理类, 也生成了, 接着就放到容器中(若 Bean 是单例, 则会将 Bean 包裹成 DispoableBeanAdapter 主要是为后续激活xml的销毁方法或 DisposableBean.destory), 直接返回生成的 Bean 对象

上面的流程很多, 这个只是我自己对bean注入/创建的概述总结, 其中有几个注意点:

1. 其中将 Xml 里面的信息解析成 BeanDefinition是个很复杂的过程, 但其中可能只有 模版模式, 代理模式, NamespaceHandler 才真正的对我们工作有比较好的借鉴意义, 没有必要花很长时间在这里
2. Bean的整个创建主要分成, 依赖信息的收集, Bean的实例化(Instantiation), Bean的初始化(Initialization),(PS: 要牢记 "实例化"与"初始化" 这两个概念)
2. IOC 基本容器启动 Demo

这里指的基本容器就是 "DefaultListableBeanFactory", 下面我看一个 Demo:




    


// 测试代码
@Test
public void doTraditionBeanFactory() throws Exception {
    String resourceName = "org/springframework/beans/factory/xml/application.xml";
    // 最基本的 IOC 工厂 DefaultListableBeanFactory
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    // 配置Bean依赖文件 
    Resource resource = new ClassPathResource(resourceName);
    // 使用 XML 读取器读取 xml 里面的信息, 并且设置到 BeanFactory 中
    new XmlBeanDefinitionReader(factory).loadBeanDefinitions(resource);
    // 获取 BeanFactory 中的对象 (PS: 注意这时 容器中指存在 BeanDefinition, 还未生成对应的 Bean)
    TestBean bean = (TestBean) factory.getBean("testBean");
    assertNotNull(bean);
}

上面的Demo中主要有以下组件:

1. DefaultListableBeanFactory: 最基本也是最实用的 BeanFactory 工厂
2. Resource: 对xml资源的统一封装
3. XmlBeanDefinitionReader: xml文件的读取器, 主要完成 xml 里面配置资源的解析(解析成BeanDefinition), 并且注入到 BeanFactory 中

对仅仅这3个类就完成了Bean配置文件的定位, 读取, 解析, 注入, 类创建, 下面会一一进行解析

3. 配置文件的定位与读取

这里的配置文件 "org/springframework/beans/factory/xml/application.xml" 包裹在ClassPathResource, 通过 class/classLoader 来直接读取文件, 转换成数据流

public InputStream getInputStream() throws IOException {
    // 下面通过 class/ClassLoader 来判断怎么去读取资源
    InputStream is;
    if (this.clazz != null) {                               // 若配置了 class, 则直接通过 class 来获取文件的数据流对象
        is = this.clazz.getResourceAsStream(this.path);
    }
    else if (this.classLoader != null) {                    // 若配置了 classLoader, 则直接通过 classLoader 来获取文件的数据流对象      
        is = this.classLoader.getResourceAsStream(this.path);
    }
    else {                                                  // 通过这个方法的调用类(也就是 Reflection.getCallerClass())背后的 classLoader 来获取数据流
        is = ClassLoader.getSystemResourceAsStream(this.path);
    }
    if (is == null) {
        throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");
    }
    return is;
}

有了数据流, 我们就可以通过 Document 解析器解析成 Document, 在根据 Document中每个节点所在的 Namespace 来解析成对应的 BeanDefinition

4. 将配置文件解析成 BeanDefinition (解析主入口)

这里有个偏离目录以下, 常见的Bean配置文件主要通过 BeanDefinitionReader(子类 XmlBeanDefinitionReader, PropertiesBeanDefinitionReader), 或扫描指定目录下面的所有 class 文件, 将被指定注解修饰的类注入到容器中, 一般现在这两种方法在项目中都使用, 其中 XmlBeanDefinitionReader 完成 PropertiesBeanDefinitionReader, 我将这个归结为以下原因:

1. 用 XML 配置 Bean, 扩展性好(支持各种数据结构, list, map)
2. 能自己扩充命名空间(基本命名空间只针对  标签), 比如Spring原生扩充的命名空间, (aop中),  (事务配置), (SpringMVC中配置)

直接看 XmlBeanDefinitionReader 的加载过程吧

// 这里是载入 XML 形式 Bean 定义资源文件的方法
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    Assert.notNull(encodedResource, "EncodedResource must not be null");
    if (logger.isInfoEnabled()) {
        logger.info("Loading XML bean definitions from " + encodedResource.getResource());
    }
    // 通过类属性 resourcesCurrentlyBeingLoaded 记录当前线程已加载的资源
    Set currentResources = this.resourcesCurrentlyBeingLoaded.get();
    if (currentResources == null) {
        currentResources = new HashSet(4);
        this.resourcesCurrentlyBeingLoaded.set(currentResources);
    }
    // 若配置信息已经加载过, 则直接抛出异常
    if (!currentResources.add(encodedResource)) {
        throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    }
    try {
        // 将资源文件转为 InputStream 的 IO 流
        InputStream inputStream = encodedResource.getResource().getInputStream();
        try {
            // 把 InputStream 封装成 InputSource(InputSource 这个类并不来自于 Spring, 它的全路径是 org.xml.sax.InputSource), 接着就是 通过 DocumentBuilder 解析 Docuement
            InputSource inputSource = new InputSource(inputStream);
            if (encodedResource.getEncoding() != null) {
                inputSource.setEncoding(encodedResource.getEncoding());
            }
            // doLoadbeanDefinitions 才是核心加载资源文件的方法
            return doLoadBeanDefinitions(inputSource, encodedResource.getResource());       
        }
        finally {
            inputStream.close();                // 关闭从 Resource 中得到的 IO 流
        }
    }
    catch (IOException ex) {
        throw new BeanDefinitionStoreException(
                "IOException parsing XML document from " + encodedResource.getResource(), ex);
    }
    finally {
        currentResources.remove(encodedResource);
        if (currentResources.isEmpty()) {
            this.resourcesCurrentlyBeingLoaded.remove();
        }
    }
}

代码进行到这里其实我们只是获取对应的 xml的数据流对象, 接着需要将 数据流对象转化成 Document 对象, 针对这部分内容,首先需要介绍下面几个对象:

1. DefaultDocumentLoader: 这个类完成了 Document 解析器工厂 DocumentBuilderFactory 的创建及配置(配置是否支持命名空间, 是否支持校验)
2. XmlValidationModeDetector: xml 格式的校验器, 校验 xml头是否是包含 "DOCTYPE", 校验每个节点是否是 "<" 开头, ">" 结尾
3. errorHandler: xml解析错误时的报警机制
4. DocumentBuilder: 将数据流包装类 InputSource 解析成 Doucment 的解析器 ( 这个类存在于 javax.xml.parsers 中)
5. DocumentBuilderFactory: DocumentBuilder的工厂类, 其中主要设置 校验模式与是否支持命名空间

以上几个最中还是 DocumentBuilder 将xml解析成 Document, 有了Document我们可以接下来的 Document解析成 BeanDefinition 工作

现在又会出现有几个非常重要的工具类:

1. DefaultNamespaceHandlerResolver: xml中Namespace解析器, 这个类会获取所有 jar/war/directory 中"META-INF/spring.handlers"的内容, 生成对应的 NamespaceHandler, 并调用 init方法进行初始化(这里定义各个各个标签的详细Bean解析器 -> BeanDefinitionParser)
2. XmlReaderContext: Xml读取器上下文, 里面包含了 ProblemReporter,  ReaderEventListener, SourceExtractor (前面三个类几乎没做什么东西), NamespaceHandlerResolver(xml中节点的命名空间解析器), 当然还有 BeanDefinitionRegistry(其实这里就是 DefaultListableBeanFactory), 

上面出现了多个工具类(对, 没错, 为了解析个xml文件, Spring使用了这么多的工具类), 接下来就是 Docment 的解析

先看一下解析的入口:

/**
 * 如果想在 XML 解析前后对 Element 元素做一些处理(模版模式)
 * 则在 DefaultBeanDefinitionDocumentreader 的子类重写 preProcessXml(...) postProcessXml(..) 即可
 * Register each bean definition within the given root {@code } element.
 */
protected void doRegisterBeanDefinitions(Element root) {
    BeanDefinitionParserDelegate parent = this.delegate;
    // 创建解析的委托处理工具类 (这个类 用于完成正真的解析过程)
    this.delegate = createDelegate(getReaderContext(), root, parent);

    if (this.delegate.isDefaultNamespace(root)) {
        // 此处针对  的节点属性 profile 进行操作
        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)) {      // 查看环境变量中的 Profile 是否和 xml一致, 若不一致则直接不属于这个 profile, 直接返回
                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, 这个类也是解析的核心类, 无论是 , , 标签, 还是其他命名空间的标签, 都是由这个类来进行解析的, 这时再看看在 DefualtBeanDefinitionDocumentReader 的解析策略(主要以 Namespace 来进行区分)

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    // Bean 定义额 Document 对象使用了 Spring 默认的 XML 命名空间 (http://www.springframework.org/schema/beans)
    if (delegate.isDefaultNamespace(root)) {
        // 获取 Bean 定义的 Document 对象根元素的所有子节点
        NodeList nl = root.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            // 获取  Document 节点是 XML 元素节点
            if (node instanceof Element) {
                Element ele = (Element) node;
                // 若果是默认命名空间(beans), 则直接解析 比如 
                if (delegate.isDefaultNamespace(ele)) {
                    // 解析 import 标签, alias 标签, bean 标签, 内置  标签
                    parseDefaultElement(ele, delegate);
                }
                else {
                    // 没有使用 Spring 默认的 XML 命名空间, 则使用用户自定义的解析规则解析元素节点 (这里蕴含这在默认命名空间的节点里面可以存在非默认命名空间的节点)
                    delegate.parseCustomElement(ele);
                }
            }
        }
    }
    else {
        // Document 的根节点没有使用 Spring 默认的命名空间, 则使用用户自定义的
        delegate.parseCustomElement(root);
    }
}

从这里可以看出无论是否是默认命名空间, 都是通过 BeanDefinitionParserDelegate 来进行解析

5. 默认命名空间标签解析

这里主要针对 import, alias, bean, beans 标签进行解析

// 使用 Spring 的 Bean 规则解析 Document 元素节点
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);
    }
    // 元素节点既不是导入元素, 也不是别名元素, 即普通的  元素,
    // 按照 Spring 的bean规则解析元素
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
        processBeanDefinition(ele, delegate);
    }
    // 如果是 beans 标签, 则回到代码的上层, 递归解析
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
        // recurse
        // 递归
        doRegisterBeanDefinitions(ele);
    }
}

当遇到 import标签时, 直接读取对应资源, 并通过 XmlBeanDefinitionReader 再次进行读取资源配置文件

/**
 * Parse an "import" element and load the bean definitions
 * from the given resource into the bean factory.
 *
 * Demo
 *
 * 
 *     
 *     
 * 
 */
// 解析  导入元素, 从给定的导入路径加载 Bean定义资源到 Spring Ioc 容器中
protected void importBeanDefinitionResource(Element ele) {
    // 获取  标签的 resource 属性值
    String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
    // 如果导入额元素的 location 属性值为空, 则没有导入任何资源, 直接返回
    if (!StringUtils.hasText(location)) {
        getReaderContext().error("Resource location must not be empty", ele);
        return;
    }
    // 这里强调一下, 对于  标签, 其会从 System.getProperties() 和 System.getenv() 中属性获取, 进行解析占位符 ${} 中的内容
    location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);

    Set actualResources = new LinkedHashSet(4);

    // 标识给定的导入元素的 location 是否是绝对路径
    // Discover whether the location is an absolute or relative URI
    boolean absoluteLocation = false;
    try {
        absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
    }
    catch (URISyntaxException ex) {
        // cannot convert to an URI, considering the location relative
        // unless it is the well-known Spring prefix "classpath*:"
        // 给定的导入元素的 location 不是绝对路径
    }

    // 如果是绝对 URI 则直接根据 地址加载对应的配置文件
    // 给定的导入元素的 location 是绝对路径
    // Absolute or relative?
    if (absoluteLocation) {
        try {
            // 使用资源读入器加载给定路径的 Bean 定义资源(这里其实就是递归解析的一个过程)
            int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
            if (logger.isDebugEnabled()) {
                logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
            }
        }
        catch (BeanDefinitionStoreException ex) {
            getReaderContext().error(
                    "Failed to import bean definitions from URL location [" + location + "]", ele, ex);
        }
    }
    else {
        // 如果是相对路径, 则根据相对地址计算出绝对地址
        // No URL -> considering resource location as relative to the current file.
        try {
            int importCount;
            // 将给定导入元素的 location 封装为相对路径资源
            Resource relativeResource = getReaderContext().getResource().createRelative(location);
            // 封装的相对路径资源存在
            if (relativeResource.exists()) {        // 下面又是 解析 xml 里面的描述信息, 来加载 Bean
                importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
                actualResources.add(relativeResource);
            }
            // 封装的相对路径资源不存在
            else {  // 如果解析不成功, 则使用默认的解析器 ResourcePatternResolver 进行解析
                // 获取 Spring Ioc 容器资源读入器的基本路径
                String baseLocation = getReaderContext().getResource().getURL().toString();
                // 下面又是 解析 xml 里面的描述信息, 来加载 Bean
                importCount = getReaderContext().getReader().loadBeanDefinitions(
                        StringUtils.applyRelativePath(baseLocation, location), actualResources);
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");
            }
        }
        catch (IOException ex) {
            getReaderContext().error("Failed to resolve current resource location", ele, ex);
        }
        catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]",
                    ele, ex);
        }
    }
    Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]);
    // 在解析完  元素之后, 向对应监听器发送相应时间通知
    getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
}

当遇到 标签时, 会将解析的结果注册到 DefaultListableFactory 的父级类 SimpleAliasRegistry#aliasMap 中

/**
 * Process the given alias element, registering the alias with the registry.
 */
// 解析  别名元素, 为 Bean 向 Spring Ioc 容器注册别名
protected void processAliasRegistration(Element ele) {
    // 获取  别名元素中的 name 的属性值
    String name = ele.getAttribute(NAME_ATTRIBUTE);
    // 获取  别名元素中 alias 的属性值
    String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
    boolean valid = true;
    //  别名元素的 name 属性值是否为空
    if (!StringUtils.hasText(name)) {
        getReaderContext().error("Name must not be empty", ele);
        valid = false;
    }
    //  别名元素的 alias 属性值是否为空
    if (!StringUtils.hasText(alias)) {
        getReaderContext().error("Alias must not be empty", ele);
        valid = false;
    }
    if (valid) { // name/alias 都不为空
        try {
            // 向容器的资源读入器注册别名, 查阅后其会保存到 DefaultListableFactory 的父级类 SimpleAliasRegistry#aliasMap 中
            getReaderContext().getRegistry().registerAlias(name, alias);
        }
        catch (Exception ex) {
            getReaderContext().error("Failed to register alias '" + alias +
                    "' for bean with name '" + name + "'", ele, ex);
        }
        // 解析完  元素之后, 发送容器别名处理完成事件
        getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
    }
}

到了精彩的地方 标签的解析, 这是一个非常复杂的解析过程, 先看以下主逻辑:

// 解析 Bean 定义资源 Document 对象的普通元素
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    /**
     * 利用 BeanDefinitionParserDelegate.parseBeanDefinitionElement(Element e)
     * 解析给定的 bean 元素信息为, BeanDefinitionHolder, 这其中就包含了 id, class, alias, name 等属性
     */
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
        // 这里就是对  标签里面, 不是能通过命名空间解析得了的标签的解析
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {
            // 向 Spring Ioc 容器注册解析得到 Bean 定义, 这是 Bean 定义向 Ioc 容器注册的入口
            // 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);
        }
        // 解析完成, 发送相应的注册事件
        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}

OK 这里又分为两部分, bean标签及里面子标签的解析, 先是解析 标签中的 id, name等属性

// 解析 Bean 定义资源文件中的  元素, 这个方法中主要处理  元素的 id, name
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
    // 获取  元素中的 id 属性值
    String id = ele.getAttribute(ID_ATTRIBUTE);
    // 如果有 name 属性, 则获取 name, 并且 可有多个 name, 以 , ; 为分隔符号
    String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
    
    // 将  元素中的所有的 name 属性值存放到别名中
    List aliases = new ArrayList();
    if (StringUtils.hasLength(nameAttr)) {
        String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
        aliases.addAll(Arrays.asList(nameArr));
    }

    String beanName = id;
    // 如果  元素中没有配置 id 属性时, 将别名中的第一个值赋值给 beanName
    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");
        }
    }
    
    // 检查  元素所配置的 id 或者 name 的唯一性, containingBean 标识 
    if (containingBean == null) {
        // 检查  元素锁所配置的 id, name 或者别名是否重复
        checkNameUniqueness(beanName, aliases, ele);
    }
    
    // 详细对  元素中配置的 Bean 定义进行解析的地方
    AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
    if (beanDefinition != null) {
        if (!StringUtils.hasText(beanName)) {
            try { 
                if (containingBean != null) { // (PS: containingBean默认是 null)
                    //  为解析的 Bean 生成一个唯一额 beanName 并注册
                    beanName = BeanDefinitionReaderUtils.generateBeanName(
                            beanDefinition, this.readerContext.getRegistry(), true);
                }
                else {
                    // 为解析的 Bean 生成 beanName, 并加入到 aliases中
                    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);
        return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
    }
    // 解析出错, 返回 null
    return null;
}

接着呢是 bean 标签里面的其他属性进行解析

/**
 * Parse the bean definition itself, without regard to name or aliases. May return
 * {@code null} if problems occurred during the parsing of the bean definition.
 */
// 详细对  元素中配置的 Bean 定义其他属性进行解析, 由于 上面的方法中已经对 Bean 的id, name等属性进行处理, 该方法主要处理除了这两个个以外的其他属性数据
public AbstractBeanDefinition parseBeanDefinitionElement(
        Element ele, String beanName, BeanDefinition containingBean) {
    // 记录解析的 
    this.parseState.push(new BeanEntry(beanName));
    // 这里只读去  元素中配置的 class 名字, 然后载入到 BeanDefinition 中去
    String className = null;
    // 解析 Class 属性
    if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
        className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
    }

    try {
        String parent = null;
        // 如果  元素中配置了 parent属性, 则获取parent 属性的值
        if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
            parent = ele.getAttribute(PARENT_ATTRIBUTE);
        }
        // 创建用于承载属性的 AbstractBeanDefinition 类型的 GenericBeanDefinition
        AbstractBeanDefinition bd = createBeanDefinition(className, parent);
        // 这里对当前的 Bean 元素进行属性的解析, 并设置 description 的信息 (注意是 bean 标签的, 比如 scope, abstract, lazy-init, init-method, destroy-method 等)
        parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
        bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
        
        // 对  元素的 mate(元信息)属性解析
        parseMetaElements(ele, bd);
        // 对  元素的 loopup-method 属性解析
        parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
        // 对  元素的 replaced-method 属性解析
        parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
        // 解析  元素的构造方法
        parseConstructorArgElements(ele, bd);
        // 解析  元素的  属性
        parsePropertyElements(ele, bd);
        // 解析  元素的 qualifier 属性
        parseQualifierElements(ele, bd);

        // 为当前解析的 Bean 设置所需要的资源和依赖对象
        bd.setResource(this.readerContext.getResource());
        bd.setSource(extractSource(ele));

        return bd;
    }
    catch (Throwable ex) {
        error("Unexpected failure during bean definition parsing", ele, ex);
    }
    finally {
        this.parseState.pop();
    }

    // 解析元素出错返回 null
    return null;
}

(PS: 这里都是标签解析部分, 所以详细说了)
而对应那些非默认命名空间的标签的解析, 主要是通过命名空间解析类找到对应的 NamespaceHandler 来进行解析

6. 非默认命名空间标签解析

这一部分就相对简单了, 根据节点获取 namespaceUri, 然后获取对应的 NamespaceHandler, 接着就行相应解析

// 实现对非默认命名空间节点的通用解析框架 (PS 此处的 containingBd 默认为 null)
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
    // 获取命名空间
    String namespaceUri = getNamespaceURI(ele);
    // 从 map 集合中获取 Namespacehandler 接口
    NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
    if (handler == null) {
        error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
        return null;
    }
    // 调用统一的解析接口
    return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

这时xml中描述的bean信息已经被解析成 BeanDefinition, 注入到 BeanFactory 中(PS: 注入的统一入口 BeanDefinitionRegistry.registerBeanDefinition), 紧接着就是Bean的获取(PS: 到现在Bean还未生成, 容器中存在的只是 bean 的描述信息 BeanDefinition, 只有在 BeanFactory.getBean()时才会进行一次创建, Bean一旦创建好, 就会缓存在容器中)

7. getBean中创建Bean的主逻辑

到这里其实就是刚刚执行了最上面demo中的 4行代码, 完成了 xml 文件中Bean的解析, 解析成了BeanDefinition, 并且注册到了 BeanDefinitionRegistry 中(但是我的 bean 还没生成呢, 何时生成呢, 其实就是 beanFactory.getBean() 方法里面)

String resourceName = "org/springframework/beans/factory/xml/application.xml";
// 最基本的 IOC 工厂 DefaultListableBeanFactory
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// 配置Bean依赖文件
Resource resource = new ClassPathResource(resourceName);
// 使用 XML 读取器读取 xml 里面的信息, 并且设置到 BeanFactory 中
new XmlBeanDefinitionReader(factory).loadBeanDefinitions(resource);

而整个创建的过程很复杂, 大体上分为以下几步:

1. 通过 transformedBeanName 来获取BeanName(PS:  若传来的是 别名 alias,  则通过 transformedBeanName获取对应的真实 BeanName)
2. 通过 getSingleton 从缓存中取是否已经有被创建过的单例类型的 bean, 而 getSingleton 中又分成两部
   a. 若 signletonObjects 中已经存在对象, 则直接返回
   b. 若 bean被提早暴露了(就是通过 ObjectFactory 进行提早暴露, 以解决 循环引用) , 则直接通过 ObjectFactory.getObject 返回对象(PS: 这个 ObjectFactory 是在 AbstractAutowireCapableBeanFactory.doCreateBean 中的 add SingletonFactory 中将 包裹实例化了的Bean的 ObjectFactory 加入到 singletonFactories 中)
3. 若 getSingleton 返回了对象, 则直接通过 getObjectForBeanInstance 来获取真实的对象(PS: 对, 刚才 getSingleton 返回的对象有可能是 FactoryBean, 所以还需要通过 FactoryBean的getObject来获取真实的对象, 而这时还会在 这个对象上运用所有 BeanPostProcessor.postProcessAfterInitialization)
4. 这里有个判断, 若BeanDefinition是原型模式, 并且已经在创建中, 则直接报异常(PS: 这里表明若原型模式的 Bean需要一个创建好之后才能再次创建)
5. 若此时发现本 BeanFactory 中不存在 BeanDefinition, 而 parentBeanFactory 中存在对应的BeanDefinition, 则将类的创建交给 parentBeanFactory 来创建
6. 若 BeanDefinition有parentClass 的设置, 则获取parentClass的BeanDefinition, 并合并到本类对应的 BeanDefinition
7. 这时来到 Bean 的创建, 根据 BeanDefinition 是 singleton, prototype, 与其他 scope 来分别处理, 最后基本上也是交给 getObjectForBeanInstance 来获取真实的 Bean(上面获取的bean可能是 FactoryBean, 而不是真正需要的 Bean), 
8. 最后将对象返回到上层

这里可以看一下下面主逻辑的代码

// 参考资料 http://www.cnblogs.com/ITtangtang/p/3978349.html
// 正真实现向 Ioc 容器获取 Bean 的功能, 也是触发依赖注入功能的地方
@SuppressWarnings("unchecked")
protected  T doGetBean(
        final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)
        throws BeansException {

    // 获取真实的 beanName的名称(PS: 如果name是别名, 将别名转换为规范的 Bean 名称)
    final String beanName = transformedBeanName(name);
    Object bean;

    // spring创建bean原则: 不等 bean 创建完成就会将 包装bean的ObjectFactory对象提早暴露出来, 主要是解决循环依赖问题, 这样一旦下一个类创建时,若需要查找依赖类, 则可以通过 ObjectFactory 来提前获取引用
    // 先从缓存中取是否已经有被创建过的单例类型的 bean, 对于单例模型的 Bean 整个 Ioc 容器中只创建一次, 不需要重复创建
    // Eagerly check singleton cache for manually registered singletons.
    Object sharedInstance = getSingleton(beanName);
    // 如果能从缓存中获得已缓存的单例 bean, 并且参数 args == null (args默认就是 null), 那么直接返回缓存中的 bean, 否则继续创建 bean
    if (sharedInstance != null && args == null) {
        if (logger.isDebugEnabled()) {
            // 如果指定名称的单例 Bean, 在创建过程中, 则打印以下日志信息
            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 + "'");
            }
        }
        // 返回对应的实例, 可能存在是 FactoryBean 的情况, 返回的是 通过 Factorybean 创建的 bean 实例(如果 beanName 的命名是 &开头或sharedInstance不是Factorybean, 那么返回的是 sharedInstance 实例) (PS: BeanFactory 是管理容器中的 Bean 的工厂, 而 FactoryBean 是 创建对象的工厂 bean)
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }
    else { // 若 不能在缓存中找到 单例 bean, 则执行下面的逻辑
        /**
         * 只有单例模式下, 才能尝试解决循环依赖, 原型模式下, 直接抛出异常 BeanCurrentlyInCreationException
         * 什么是循环依赖, 例如 A 中有B 属性, B 中也有 A 属性,但是 A 还未创建完成时, 会先去创建B, 但是创建B的时候又要先去创建 A, 造成循环依赖
         */
        // 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进行检查, 首先检查是否
         * 能在当前的 BeanFactory 中获取的所有需要的 bean, 如果不能则委托当前容器的
         * 父级容器去查找, 如果还是找不到则沿着容器的继承体系向父级容器查找
         */
        // Check if bean definition exists in this factory.
        BeanFactory parentBeanFactory = getParentBeanFactory();
        // 如果当前工厂 AbstractBeanFactory 存在父级 beanFactory,且当前 AbstractBeanFactory 不存在 bean 定义(BeanDefinition), 则把创建 bean 的职责交给父级 Beanfactory
        // 当前容器的父级容器存在, 其当前容器中不存在指定名称的 Bean
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // 解析指定的 bean 名称的原始名称 (其实就是, 若name最前面是$符号, 则还是返回代 $符号的name)
            // Not found -> check parent.
            String nameToLookup = originalBeanName(name);
            // delegate 到 beanFactory 中寻找
            if (args != null) {
                // Delegation to parent with explicit args.
                // 委派父级容器根据指定名称和显示的参数查找
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else {
                // 委派父级容器根据指定名称和类型查找
                // No args -> delegate to standard getBean method.
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
        }

        if (!typeCheckOnly) { // (PS: 默认 false)
            // 把指定的 beanName 记录到 alreadyCreated Map 中(缓存), 表明该 beanName 已经创建过, 或即将创建 (beanFactory 用此来优化 beanName 重复创建)
            markBeanAsCreated(beanName);
        }

        try {
            /**
             * 将存储 XML 配置文件的 GenericBeanDefinition 转换成 RootBeanDefinition, 若有 parentName 属性, 则将parentName对应的 BeanDefinition属性合并到自己的 BeanDefinition 属性上
             * 为什么要将 GenericBeanDefinition 转化为 RootbeanDefinition 是因为:
             * 从 XML 配置文件中读取到的 Bean 信息是存储到 GenericbeanDefinition 中, 但是
             * 所有 Bean 后续处理都是针对 RootBeanDefinition 的, 所以这里需要做一个转换
             */
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);

            // 获取当前的 Bean 所依赖 Bean(PS: 一般 dependsOn 都为 null, 很少通过dependsOn来实现依赖注入)
            // 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 + "'");
                    }
                    // 把 bean 依赖的信息缓存起来
                    registerDependentBean(dep, beanName);   // 缓存依赖调用
                    // 递归调用 getBean 方法, 获取当前 Bean 的依赖的 Bean
                    getBean(dep);
                }
            }


            // 创建单例模式的 Bean 实例对象
            // 这里通过 createBean 方法创建 singleton bean 的实例, ObjectFactory中有一个会调函数 getObject, 会在 getSingleton 中会触发 ObjectFactory -> getObject() -> 最后到这里的 createBean()
            // Create bean instance.
            if (mbd.isSingleton()) { // 如果是 singleton
                sharedInstance = getSingleton(beanName, new ObjectFactory() { // 这里使用一个匿名内部类ObjectFactory
                    @Override
                    public Object getObject() throws BeansException {
                        try {
                            // 调用 AbstractBeanFactory 的实现类 AbstractAutowireCapablebeanFactory 中的 createBean 方法
                            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.
                            // 显示的从容器单例模式 Bean 缓存中清除实例对象
                            destroySingleton(beanName);
                            throw ex;
                        }
                    }
                });
                // 获取给定 Bean 实例对象 (PS: 若 sharedInstance 是 FactoryBean, 则会调用 FactoryBean.getObject 来返回对应的对象)
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }
            // Ioc 容器创建原型模式 bean 实例对象
            else if (mbd.isPrototype()) {           // 如果是prototype
                // 原型模式(Prototype) 是每次都会创建一个新的对象
                // 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 的原型对象已经创建成功 (PS: prototypesCurrentlyInCreation.remove())
                    afterPrototypeCreation(beanName);
                }
                // 获取给定 Bean 实例对象 (PS: 若 sharedInstance 是 FactoryBean, 则会调用 FactoryBean.getObject 来返回对应的对象)
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }
            /**
             *  要创建的 bean 即不是单例模式, 也不是原型模式, 则根据 bean 定义资源中
             *  配置的生命周期范围, 选择实例化 Bean 的合适方法, 这种在 Web 应用程序中
             *  比较常用: 如: request, session, application 等生命周期
             */
            else {      // 指定的scope 上实例化 bean
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                // bean 定义资源中没有配置生命周期的范围, 则 Bean 定义不合法
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                }
                try { // 这里又使用一个匿名内部类, 获取一个指定生命周期范围的实例
                    Object scopedInstance = scope.get(beanName, new ObjectFactory() {
                        @Override
                        public Object getObject() throws BeansException {
                            beforePrototypeCreation(beanName);
                            try {
                                return createBean(beanName, mbd, args);
                            }
                            finally {
                                afterPrototypeCreation(beanName);
                            }
                        }
                    });
                    // 获取给定 Bean 实例对象 (PS: 若 sharedInstance 是 FactoryBean, 则会调用 FactoryBean.getObject 来返回对应的对象)
                    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 实例化类型 (PS: 默认 requiredType都是 null)
    // Check if required type matches the type of the actual bean instance.
    if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
        try {
            return getTypeConverter().convertIfNecessary(bean, requiredType);
        }
        catch (TypeMismatchException ex) {
            if (logger.isDebugEnabled()) {
                logger.debug("Failed to convert bean '" + name + "' to required type '" +
                        ClassUtils.getQualifiedName(requiredType) + "'", ex);
            }
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    }
    return (T) bean;
}
 
 

上述代码中涉及到了以下几点:

1. IOC容器中, 在创建/获取Bean时都是获取最终的 beanName来进行操作(因为其中涉及到 beanName 对应的 alias)
2. Spring使用过提前将创建的对象通过 ObjectFactory进行提早暴露来支持单例模式的循环引用
3. 在创建Bean时主要分为 singleton, prototype, 与其他 scope 来创建 bean, 最终还会 通过 getObjectForBeanInstance 来获取最终的 Bean (主要因为 FactoryBean 这个对象存在, 而 FactoryBean 的存在主要是将一些需要复杂的创建方法才能创建出来类时, 通过一个统一创建方法(这些统一创建方法存在于 FactoryBean中)来创建)
4. 整个创建过程中涉及了多个模版方法, AbstractBeanFactory 中存在的是创建 Bean 的主逻辑(比如 createBean方法)
8. singleton 模式 Bean 的创建主逻辑

下面是 singleton 模式Bean的创建主逻辑, 主要有以下几点

1. 通过对singletonObjects加上 synchronized 关键字, 来使整个创建Bean的过程一个一个进行
2. 在创建 bean 前, 在 singletonsCurrentlyInCreation 加入正在创建 Bean 的beanName
3. 通过 objectFactory.getObject -> 来触发 createBean 来创建Bean
4. 在创建 bean 结束后, 会删除正在创建 Bean 时存留在 singletonsCurrentlyInCreation, singletonFactories 中的信息, 并将最终创建的对象放入 singletonObjects 中

详细的代码如下:

public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
    Assert.notNull(beanName, "'beanName' must not be null");
    synchronized (this.singletonObjects) {                                          // 这里面的 synchronized 非常重要, 有了 synchronized 说明, 单例对象可以按照顺序的添加到 singletonObjects
        // 首先检查对应的 bean 是否已经加载过了, 因为 singleton 模式其实就是复用以创建的 bean
        Object singletonObject = this.singletonObjects.get(beanName);
        // 如果为空才可以进行 singleton 的 bean 的初始化
        if (singletonObject == null) {
            if (this.singletonsCurrentlyInDestruction) {                // 在这个单例正在销毁时, 不允许, 单例的创建
                throw new BeanCreationNotAllowedException(beanName,
                        "Singleton bean creation not allowed while 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 + "'");
            }
            // 下面一步非常重要 通过 this.singletonsCurrentlyInCreation.add(beanName) 将当前正要创建的 bean 记录到缓存中, 这样可以对循环依赖进行检测
            beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet();
            }
            try { // 正真创建 Bean 的地方, 这里会回调 createBean 方法
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            }
            catch (IllegalStateException ex) {   
            }
            finally {
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = null;
                } // 当 bean 记载结束后需要移除缓存中对该 bean 的正在加载状态的记录
                afterSingletonCreation(beanName);
            }
            if (newSingleton) {
                // 将结果记录值缓存中, 并删除加载 bean 过程中所记录的各种辅助状态(比如提早暴露的类名, 以及提早暴露的单例工厂)
                addSingleton(beanName, singletonObject);
            }
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }
}
9. singleton 模式 Bean 的创建逻辑 (一)

代码的主逻辑如下:

1. 通过 resolveBeanClass方法来获取要生成的 Bean的 class 属性
2. 通过 BeanPostProcessor.postProcessBeforeInstantiation 来实例化对象, 若这里创建aop对象成功的话, 则直接返回对象(比如 AbstractAutoProxyCreator 中配置了customTargetSourceCreators, 则就能创建 aop 对象)
3. 若上面没有创建 aop 对象成功, 则调用正真类创建方法 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;

        // 根据设置的 class 属性或者根据 classname 来解析 Class
        // 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);
        }

        // 校验和准备 bean 中覆盖的方法
        // Prepare method overrides.
        try {
            mbdToUse.prepareMethodOverrides();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                    beanName, "Validation of method overrides failed", ex);
        }

        try {
            // 给 beanPostProcessor 一个机会来返回代理来代替正真的实例 (PS: 这个是在 类的实例化前的 前置方法postProcessBeforeInstantiation中创建对象,
            // 比如说: 你在 AbstractAutoProxyCreator 中设置了 customTargetSourceCreators后, 就会通过这个方法返回代理对象)
            // 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 的调用 (PS: Spring中正真做事的方法名前缀一般都是 do 开头)
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isDebugEnabled()) {
            logger.debug("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
10. singleton 模式 Bean 的创建逻辑 (二)
1. 根据指定的 bean 使用对应的策略创建新的实例, 如: 工厂方法, 构造函数自动注入, 简单初始化
2. 调用 PostProcessor 后置处理器, 这里主要是合并通过 注解修饰表示的依赖关闭进行收集以下(比如 AnnotatedAwareBeanPostProcess 收集 @Autowired, @Value 注解)
3. 判断是否需要提早曝光: 单例 & 允许循环依赖 & 当前 bean 正在创建中, 则通过 ObjectFactory 暴露出去
   为解决后面循环依赖, 可以在 bean 初始化完成前将 bean包裹于ObjectFactory中, 暴露到 singletonFactories里面
4. 初始化Bean, 这里主要涉及以下:
   4.1 通过 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation 来判断是否要配置依赖属性
   4.2 通过 InstantiationAwareBeanPostProcessor.postProcessPropertyValues 来解决 注解配置的依赖属性
   4.3 通过 applyPropertyValues 解决 Bean 的配置信息及依赖属性
5. 在完成对 Bean 的生成和依赖注入以后, 进行Bean初始化方法的调用
   5.1 bean 初始化前置方法的调用 (BeanPostProcessor.postProcessBeforeInitialization, 比如 ApplicationContextAware 中对aware接口的触发)
   5.2 初始化方法 InitializingBean.afterPropertiesSet 与在 xml 中配置的 init-method 方法的触发
   5.3 bean 初始化前置方法的调用 (BeanPostProcessor.postProcessAfterInitialization, 比如 AspectJAwareAdvisorAutoProxyCreator通过 aop 命名空间生成 aop 对象, AnnotationAwareAspectJAutoProxyCreator 中通过 AspectJ 注解生成 aop 对象)
6. 若对象是 singleton, 则包装成 DisposableBeanAdapter, 放入disposableBeans 中

代码如下:

// 真正创建 bean 的方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
        throws BeanCreationException {

    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    // 如果是 Singleton 则先把缓存中的同名 Bean 清除(原型模式下次创建时, 可能有些属性就不一样了)
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    // 这里是创建 Bean 的地方, 由 createBeanInstance 来完成
    if (instanceWrapper == null) {
        // 根据指定的 bean 使用对应的策略创建新的实例, 如: 工厂方法, 构造函数自动注入, 简单初始化
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    } // 获取实例化对象
    final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
    // 获取实例化对象的类型
    Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
    mbd.resolvedTargetType = beanType;

    // 调用 PostProcessor 后置处理器, 这里主要是合并通过 注解修饰表示的依赖关闭进行收集以下(比如 AnnotatedAwareBeanPostProcess 收集 @Autowired, @Value 注解)
    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);                                               // 对典型的是 AutowiredAnnotationBeanPostProcessor 中用于手机 自动装配的信息
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Post-processing of merged bean definition failed", ex);
            }
            mbd.postProcessed = true;
        }
    }

    // 是否需要提早曝光: 单例 & 允许循环依赖 & 当前 bean 正在创建中, 则通过 ObjectFactory 暴露出去
    // 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");
        }
        // 为解决后面循环依赖, 可以在 bean 初始化完成前将 bean包裹于ObjectFactory中, 暴露到 singletonFactories里面
        addSingletonFactory(beanName, new ObjectFactory() {
            @Override
            public Object getObject() throws BeansException {
                // AOP对象的提早暴露 ,主要应用 SmartInstantiationAwareBeanPostProcessor中, 若这里的对象被其他对象依赖, 并且针对这个对象会创建aop对象, 则对应的 aop 对象会在 getEarlyBeanReference中提早创建
                // 这里也就解决了 对象在初始化之前提早暴露与创建 aop 对象的关系
                return getEarlyBeanReference(beanName, mbd, bean);
            }
        });
    }

    // 这里是对 Bean 初始化, 依赖注入往往在这里发生, 这个 exposedObject 在初始化处理完成以后会返回 作为依赖注入完成以后的 Bean
    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        /** 1. 通过 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation 来判断是否要配置依赖属性
         *  2. 通过 InstantiationAwareBeanPostProcessor.postProcessPropertyValues 来解决 注解配置的依赖属性
         *  3. 通过 applyPropertyValues 解决 Bean 的配置信息及依赖属性
         */
        populateBean(beanName, mbd, instanceWrapper);
        if (exposedObject != null) {
            /** 在完成对 Bean 的生成和依赖注入以后
             *  1. bean 初始化前置方法的调用 (BeanPostProcessor.postProcessBeforeInitialization, 比如 ApplicationContextAware 中对aware接口的触发)
             *  2. 初始化方法 InitializingBean.afterPropertiesSet 与在 xml 中配置的 init-method 方法的触发
             *  3. bean 初始化前置方法的调用 (BeanPostProcessor.postProcessAfterInitialization, 比如 AspectJAwareAdvisorAutoProxyCreator通过 aop 命名空间生成 aop 对象,
             *       AnnotationAwareAspectJAutoProxyCreator 中通过 AspectJ 注解生成 aop 对象)
             */
            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) {
        // 获取 指定名称的已注册的且是提早暴露的 单例模式 Bean 对象
        Object earlySingletonReference = getSingleton(beanName, false);
        // earlySingletonReference 只有在检测到有循环依赖的情况下才不会为空
        if (earlySingletonReference != null) {
            // 如果 exposedObject 没有在初始化方法中被改变, 也就是没有被增强, 直接将提早暴露的 earlySingletonReference 赋值给 exposedObject
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { // exposedObject != Bean, bean 已经变成 aop 对象了, 且 这个条件 hasDependentBean(beanName) 一般不满足
                String[] dependentBeans = getDependentBeans(beanName); // (PS: 现在很少用 dependentBeans 放依赖的对象了)
                Set actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                /**
                 * 因为 bean 创建后其所依赖的 bean 一定是已经创建的
                 * 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 {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}
 
 
11. singleton 模式 Bean 的创建逻辑 (三)

这里主要还是进行 Bean 的依赖属性的注入

1. 通过 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation判断是否需要进行下面的属性配置
2. 若 beanDefinition.autowireMode是 AUTOWIRE_BY_NAME/AUTOWIRE_BY_TYPE 则相应的进行依赖属性的查找+注入
3. 通过 InstantiationAwareBeanPostProcessor.postProcessPropertyValues 来将 注解在类属性上的依赖配置进行查找到+设置进去(比如 AnnotationAwareBeanPostProcessor 处理 @Autowire 或 @Value)
4. 通过 applyPropertyValues 来设置 xml 里面配置的其他一般属性

代码如下

// 将 Bean 属性设置到生成的实例对象上
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
    // 这里取得在 BeanDefinition 中设置的 property值, 这些 property 来自对 BeanDefinition的解析
    PropertyValues pvs = mbd.getPropertyValues();
    // 实例对象为 null
    if (bw == null) {
        if (!pvs.isEmpty()) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
        }
        else {
            // 没有任何属性可以填充, 直接返回
            // Skip property population phase for null instance.
            return;
        }
    }

    // 给 InstantiationAwareBeanPostProcessor 最后依次机会在属性设置前来改变 bean的属性设置
    // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
    // state of the bean before properties are set. This can be used, for example,
    // to support styles of field injection.
    boolean continueWithPropertyPopulation = true;

    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                // 在 Bean 实例化之后 的后处理器(PS: 这里若返回 false 将阻止其后的 InstantiationAwareBeanProcessor 执行)
                if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    continueWithPropertyPopulation = false;
                    break;
                }
            }
        }
    }
    // 如果后处理器发出停止填充命令则终止后续的执行
    if (!continueWithPropertyPopulation) {
        // 如果上面的 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation 返回 false, 则
        // 1. 系统中的InstantiationAwareBeanPostProcessor就不会执行;
        // 2 接下来也不会对 Bean  进行属性的注入 (PS: 这里的属性注入是指通过 XML 格式的属性注入)
        return;
    }
    // 依赖注入开始, 首先处理 autowire 自动装配的注入 (PS: 默认 AUTOWIRE_NO)
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
            mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
        // 对 autowire 自动装配的处理, 根据 Bean 名称自动装配注入
        // Add property values based on autowire by name if applicable.
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }
        // 对 autowire 自动装配的处理, 根据 Bean 类型自动装配注入
        // Add property values based on autowire by type if applicable.
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }

        pvs = newPvs;
    }
    // 检查容器是否持有 实例化后置处理器 InstantiationAwareBeanPostProcessors
    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    // Bean 实例对象没有依赖, 即没有继承的基类
    boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

    if (hasInstAwareBpps || needsDepCheck) {
        // 从实例对象中提取属性描述符
        PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        if (hasInstAwareBpps) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    // 使用 BeanPostProcessor 处理器处理属性值(比如 AnnotationAwareBeanPostProcessor 处理 @Autowire 或 @Value)
                    pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);               
                    if (pvs == null) {
                        return;
                    }
                }
            }
        }
        if (needsDepCheck) {
            // 依赖检查, 对应 depends-on 属性, 3.0 已经弃用此属性
            // 为要设置的属性进行依赖检查
            checkDependencies(beanName, mbd, filteredPds, pvs);
        }
    }
    // 将属性应用到 bean 中
    // 对属性进行注入
    applyPropertyValues(beanName, mbd, bw, pvs);
}

在进行依赖属性设置好后, 接着就是 Bean 的初始化部分, 而这里, 又分为 初始化前置方法, 初始化方法, 初始化后置方法

12. singleton 模式 Bean 的创建逻辑 (四)

下面主要还是初始化方法的调用, 有 初始化前置方法, 初始化方法, 初始化后置方法

1. 直接激活一些aware 接口
2. 通过 beanProcessor.postProcessBeforeInitialization 来做一些初始化方法前的工作, 比如 ApplicationContextAwareProcessor 来激活一些 aware 接口
3. 通过 beanProcessor.postProcessAfterInitialization 来完成一些 bean 属性或bean对象本身的一些修改操作(比如 AspectJAwareAdvisorAutoProxyCreator通过 aop 命名空间生成 aop 对象, AnnotationAwareAspectJAutoProxyCreator 中通过 AspectJ 注解生成 aop 对象)

见代码如下

// 初始化容器创建的 Bean 实例对象, 为其添加 BeanPostProcessor后置处理器
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    // JDK 的安全机制验证权限
    if (System.getSecurityManager() != null) {
        // 实现 PrivileegedAction 接口的匿名内部类
        AccessController.doPrivileged(new PrivilegedAction() {
            @Override
            public Object run() {
                invokeAwareMethods(beanName, bean);
                return null;
            }
        }, getAccessControlContext());
    }
    else {
        // 对特殊的处理器 Aware接口, 如 BeanClassLoaderAware, BeanFactoryAware
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    // 对 BeanPostProcessor 初始化前置处理方法 postProcessBeforeInitialization 的调用, 为 bean 初始化前做些准备工作(比如 ApplicationContextAwareProcessor 来激活 aware 接口)
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    /**
     * 调用 Bean 的初始化方法, 这个初始化方法在 BeanDefinition 中通过定义 init-method 属性指定的同时
     * 如果 Bean 实现了 InitializingBean 接口, 那么这个 Bean 的 afterPropertiesSet 实现也会被调用
     */
    try {
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                (mbd != null ? mbd.getResourceDescription() : null),
                beanName, "Invocation of init method failed", ex);
    }
    // 对 beanPostProcessor 后置处理器的 postProcessAfterInitialization 回调方法的调用
    // aop对象的创建就在这里, 比如 AspectJAwareAdvisorAutoProxyCreator通过 aop 命名空间生成 aop 对象, AnnotationAwareAspectJAutoProxyCreator 中通过 AspectJ 注解生成 aop 对象
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}
 
 

这时让我们再回到 AbstractBeanFactory.doGetBean中, 这时bean已经创建好了, 但这时返回的对象可能是 FactoryBean, 还需要通过 getObjectFromFactoryBean 来返回最真实的对象

13. singleton 模式 Bean --> 获取最真实的 Bean 实例

这里再 AbstractBeanFactory.getObjectForBeanInstance 来进行操作:

1. 若beanName是以 & 开始, 或上面获取的对象是 FactoryBean 时才真进行下面的获取操作
2. 尝试从缓存中获取已经创建的对象
3. 通过 FactoryBean.getObject来获取最终的对象
4. 判断上面所产生的对象是否需要初始化方法的后置方法的处理(其实就是 beanProcessor.postProcessAfterInitialization)

到这里为止, BeanFactory创建Bean已经完成

14. prototype 模式 Bean 主逻辑

首先说一下, 单例模式的 Bean 与 singleton 模式差不多, 以下以两者的区别来叙述:

1. 在创建 prototype 模式Bean之前, 会在prototypesCurrentlyInCreation设置以下现在正在创建的类名(PS: 想一想是不是在前面是否有个判断: 在原型bean创建bean时, 你同时再创建Bean, 会直接报异常)
2. 接着就和 singleton Bean创建一样
3. 然后消除一下 prototypesCurrentlyInCreation中的信息
4. 最后通过 getObjectForBeanInstance 来返回最终的 Bean (PS: 上面返回的对象可能是 FactoryBean)

其他一些 Scope 的 Bean, 其实就是在创建好 Bean 之后将 Bean 放置到 ServletContext, ThreadLocal, TransactionSynchronizationManager的ScopedObjectsHolder 中, 整个创建过程非常相似! 至此 BeanFactory 收集 BeanDefinition, 创建 Bean 的过程就叙述OK了!

15. IOC 之 Bean 的生命周期

到这里我们可以大体总结了一下 IOC 中Bean的生命周期, 主要流程如下:

1. 收集 bean 描述信息
    1.1 通过 XMLBeanDefinitionReader 读取 xml 信息, 封装成 GenericBeanDefinition 注册到 BeanFactory 里面
        或 扫描指定目录下的所有类, 并将符合要求的类封装成 BeanDefinition, 并注册到 BeanFactory 里面
    1.2 若遇到 特殊的命名空间, 则获取对应的 NamespaceHandler 来进行解析(PS: 如 MVC, TX, AOP 等)

2. 生成 bean
    2.1 调用 BeanFactoryPostProcessor 来处理 BeanDefinition 里面的 ${占位符号}
    2.2 调用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation (实例化前置函数) 来生成对象
        postProcessBeforeInstantiation 主要是当程序中设置了 自定义的 customTargetSourceCreators 时创建 对应 Bean 的代理
    2.3 通过反射生成对应的 bean 
    2.4 调用 MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition 来收集 Bean 里面的描述信息 
        (比如 
                AutowiredAnnotationBeanPostProcessor 收集 Autowired, Value 标注的属性/方法;
                CommonAnnotationBeanPostProcessor 收集 PostConstruct, PreDestroy 标注的方法;
        )
    2.5 判断 bean 是否允许提早暴露+循环引用, 若是的话, 则直接将 bean 封装到 ObjectFactory 对象中
    2.6 调用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation (实例化后置函数) 
        这个方法返回 true/false, 来决定是否将 XML 配置的 Bean 的属性运用到 Bean 上, 或 配置被 Autowired/Value 修饰的属性
    2.7 调用 BeanPocessor.postProcessBeforeInitialization (初始化前置方法)
        最常见的设置 Bean 实现的各种 Aware 方法就是通过 ApplicationContextAwareProcessor 来实现的
    2.8 初始化 bean 的初始方法, 主要是两部分(1. XML 里面配置的 init 方法; 2. InitializingBean接口的afterPropertiesSet 方法)
    2.9 调用 BeanProcessor.postProcessAfterInitialization 方法
        Spring 中的 AOP 很多时候就是通过这个初始化后置方法实现代理类, 如 AnnotationAwareAspectJAutoProxyCreator(基于 Aspect 注解)
        AspectJAwareAdvisorAutoProxyCreator(直接解析  配置的信息)
    2.10 将 Bean 封装成 DisposableBeanAdapter 装入到 能销毁的Bean 的 Map 中
16. 总结:

本篇叙述了 BeanDefinition 的收集(主要集中在 xml 中配置信息的收集), Bean 的创建! 涉及的代码量比较大, 需要持续深入的看源代码(当时自己也是查看了很多源码分析的blog/书籍), 而其中最重要的几点应该是如下:

1. Spring 对公共事务/事件的抽象,  比如 
   所有描述资源抽象成 Resource, 
   所有BeanDefinition设计了顶层方法 BeanDefinitionReader(不同的资源有不同策略的实现子类)
   BeanFactory根据功能及特点分层设计接口及实现类
2. 自定义命名空间(NamespaceHandler)的使用, 我们默认的都是使用 BeanDefinitonParserDelegate来进行解析, 若碰到其他命名空间的标签, 则获取对应的NamespaceParser 来进行解析
3. 大量工厂模式, 抽象工厂模式, 模版模式, 策略模式, 监听器模式, 单例模式, 原型模式, 模版模式(这个非常重要), 建造者模式,  ThreadLocal 的使用
4. Bean 生命周期的理解, 其中涉及 BeanPostProcessor 及其子类
5. 动态代理 AOP 的实现方式, 及原理
17. 参考资料

Spring技术内幕分析
Spring IOC 原理
Spring 5 源码分析
开涛的 Spring杂谈
伤神的 Spring源码分析
Spring Core
Spring IOC 源码分析
Spring源码情操陶冶
Spring 揭秘 (PS: 这本书绝对给力)
Spring 技术内幕
Spring 源码深度分析
Spring 高级程序设计 (PS:这本书已经绝版, 所以当时是自己下载 pdf, 然后联系淘宝卖家忙帮复印, 其实就是英文版本的 "Pro Spring 3")
深入分析 Java Web(PS: 许令波写的, 虽然是本老书, 但是里面分析得确实很深入)
expert one-on-one J2EE Development without EJB (PS: Spring 作者自己写的书, 当时也是下载 PDF, 联系淘宝卖家复印购买到的)

你可能感兴趣的:(Spring 4.3 源码分析之 IOC 基本容器启动)