本篇内容介绍了“Spring实现读取配置文件的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beanFactory.xml")); public class XmlBeanFactory extends DefaultListableBeanFactory { //核心代码,XmlBeanFactory中使用了自定义的XmlBeanDefinitionReader读取XML文件 XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this); public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory){ //读取XML配置文件的核心代码 this.reader.loadBeanDefinitions(resource); } }
加载资源文件可以使用Spring提供的类,如
Resource resource = new ClassPathResource("beanFactory.xml"); //getInputStream是在InputStreamResource中定义的唯一方法,它也是Spring对资源封装的最上层接口 InputStream inputStream = resource.getInputStream();
public interface InputStreamSource { InputStream getInputStream() throws IOException; } public interface Resource extends InputStreamSource { boolean exists(); boolean isReadable(); boolean isOpen(); URL getURL() throws IOException; URI getURI() throws IOException; File getFile() throws IOException; long contentLength() throws IOException; long lastModified() throws IOException; Resource createRelative(String relativePath) throws IOException; String getFilename(); String getDescription(); }
当使用new ClassPathResource
将资源文件封装为Resource
之后,就可以使用XmlBeanDefinitionReader
来读取配置文件。
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beanFactory.xml")); public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory){ this.reader.loadBeanDefinitions(resource); } public int loadBeanDefinitions(Resource resource){ //EncodedResource主要用于对资源文件的编码处理的 return loadBeanDefinitions(new EncodedResource(resource)); } public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { //通过Set来记录已经加载的资源,它是放在ThreadLocal中 Set<EncodedResource> currentResources = resourcesCurrentlyBeingLoaded.get(); if (currentResources == null) { currentResources = new HashSet<EncodedResource>(4); //放入ThreadLocal中 this.resourcesCurrentlyBeingLoaded.set(currentResources); } if (!currentResources.add(encodedResource)) { throw new BeanDefinitionStoreException(); } try { //获取文件输入流,上面已经分析过 InputStream inputStream = encodedResource.getResource().getInputStream(); try { InputSource inputSource = new InputSource(inputStream); if (encodedResource.getEncoding() != null) { inputSource.setEncoding(encodedResource.getEncoding()); } //真正进入读取的逻辑核心部分,此处传入的inputSource是org.xml.sax.InputResource,用于sax解析 return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); } } protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource){ try { //步骤1,获取XML文件的验证模式,Spring用来校验验证模式的方法就是判断是否包含DOCTYPE,如果包含就是DTD,否则就是XSD int validationMode = getValidationModeForResource(resource); //步骤2,加载XML文件,并得到对应的Document Document doc = this.documentLoader.loadDocument( inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware()); //步骤3,根据返回的Document注册Bean信息 return registerBeanDefinitions(doc, resource); } } //步骤2 public Document loadDocument(InputSource inputSource, EntityResolver entityResolver, ErrorHandler errorHandler, int validationMode, boolean namespaceAware){ //SAX解析XML文档,返回Document对象 DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware); DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler); return builder.parse(inputSource); } //步骤3 public int registerBeanDefinitions(Document doc, Resource resource) { BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); //设置环境变量 documentReader.setEnvironment(this.getEnvironment()); //记录之前BeanDefinition中定义的Bean的数量 int countBefore = getRegistry().getBeanDefinitionCount(); documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); //返回本次加载的BeanDefinition个数 return getRegistry().getBeanDefinitionCount() - countBefore; }
documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext){ this.readerContext = readerContext; //读取的根元素,debug时显示为[beans: null] Element root = doc.getDocumentElement(); doRegisterBeanDefinitions(root); } protected void doRegisterBeanDefinitions(Element root) { //处理profile元素,profile标签可以用于配置生产环境、开发环境等 String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec)) { Assert.state(this.environment != null, "Environment must set for evaluating profiles"); String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); if (!this.environment.acceptsProfiles(specifiedProfiles)) { return; } } //专门处理解析的代理 BeanDefinitionParserDelegate parent = this.delegate; this.delegate = createDelegate(this.readerContext, root, parent); //此处的两个方法为空实现,面向继承设计,这是模板方法模式,子类可以继承并在解析前做一些处理 preProcessXml(root); parseBeanDefinitions(root, this.delegate); postProcessXml(root); this.delegate = parent; } protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { 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)) { //解析默认标签,如bean parseDefaultElement(ele, delegate); } else { //解析自定义标签,如<aop:aspectj-autoproxy/> delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }
“Spring实现读取配置文件的方法”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。