Spring IOC初始化2--加载BeanDefinition

Spring IOC 源码分析有三篇
Spring IOC 初始化1–定位
Spring IOC 初始化2–加载BeanDefinition
Spring IOC 初始化3–注册BeanDefinition

基于Spring 5.2.6.RELEASE
下面是第二步,载入Beandefinition
BeanDefinition的载入

//AbstractXmlApplicationContext#loadBeanDefinitions
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    //创建XmlBeanDefinitionReader,容器使用该读取器读取Bean定义资源
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
	//为beanDefinitionReader 设置环境
	beanDefinitionReader.setEnvironment(this.getEnvironment());
	//为beanDefinitionReader设置资源加载器
	beanDefinitionReader.setResourceLoader(this);
	//为Bean读取器设置解析器
	beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
	//当Bean读取器读取Bean定义的Xml资源文件时,启用Xml的校验机制
	initBeanDefinitionReader(beanDefinitionReader);
	//载入Beandefinition
	loadBeanDefinitions(beanDefinitionReader);
}

1、创建Beandefinition读取器

DefaultListableBeanFactory 实现了 BeanDefinitionRegistry,因此DefaultListableBeanFactory也是一个注册器

public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
    super(registry);
}

调用父构造器

private final BeanDefinitionRegistry registry;
private ResourceLoader resourceLoader;
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    this.registry = registry;

    // Determine ResourceLoader to use.
    //DefaultListableBeanFactory 没有实现 ResourceLoader
    if (this.registry instanceof ResourceLoader) {
        this.resourceLoader = (ResourceLoader) this.registry;
    }
    else {
        this.resourceLoader = new PathMatchingResourcePatternResolver();
    }

    // Inherit Environment if possible
    if (this.registry instanceof EnvironmentCapable) {
        this.environment = ((EnvironmentCapable) this.registry).getEnvironment();
    }
    else {
        this.environment = new StandardEnvironment();
    }
}

创建resourceLoader

private final ResourceLoader resourceLoader;
public PathMatchingResourcePatternResolver() {
    this.resourceLoader = new DefaultResourceLoader();
}
private ClassLoader classLoader;
public DefaultResourceLoader() {
    this.classLoader = ClassUtils.getDefaultClassLoader();
}
public static ClassLoader getDefaultClassLoader() {
    ClassLoader cl = null;
    try {
        cl = Thread.currentThread().getContextClassLoader();
    }
    catch (Throwable ex) {
        // Cannot access thread context ClassLoader - falling back...
    }
    if (cl == null) {
        // No thread context class loader -> use class loader of this class.
        cl = ClassUtils.class.getClassLoader();
        if (cl == null) {
            // getClassLoader() returning null indicates the bootstrap ClassLoader
            try {
                cl = ClassLoader.getSystemClassLoader();
            }
            catch (Throwable ex) {
                // Cannot access system ClassLoader - oh well, maybe the caller can live with null...
            }
        }
    }
    return cl;
}

2、加载BeanDefinition

//org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
	//获取Bean定义资源的定位	ClassPathXmlApplicationContext的这个为空
	Resource[] configResources = getConfigResources();
	if (configResources != null) {
		//Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位
		//的Bean定义资源
		reader.loadBeanDefinitions(configResources);
	}
	//上一篇构造器的第二步设置 configLocations	获取Bean的定位信息
	String[] configLocations = getConfigLocations();
	if (configLocations != null) {
		//Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位的BeanDefinition
		reader.loadBeanDefinitions(configLocations);
	}
}

加载BeanDefinition并返回计数

//AbstractBeanDefinitionReader#loadBeanDefinitions
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
	Assert.notNull(locations, "Location array must not be null");
	int counter = 0;
	for (String location : locations) {
		counter += loadBeanDefinitions(location);
	}
	return counter;
}
//org.springframework.beans.factory.support.AbstractBeanDefinitionReader#loadBeanDefinitions(java.lang.String)
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
	return loadBeanDefinitions(location, null);
}

//org.springframework.beans.factory.support.AbstractBeanDefinitionReader#loadBeanDefinitions
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
	//获取资源加载器	defaultResourceLoader
	ResourceLoader resourceLoader = getResourceLoader();
	if (resourceLoader == null) {
		throw new BeanDefinitionStoreException(
				"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
	}

	if (resourceLoader instanceof ResourcePatternResolver) {
		try {
			//将指定位置的Bean定义资源文件解析为Spring IOC容器封装的资源
			//加载多个指定位置的Bean定义资源文件
			Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
			//委派调用其子类XmlBeanDefinitionReader的方法,实现加载功能
			int loadCount = loadBeanDefinitions(resources);
			if (actualResources != null) {
				for (Resource resource : resources) {
					actualResources.add(resource);
				}
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
			}
			return loadCount;
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"Could not resolve bean definition resource pattern [" + location + "]", ex);
		}
	}
	else {
		//将指定位置的Bean定义资源文件解析为Spring IOC容器封装的资源
		//加载单个指定位置的Bean定义资源文件
		Resource resource = resourceLoader.getResource(location);
		//委派调用其子类XmlBeanDefinitionReader的方法,实现加载功能
		int loadCount = loadBeanDefinitions(resource);
		if (actualResources != null) {
			actualResources.add(resource);
		}
		if (logger.isDebugEnabled()) {
			logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
		}
		return loadCount;
	}
}

2.1、获取资源加载器

//org.springframework.beans.factory.support.AbstractBeanDefinitionReader#getResourceLoader
public ResourceLoader getResourceLoader() {
    return this.resourceLoader;
}

2.2、获取资源

//org.springframework.core.io.support.PathMatchingResourcePatternResolver#getResource
public Resource getResource(String location) {
    return getResourceLoader().getResource(location);
}

2.2.1、获取资源加载器
private final ResourceLoader resourceLoader;
//org.springframework.core.io.support.PathMatchingResourcePatternResolver#getResourceLoader
public ResourceLoader getResourceLoader() {
    return this.resourceLoader;
}

2.2.2、获取资源
//org.springframework.core.io.DefaultResourceLoader#getResource
public Resource getResource(String location) {
    Assert.notNull(location, "Location must not be null");

    for (ProtocolResolver protocolResolver : getProtocolResolvers()) {
        Resource resource = protocolResolver.resolve(location, this);
        if (resource != null) {
            return resource;
        }
    }

    if (location.startsWith("/")) {
        return getResourceByPath(location);
    }
    else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
        return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
    }
    else {
        try {
            // Try to parse the location as a URL...
            URL url = new URL(location);
            return (ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
        }
        catch (MalformedURLException ex) {
            // No URL -> resolve as resource path.
            return getResourceByPath(location);
        }
    }
}

2.3、加载BeanDefinition

//XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.Resource)
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
	return loadBeanDefinitions(new EncodedResource(resource));
}

2.3.1、创建EncodedResource
private final Resource resource;
@Nullable
private final String encoding;
@Nullable
private final Charset charset;
public EncodedResource(Resource resource) {
    this(resource, null, null);
}
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;
}

EncodedResource 保存了资源的编码信息

2.3.2、加载
private final ThreadLocal<Set<EncodedResource>> resourcesCurrentlyBeingLoaded =
    new NamedThreadLocal<Set<EncodedResource>>("XML bean definition resources currently being loaded"){
    @Override
    protected Set<EncodedResource> initialValue() {
        return new HashSet<>(4);
    }
};
//org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    Assert.notNull(encodedResource, "EncodedResource must not be null");
    if (logger.isTraceEnabled()) {
        logger.trace("Loading XML bean definitions from " + encodedResource);
    }

    Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();

    if (!currentResources.add(encodedResource)) {
        throw new BeanDefinitionStoreException(
            "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    }
	//将资源转为输入流
    try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
        InputSource inputSource = new InputSource(inputStream);
        if (encodedResource.getEncoding() != null) {
            inputSource.setEncoding(encodedResource.getEncoding());
        }
        //加载
        return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
    }
    catch (IOException ex) {
        throw new BeanDefinitionStoreException(
            "IOException parsing XML document from " + encodedResource.getResource(), ex);
    }
    finally {
        currentResources.remove(encodedResource);
        if (currentResources.isEmpty()) {
            this.resourcesCurrentlyBeingLoaded.remove();
        }
    }
}

具体的载入

//org.springframework.beans.factory.xml.XmlBeanDefinitionReader#doLoadBeanDefinitions
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
    try {
        //将输入流xml转为文档
        Document doc = doLoadDocument(inputSource, resource);
        //注册
        int count = registerBeanDefinitions(doc, resource);
        if (logger.isDebugEnabled()) {
            logger.debug("Loaded " + count + " bean definitions from " + resource);
        }
        return count;
    }
    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);
    }
}

2.3.2.1、加载document
private DocumentLoader documentLoader = new DefaultDocumentLoader();
//org.springframework.beans.factory.xml.XmlBeanDefinitionReader#doLoadDocument
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
	return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
			getValidationModeForResource(resource), isNamespaceAware());
}

2.3.2.1.1、获取实体解析器
//org.springframework.beans.factory.xml.XmlBeanDefinitionReader#getEntityResolver
protected EntityResolver getEntityResolver() {
	if (this.entityResolver == null) {
		// Determine default EntityResolver to use.
		ResourceLoader resourceLoader = getResourceLoader();
		if (resourceLoader != null) {
			this.entityResolver = new ResourceEntityResolver(resourceLoader);
		}
		else {
			this.entityResolver = new DelegatingEntityResolver(getBeanClassLoader());
		}
	}
	return this.entityResolver;
}

public ResourceEntityResolver(ResourceLoader resourceLoader) {
    super(resourceLoader.getClassLoader());
    this.resourceLoader = resourceLoader;
}

调用父构造器

public DelegatingEntityResolver(@Nullable ClassLoader classLoader) {
    this.dtdResolver = new BeansDtdResolver();
    this.schemaResolver = new PluggableSchemaResolver(classLoader);
}

创建了dtd和schema两个解析器

2.3.2.2.2、加载文档
//org.springframework.beans.factory.xml.DefaultDocumentLoader#loadDocument
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);
	//将spring的bean资源解析为文档
	return builder.parse(inputSource);
}

创建文档构建工厂

//org.springframework.beans.factory.xml.DefaultDocumentLoader#createDocumentBuilderFactory
protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware)
			throws ParserConfigurationException {

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(namespaceAware);

    if (validationMode != XmlValidationModeDetector.VALIDATION_NONE) {
        factory.setValidating(true);
        if (validationMode == XmlValidationModeDetector.VALIDATION_XSD) {
            // Enforce namespace aware for XSD...
            factory.setNamespaceAware(true);
            try {
                factory.setAttribute(SCHEMA_LANGUAGE_ATTRIBUTE, XSD_SCHEMA_LANGUAGE);
            }
            catch (IllegalArgumentException ex) {
                ParserConfigurationException pcex = new ParserConfigurationException(
                    "Unable to validate using XSD: Your JAXP provider [" + factory +
                    "] does not support XML Schema. Are you running on Java 1.4 with Apache Crimson? " +
                    "Upgrade to Apache Xerces (or Java 1.5) for full XSD support.");
                pcex.initCause(ex);
                throw pcex;
            }
        }
    }

    return factory;
}

创建文档构建器

//org.springframework.beans.factory.xml.DefaultDocumentLoader#createDocumentBuilder
protected DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory, @Nullable EntityResolver entityResolver, @Nullable ErrorHandler errorHandler) throws ParserConfigurationException {

    DocumentBuilder docBuilder = factory.newDocumentBuilder();
    if (entityResolver != null) {
        docBuilder.setEntityResolver(entityResolver);
    }
    if (errorHandler != null) {
        docBuilder.setErrorHandler(errorHandler);
    }
    return docBuilder;
}

2.3.2.2、生成BeanDefinition
//org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    //创建BeanDefinitionDocumentReader
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    //获得容器中注册的Bean数量	获取的是 DefaultListableBeanFactory#beanDefinitionMap 的 size
    int countBefore = getRegistry().getBeanDefinitionCount();
    //生成BeanDefinition并注册
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    //统计该次生成多少
    return getRegistry().getBeanDefinitionCount() - countBefore;
}

2.3.2.2.1、创建BeanDefinitionDocumentReader
private Class<? extends BeanDefinitionDocumentReader> documentReaderClass =
			DefaultBeanDefinitionDocumentReader.class;
//org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createBeanDefinitionDocumentReader
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
    return BeanUtils.instantiateClass(this.documentReaderClass);
}

这里创建了一个DefaultBeanDefinitionDocumentReader

2.3.2.2.2、创建ReaderContext
//org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createReaderContext
public XmlReaderContext createReaderContext(Resource resource) {
    return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
                                this.sourceExtractor, this, getNamespaceHandlerResolver());
}

这里创建了一个XmlReaderContext

private final XmlBeanDefinitionReader reader;
private final NamespaceHandlerResolver namespaceHandlerResolver;
public XmlReaderContext(
    Resource resource, ProblemReporter problemReporter,
    ReaderEventListener eventListener, SourceExtractor sourceExtractor,
    XmlBeanDefinitionReader reader, NamespaceHandlerResolver namespaceHandlerResolver) {

    super(resource, problemReporter, eventListener, sourceExtractor);
    this.reader = reader;
    this.namespaceHandlerResolver = namespaceHandlerResolver;
}

调用父构造器

private final Resource resource;
private final ProblemReporter problemReporter;
private final ReaderEventListener eventListener;
private final SourceExtractor sourceExtractor;
public ReaderContext(Resource resource, ProblemReporter problemReporter,
			ReaderEventListener eventListener, SourceExtractor sourceExtractor) {

    this.resource = resource;
    this.problemReporter = problemReporter;
    this.eventListener = eventListener;
    this.sourceExtractor = sourceExtractor;
}

public NamespaceHandlerResolver getNamespaceHandlerResolver() {
    if (this.namespaceHandlerResolver == null) {
        this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
    }
    return this.namespaceHandlerResolver;
}

protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
    ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader());
    return new DefaultNamespaceHandlerResolver(cl);
}

这里 创建了一个DefaultNamespaceHandlerResolver

2.3.2.2.3、读取资源生成BeanDefinition并注册
private XmlReaderContext readerContext;
//org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#registerBeanDefinitions
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    this.readerContext = readerContext;
    doRegisterBeanDefinitions(doc.getDocumentElement());
}

//org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions
protected void doRegisterBeanDefinitions(Element root) {
    // Any nested <beans> elements will cause recursion in this method. In
    // order to propagate and preserve <beans> default-* attributes correctly,
    // keep track of the current (parent) delegate, which may be null. Create
    // the new (child) delegate with a reference to the parent for fallback purposes,
    // then ultimately reset this.delegate back to its original (parent) reference.
    // this behavior emulates a stack of delegates without actually necessitating one.
    //BeanDefinition解析器,保存BeanDefinition
    BeanDefinitionParserDelegate parent = this.delegate;
    this.delegate = createDelegate(getReaderContext(), root, parent);
	//spring 默认的namespace
    if (this.delegate.isDefaultNamespace(root)) {
        String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
        if (StringUtils.hasText(profileSpec)) {
            String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            // We cannot use Profiles.of(...) since profile expressions are not supported
            // in XML config. See SPR-12458 for details.
            if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                                 "] not matching: " + getReaderContext().getResource());
                }
                return;
            }
        }
    }

    preProcessXml(root);
    parseBeanDefinitions(root, this.delegate);
    postProcessXml(root);

    this.delegate = parent;
}

//org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#getReaderContext
protected final XmlReaderContext getReaderContext() {
    Assert.state(this.readerContext != null, "No XmlReaderContext available");
    return this.readerContext;
}

创建BeanDefinition解析器

protected BeanDefinitionParserDelegate createDelegate(
    XmlReaderContext readerContext, Element root, @Nullable BeanDefinitionParserDelegate parentDelegate) {

    BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
    delegate.initDefaults(root, parentDelegate);
    return delegate;
}

private final XmlReaderContext readerContext;
public BeanDefinitionParserDelegate(XmlReaderContext readerContext) {
    Assert.notNull(readerContext, "XmlReaderContext must not be null");
    this.readerContext = readerContext;
}

2.3.2.2.3、解析BeanDefinition
//org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitions
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    //spring 默认的namespace
    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 {//自己的namespace
        delegate.parseCustomElement(root);
    }
}

//org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseDefaultElement
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
        importBeanDefinitionResource(ele);
    }
    else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
        processAliasRegistration(ele);
    }
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
        processBeanDefinition(ele, delegate);
    }
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
        // recurse
        doRegisterBeanDefinitions(ele);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值