本篇内容介绍了“Spring实现读取配置文件的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
1、XMLBeanFcatory

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);
}
}
2、配置文件封装
加载资源文件可以使用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();
}
3、加载资源文件
当使用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;
}
4、开始解析
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实现读取配置文件的方法”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注天达云网站,小编将为大家输出更多高质量的实用文章!