天天看點

(Spring源碼分析)XmlBeanFactory容器

先来看一个简单使用Spring的Demo

  • BuildTest
    public class BuildTest {
    	@Test
    	public void testBean(){
    		BeanFactory beanFactory=new XmlBeanFactory(new ClassPathResource("spring-context.xml"));
    		TestBean testBean=(TestBean) beanFactory.getBean("testBean");
    		System.out.println(testBean.getStr());
    	}
    }
               
  • TestBean
    public class TestBean {
    	private String str = "Hello Spring";
    
    	public String getStr() { return str; }
    
    	public void setStr(String str) { this.str = str;}
    }
               
  • spring-context.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    	<bean id="testBean" class="com.wyj.learning.build.bean.TestBean"/>
    
    </beans>
               
    这是一个使用Spring的很简单的一个Demo,但是它包含从xml配置文件中读取bean信息注册到Spring容器中、解析xml中不同的标签、bean的加载、bean的获取等一系列Spring容器初始化到从Spring容器中获取bean操作
  • 使用XmlBeanFactory初始化Spring IOC容器,XmlBeanFactory是一个很基础的Spring容器,虽然在Spring3.1开始已经不建议使用了

在上面一段代码中

ClassPathResource

主要作用是加载指定的xml配置文件

  • 先来看一下

    ClassPathResource

    初始化的源码

/**
 * 先是调用ClassPathResource(String path)带参构造方法
 */
public ClassPathResource(String path) {
    this(path, (ClassLoader) null);
}

/**
 * 调用ClassPathResource(String path, @Nullable ClassLoader classLoader)带参构造方法
 */
public ClassPathResource(String path, @Nullable ClassLoader classLoader) {
    Assert.notNull(path, "Path must not be null"); // 对xml的路径进行判断是否为null
    String pathToUse = StringUtils.cleanPath(path); // 用来处理路径中的'\','/'
    if (pathToUse.startsWith("/")) {
        pathToUse = pathToUse.substring(1);
    }
    this.path = pathToUse; // path为xml配置文件的路径
    this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader()); // 初始化classLoader
}
           

看完源码发现初始化

ClassPathResource

就做了两件事:获取xml配置文件的路径和初始化classLoader

  • 再来看

    XmlBeanFactory

    初始化的源码

/**
 * 先是调用XmlBeanFactory(Resource resource)带参构造方法,参数为Resource初始化过后的对象
 */
public XmlBeanFactory(Resource resource) throws BeansException {
    this(resource, null);
}

/**
 * 调用XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory)带参构造方法
 */
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
    super(parentBeanFactory); // 调用父类DefaultListableBeanFactory构造方法初始化
    this.reader.loadBeanDefinitions(resource); // spring初始化资源加载的真正实现
}
           

此时在

XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory)

构造方法中有两行代码:

super(parentBeanFactory)

:用来初始化父类

this.reader.loadBeanDefinitions(resource)

:spring初始化资源加载的真正实现

  • 看看

    super(parentBeanFactory)

    的源码

/**
 * 先是调用DefaultListableBeanFactory(@Nullable BeanFactory parentBeanFactory)带参构造方法
 */
public DefaultListableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
    super(parentBeanFactory);
}

/**
 * 调用父类AbstractAutowireCapableBeanFactory中AbstractAutowireCapableBeanFactory(@Nullable BeanFactory parentBeanFactory)带参构造方法
 */
public AbstractAutowireCapableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
    this(); // 调用本类无参构造方法初始化
    setParentBeanFactory(parentBeanFactory);
}

/**
 * 调用AbstractAutowireCapableBeanFactory()无参构造方法
 */
public AbstractAutowireCapableBeanFactory() {
    super(); // 调用父类抽象类AbstractBeanFactory的无参构造方法,里面是空实现
    ignoreDependencyInterface(BeanNameAware.class);
    ignoreDependencyInterface(BeanFactoryAware.class);
    ignoreDependencyInterface(BeanClassLoaderAware.class);
}

/**
 * 这里调用了三次该方法,该方法主要功能是添加需要忽略指定接口实现类的自动装配
 */
public void ignoreDependencyInterface(Class<?> ifc) {
    this.ignoredDependencyInterfaces.add(ifc);
}


/**
 * 这是parentBeanFactory,在初始化XmlBeanFactory容器的时候parentBeanFactory为null,,所以最后parentBeanFactory为null
 */
@Override
public void setParentBeanFactory(@Nullable BeanFactory parentBeanFactory) {
    if (this.parentBeanFactory != null && this.parentBeanFactory != parentBeanFactory) {
        throw new IllegalStateException("Already associated with parent BeanFactory: " + this.parentBeanFactory);
    }
    this.parentBeanFactory = parentBeanFactory;
}
           

看完

super(parentBeanFactory)

的源码发现就做了两件事:获取添加需要忽略指定接口实现类的自动装配和初始化parentBeanFactory,但是在XmlBeanFactory容器初始化的时候parentBeanFactory为null

  • 在看

    this.reader.loadBeanDefinitions(resource)

    的源码之前先来看一下reader的初始化

// 作为成员变量定义在XmlBeanFactory中,this代表当前XmlBeanFactory对象
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);

/**
 * 先是调用XmlBeanDefinitionReader(BeanDefinitionRegistry registry)带参构造方法
 */
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
    super(registry);
}

/**
 * 调用父类AbstractBeanDefinitionReader中AbstractBeanDefinitionReader(BeanDefinitionRegistry registry)带参构造方法
 */
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    this.registry = registry;

    // 确定要使用的registry是否是ResourceLoader的实现类来初始化resourceLoader
    if (this.registry instanceof ResourceLoader) {
        this.resourceLoader = (ResourceLoader) this.registry;
    }
    else {
        this.resourceLoader = new PathMatchingResourcePatternResolver();
    }

    // 初始化
    if (this.regenvironmentistry instanceof EnvironmentCapable) {
        this.environment = ((EnvironmentCapable) this.registry).getEnvironment();
    }
    else {
        this.environment = new StandardEnvironment();
    }
}
           

看完

private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this)

的源码,里面仅仅只是对resourceLoader和environment进行了初始化

  • 再来看

    this.reader.loadBeanDefinitions(resource)

    的源码

/**
 * 先是调用DefaultListableBeanFactory(@Nullable BeanFactory parentBeanFactory)带参构造方法
 */
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    return loadBeanDefinitions(new EncodedResource(resource));
}

/**
 * 调用EncodedResource中EncodedResource(Resource resource)构造方法初始化EncodedResource对象
 */
public EncodedResource(Resource resource) {
    this(resource, null, null);
}

/**
 * 调用EncodedResource(Resource resource, @Nullable String encoding, @Nullable Charset charset)来初始化resource、encoding和charset
 */
private EncodedResource(Resource resource, @Nullable String encoding, @Nullable Charset charset) {
    super(); // 空实现
    Assert.notNull(resource, "Resource must not be null");
    this.resource = resource;
    this.encoding = encoding;
    this.charset = charset;
}

/**
 * 从xml配置文件中加载bean,主要是调用doLoadBeanDefinitions(inputSource, encodedResource.getResource())方法来实现的
 */
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);
    }

    Set<EncodedResource> 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 inputStream = encodedResource.getResource().getInputStream();
        try {
            InputSource inputSource = new InputSource(inputStream);
            if (encodedResource.getEncoding() != null) {
                inputSource.setEncoding(encodedResource.getEncoding());
            }
            return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); // 真正实现从xml配置文件加载bean
        }
        finally {
            inputStream.close();
        }
    }
    catch (IOException ex) {
        throw new BeanDefinitionStoreException(
            "IOException parsing XML document from " + encodedResource.getResource(), ex);
    }
    finally {
        currentResources.remove(encodedResource);
        if (currentResources.isEmpty()) {
            this.resourcesCurrentlyBeingLoaded.remove();
        }
    }
}

/**
 * 真正实现从xml配置文件加载bean
 */
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
    throws BeanDefinitionStoreException {
    try {
        Document doc = doLoadDocument(inputSource, resource); // 这里是从xml配置文件中获取Document
        return registerBeanDefinitions(doc, resource); // 解析并注册bean
    }
    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配置文件中解析出来的Document对象来解析并注册bean
 */
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    // 使用DefaultBeanDeFinitionDocumentReader实例化BeanDefinitionDocumentReader
    // 在实例化BeanDefinitionReader时候会将BeanDefinitionRegister传入,默认使用继承自DefaultListableBeanFactory的子类
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    // 记录统计前BeanDefinition的加载个数
    int countBefore = getRegistry().getBeanDefinitionCount();
    // 加载及注册bean
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    // 记录本次加载的BeanDefinition个数
    return getRegistry().getBeanDefinitionCount() - countBefore;
}

/**
 * 获取xml配置文件中的root
 */
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    this.readerContext = readerContext;
    logger.debug("Loading bean definitions");
    Element root = doc.getDocumentElement(); // 获取root,以便再次将root作为参数继续BeanDefinition的注册
    doRegisterBeanDefinitions(root); // 继续解析root
}

/**
 * 根据xml配置文件中的<beans/>定义来解析每一个bean
 */
protected void doRegisterBeanDefinitions(Element root) {
    BeanDefinitionParserDelegate parent = this.delegate;
    this.delegate = createDelegate(getReaderContext(), root, parent);

    if (this.delegate.isDefaultNamespace(root)) {
        String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); // 对profile环境进行处理
        if (StringUtils.hasText(profileSpec)) {
            String[] specifiedProfiles = StringUtils.tokenizeToStringArray( // 获取profile字符串数组
                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); // 对xml配置文件的读取
    postProcessXml(root); // 解析后处理,留给子类实现

    this.delegate = parent;
}

/**
 * 对xml配置文件的读取,解析文档中根级别的元素import、alias、bean
 */
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    // 对beans的处理
    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); // 对bean、beans、alias、import元素标签的处理
                }
                else {
                    // 对bean的处理
                    delegate.parseCustomElement(ele);
                }
            }
        }
    }
    else {
        delegate.parseCustomElement(root);
    }
}

/**
 * 对bean、beans、alias、import元素标签的处理
 */
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    // public static final String IMPORT_ELEMENT = "import";
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { // 当节点为import时
        importBeanDefinitionResource(ele);
    }
    // public static final String ALIAS_ELEMENT = "alias";
    else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { // 当节点为alias时
        processAliasRegistration(ele);
    }
    // public static final String BEAN_ELEMENT = "bean"
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { // 当节点为bean时
        processBeanDefinition(ele, delegate);
    }
    // public static final String NESTED_BEANS_ELEMENT = "beans";
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // 当节点为beans时
        // recurse
        doRegisterBeanDefinitions(ele);
    }
}
           

繼續閱讀