`
young-2017
  • 浏览: 9496 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

spring加载xml配置文件的源码分析

阅读更多
1 将资源文件封装成Resource
     如Resource re = new ClassPathResource("");

2. 将加载好的资源文件 通过XmlBeanFactory初始化

public class XmlBeanFactory extends DefaultListableBeanFactory {

	private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
	
	public XmlBeanFactory(Resource resource) throws BeansException {
		this(resource, null);
	}

       /**  该方法为资源加载的真正实现*/
	public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
		super(parentBeanFactory);
		this.reader.loadBeanDefinitions(resource);
	}

}



3.加载bean
 
   @Override
	public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
		return loadBeanDefinitions(new EncodedResource(resource));
	}

首先使用EncodedResource对resource进行封装,当设置了编码属性,spring会使用相应的编码作为输入流的编码
private EncodedResource(Resource resource, String encoding, Charset charset) {
		super();
		Assert.notNull(resource, "Resource must not be null");
		this.resource = resource;
		this.encoding = encoding;
		this.charset = charset;
	}

public Reader getReader() throws IOException {
		if (this.charset != null) {
			return new InputStreamReader(this.resource.getInputStream(), this.charset);
		}
		else if (this.encoding != null) {
			return new InputStreamReader(this.resource.getInputStream(), this.encoding);
		}
		else {
			return new InputStreamReader(this.resource.getInputStream());
		}
	}


上述代码构建好了一个有编码的InputStreamReader
下面这个方法才是真正的数据准备阶段
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		Assert.notNull(encodedResource, "EncodedResource must not be null");
		if (logger.isInfoEnabled()) {
			logger.info("Loading XML bean definitions from " + encodedResource.getResource());
		}

		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
		if (currentResources == null) {
			currentResources = new HashSet<EncodedResource>(4);
			this.resourcesCurrentlyBeingLoaded.set(currentResources);
		}
		if (!currentResources.add(encodedResource)) {
			throw new BeanDefinitionStoreException(
					"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
		}
		try {
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
                               /**真正的核心逻辑**/
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}
			finally {
				inputStream.close();
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"IOException parsing XML document from " + encodedResource.getResource(), ex);
		}
		finally {
			currentResources.remove(encodedResource);
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
			}
		}
	}

//通过属性记录已经加载的资源,放入Threadlocal变量中
	private final ThreadLocal<Set<EncodedResource>> resourcesCurrentlyBeingLoaded =new NamedThreadLocal<Set<EncodedResource>>("XML bean definition resources currently being loaded");


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

protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
		return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
				getValidationModeForResource(resource), isNamespaceAware());
	}

//获取验证模式(DTD XSD两种验证模式)
protected int getValidationModeForResource(Resource resource) {
		int validationModeToUse = getValidationMode();
                 //如果手动指定了验证模式则使用指定的验证模式
		if (validationModeToUse != VALIDATION_AUTO) {
			return validationModeToUse;
		}
                //没有指定 则使用自动检测
		int detectedMode = detectValidationMode(resource);
		if (detectedMode != VALIDATION_AUTO) {
			return detectedMode;
		}
		// Hmm, we didn't get a clear indication... Let's assume XSD,
		// since apparently no DTD declaration has been found up until
		// detection stopped (before finding the document's root tag).
		return VALIDATION_XSD;
	}


public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		int countBefore = getRegistry().getBeanDefinitionCount();
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

此段代码 主要做了三件事:
     获取对xml文件的验证模式
     加载xml文件,并得到对应的Document
     根据返回的Document注册Bean的信息




分享到:
评论

相关推荐

    spring源码分析(1-10)

    1. **Spring 事务处理**:Spring 提供了声明式事务管理,允许开发者在配置文件中定义事务边界,无需在业务逻辑代码中显式控制事务开始、提交和回滚。它主要基于AOP代理来实现,通过TransactionInterceptor拦截器进行...

    spring famework xml配置使用示例

    通过这个"spring framework xml配置使用示例",你可以学习到如何使用XML配置文件来设置Spring环境,管理Bean,以及处理Bean之间的依赖关系。在实际开发中,虽然现在的趋势是使用Java配置和注解,但理解XML配置仍然是...

    spring配置文件模板

    源码分析是理解Spring配置文件的另一个重要途径。Spring框架是开源的,我们可以通过阅读源码来了解其内部工作原理。例如,`ApplicationContext`接口和其实现类如`ClassPathXmlApplicationContext`,它们负责加载和...

    spring 个人小结 源码分析机制原理

    Spring提供多种实例化Bean的方式,这里以`XmlBeanFactory`为例,通过`FileSystemResource`加载XML配置文件,然后通过`getBean`方法获取Bean实例。在`getBean`内部,会根据Bean定义创建并初始化Bean对象,包括执行...

    Spring源码分析

    以上只是Spring源码分析的部分内容,实际源码中还包括Spring的其他模块,如Spring Batch(批处理)、Spring Security(安全)、Spring Integration(集成)等。理解并掌握Spring源码,有助于我们更好地利用Spring...

    Spring源码分析_Spring_IOC

    ### Spring源码分析_Spring_IOC:深入理解Spring的IOC容器机制 #### 基本概念与核心作用 在探讨Spring框架的核心组件之一——IOC(Inversion of Control,控制反转)容器之前,首先需要理解它在Spring框架中的角色...

    spring-framework-1.0-m1.zip源码

    1. 依赖注入:在Spring 1.0中,DI是通过XML配置文件实现的,它允许开发者声明组件间的依赖关系,而不是在代码中硬编码。这样,对象的创建和管理由Spring容器负责,提高了代码的可测试性和可维护性。 2. 控制反转:...

    spring security源码分析.pdf

    ### Spring Security 源码分析知识点 #### 一、Spring Security 概述 Spring Security 是一个强大且可高度定制的身份验证和访问控制框架。它提供了许多功能,包括登录表单、记住密码、CSRF 保护等。为了更好地理解...

    spring 2.0使用AOP实例(基于XML的配置方式)

    最后,我们可以通过`src`目录下的源代码来进一步了解具体的实现细节,例如切面类、被通知的方法以及相关的XML配置文件。通过对这些内容的分析和实践,你可以深入理解Spring 2.0中AOP的概念及其XML配置方式,从而在...

    Spring 3.0就这么简单源码Maven的jar包001

    首先,Spring 3.0的一大亮点是增强了对Java 5和6的支持,引入了基于注解的配置,大大减少了XML配置文件的数量和复杂性。开发者可以使用如`@Autowired`、`@Service`、`@Repository`和`@Controller`等注解,直接在类或...

    spring源码包.zip

    通过对这些模块的源码分析,我们可以深入了解Spring如何实现其强大的功能,并能更好地运用到实际项目中,提升代码质量和可维护性。无论是新手还是经验丰富的开发者,理解Spring的源码都将是一次宝贵的进阶之旅。

    spring 源码分析

    1. 创建一个用于加载XML配置文件的抽象资源对象ClassPathResource,这里的配置文件名为beans.xml。 2. 创建一个BeanFactory实现类DefaultListableBeanFactory的实例。 3. 创建一个XmlBeanDefinitionReader实例,并将...

    Spring加载XSD文件发生错误的解决方法

    Spring加载XSD文件发生错误的解决方法 在使用 Spring 框架时,可能会遇到加载 XSD 文件发生错误的问题,本文将对此问题进行详细的分析和解决。 问题描述 在使用 Spring 框架时,可能会出现 org.xml.sax....

    spring加载

    1. **配置文件解析**:Spring的启动通常始于一个或多个配置文件,如XML或Java配置类。这些配置文件定义了bean的定义,包括bean的类型、属性、依赖关系等。Spring通过BeanDefinitionReader读取这些配置,将其转化为...

    三、Spring源码分析——ApplicationContext

    《Spring源码分析——ApplicationContext》 在Java世界中,Spring框架是不可或缺的一部分,它以其强大的IoC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)特性,极大地...

    Object-XML文件的相互转换分析

    Spring的XML配置文件是其核心特性之一,它允许开发者用XML来声明和配置bean及其依赖关系。在Spring中,`BeanUtils`类提供了基本的对象-XML转换功能,而`XmlBeanDefinitionReader`则负责读取XML配置文件并创建bean...

    spring-source-4.2.4源码

    SpEL允许在配置文件或代码中动态地访问和修改对象属性,这对于依赖注入和条件逻辑的实现至关重要。 `spring-webmvc-4.2.4.RELEASE-sources`是Spring MVC的实现,它是Spring框架用于构建Web应用的核心模块。通过源码...

    Spring2(源码)

    - 容器通过XML配置文件、Java配置类或基于注解的方式获取Bean的定义信息。 5. **Spring MVC** - Spring MVC是Spring框架的一部分,用于构建Web应用程序,提供模型-视图-控制器(MVC)架构。 - DispatcherServlet...

Global site tag (gtag.js) - Google Analytics