spring源码学习(一)

DefaultListableBeanFactory是bean加载的核心部分,是Spring注册和加载bean的默认实现。
DefaultListableBeanFactory的层次结构。
spring源码学习(一)_第1张图片

自己画了个uml图如下:
spring源码学习(一)_第2张图片

AliasRegistry接口:定义对alias的增删改查

SimpleAliasRegistry类:对AliasRegistry接口进行了实现,用map来存alias
spring源码学习(一)_第3张图片

SingletonBeanRegistry接口:定义了单例的注册和获取

BeanFactory接口:定义了获取bean以及获取bean的各种属性

DefaultSingletonBeanRegistry类:对SingletonBeanRegistry接口进行了实现

HierarchicalBeanFactory接口:增加了对parentBean的支持。

BeanDefinitionRegistry:定义了对BeanDefinition的增删改查

FactoryBeanRegistrySupport:增加了对FactoryBeand的处理。

ConfigurableBeanFactory接口:提供了配置Factory的各种方法

ListableBeanFactory接口:根据各种条件获取bean的配置清单

AbstractBeanFactory类:综合了ListableBeanFactory和ConfigurableBeanFactory的功能

AutowireCapableBeanFactory接口:定义了bean的创建,自动注入,初始化以及应用bean后的处理

AbstractAutowireCapableBeanFactory类:对AutowireCapableBeanFactory接口进行实现,综合了AbstractBeanFactory和AutowireCapableBeanFactory的功能

ConfigurableListableBeanFactory接口:BeanFactory的配置清单

DefaultListableBeanFactory类:综合了全部功能

XmlBeanFactory继承DefaultListableBeanFactory,主要增加了通过xml文档来去读BeanDefinition,而注册和获取都是通过DefaulListableBeanFactory来实现的。
spring源码学习(一)_第4张图片
XmlBeanFactory源码增加了XmlBeanDefinitionReader来读取Resource之后通过this.reader.loadBeanDefinitions来读取解析xml文档并注册。

因为XmlBeanFactory接受的参数是Resuorce类型的,所以要用new ClassPathResource来将目标文件转换为Resuorce类型。

接下来我进入loadBeanDefinitions方法,发现传入的Resource先被封装为了EncodedResource类,然后在另一个重载方法中获取对应的InputStrom并构造InputSource,然后将InputSource调用doLoadBeanDefinitions方法来进行解析。
在doLoadBeanDefinitions里将Resource转换为了Document,然后根据Document注册Bean信息。
spring源码学习(一)_第5张图片
进入doLoadDocument方法里,我们能看到里面调用了getValidationModeForResource方法,这个方法是来验证xml是否符合dtd或者xsd中定义的格式的。
doLoadDocument

到这里我们可以做一个小测试:
applicationContext.xml

  
<beans  
    xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns:p="http://www.springframework.org/schema/p"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">    

    <bean id="hello" class="springtest.MyTestBean"/>  
beans> 

MyTestBean.java

public class MyTestBean {

    private String teststr = "hello world";

    public String getTeststr() {
        return teststr;
    }

    public void setTeststr(String teststr) {
        this.teststr = teststr;
    }


}

BeanFactoryTest.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class BeanFactoryTest {

    public static void main(String[] args) throws IOException {
        XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
        System.out.println("BeanFactory中Bean的数量:"+xmlBeanFactory.getBeanDefinitionCount());
        String[] bdNames = xmlBeanFactory.getBeanDefinitionNames();
        for(String str: bdNames)
            System.out.println("bean的名字:"+str);
        MyTestBean bean = (MyTestBean)xmlBeanFactory.getBean("hello");
        System.out.println(bean.getTeststr());
    }

}

运行后的结果:
result

如此简单的代码,在spring中其实是非常复杂的,上面分析的只是粗略的看了比较顶层的源码,接下来会继续分析更深层的代码。

上层代码的逻辑大概是:将文件转换为resource类型传入XmlBeanFactory中,XmlBeanFactory使用XmlBeanDefinitionReader中的loadBeanDefinitions来分析解析和注册bean,在loadBeanDefinitions中调用doLoadBeanDefinitions方法来验证资源文件并转换为Document类型,然后根据Document来进行Bean的解析和注册。

建议大家搭建环境,自己进去看看,不然很难弄清楚的。

你可能感兴趣的:(spring源码学习)