spring源码-1- xml的加载与注册
来源:互联网 发布:淘宝千人千面影响 编辑:程序博客网 时间:2024/06/12 18:48
Resource resource = new ClassPathResource("classpath:spring/application.xml");
1.资源加载
ClassPathResource 分析
spring 框架提供bean的加载机制,定义在xml中注入的bean将被创建。通过构造方法 appalication.xml 资源加载 classPathResource -》Resource其它方法 1. getPath 获取路径 2. getClassLoader 获取类加载器 3. exists 资源解析存在性 4. getInputStream 获取输入流 5. getURL 获取url 6. createRelative 创建相对资源路径 7. getDescription 获取clazz 类名 + path 信息
/** * classpath 下资源加载 */public class ClassPathResource extends AbstractFileResolvingResource { private final String path; //jvm 类加载器 private ClassLoader classLoader; private Class<?> clazz; public ClassPathResource(String path) { this(path, (ClassLoader) null); } public ClassPathResource(String path, ClassLoader classLoader) { Assert.notNull(path, "Path must not be null"); //整理classpath 路径 (.. // prefix 等) String pathToUse = StringUtils.cleanPath(path); if (pathToUse.startsWith("/")) { pathToUse = pathToUse.substring(1); } this.path = pathToUse; this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader()); }
StringUtils cleanPath(path) 源码解析
clanPath 是对path路径的一个简单处理。
/** * 例1 classpath:spring/application.xml * 例2 http://blog.csdn.net/csdn_ygy */ public static String cleanPath(String path) { if (path == null) { return null; } //WINDOWS_FOLDER_SEPARATOR = "\\" FOLDER_SEPARATOR = "/" /** * 效果等同于String.replaceAll (使用StringBuffer) * 用StringBuilder效率更快 */ String pathToUse=replace(path, WINDOWS_FOLDER_SEPARATOR, FOLDER_SEPARATOR); int prefixIndex=pathToUse.indexOf(":"); String prefix=""; if (prefixIndex != -1) { prefix=pathToUse.substring(0, prefixIndex + 1); // classpath http if (prefix.contains("/")) { prefix=""; } else { // spring/application.xml /blog.csdn.net/csdn_ygy pathToUse=pathToUse.substring(prefixIndex + 1); } } if (pathToUse.startsWith(FOLDER_SEPARATOR)) { prefix=prefix + FOLDER_SEPARATOR; pathToUse=pathToUse.substring(1); // spring/application.xml blog.csdn.net/csdn_ygy } /** * 以/ 切割 String用正则且步骤繁琐, * 本方法采用Stringbuilder 效率较快 {"spring","application.xml"} */ String[] pathArray=delimitedListToStringArray(pathToUse, FOLDER_SEPARATOR); List<String> pathElements=new LinkedList<>(); int tops=0; for (int i=pathArray.length - 1; i >= 0; i--) { String element=pathArray[i]; //application.xml if (CURRENT_PATH.equals(element)) { } else if (TOP_PATH.equals(element)) { tops++; } else { if (tops > 0) { // Merging path element with element corresponding to top path. tops--; } else { // Normal path element found. pathElements.add(0, element); } } } // Remaining top paths need to be retained. for (int i=0; i < tops; i++) { pathElements.add(0, TOP_PATH); } return prefix + collectionToDelimitedString(pathElements, FOLDER_SEPARATOR); }
2.资源解析
XmlBeanFactory (已过时)
直接使用DefaultListableBeanFactory (主要是对bean 注册后的处理)以及XmlBeanDefinitionReader (资源文件读取 解析 及注册)
// 用于从xml中读取 beanDefinition@Deprecated@SuppressWarnings({"serial", "all"})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); //加载beanDefinition this.reader.loadBeanDefinitions(resource); }}
2.1资源解析-xml验证
XmlValidationModeDetector 源码分析(获取xml 后 ,对xml 约束文件解读 ,进行验证)
// 1 auto 2 dtd 3 xsd(schema) : xml 验证模式 public int detectValidationMode(InputStream inputStream) throws IOException { // Peek into the file to look for DOCTYPE. BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); try { boolean isDtdValidated = false; //是否是dtd String content; while ((content = reader.readLine()) != null) { // 判断是否为注释 <-- 注释设置 true "<-- xxxxxxxx" => xxxxxxxxxxxxx content = consumeCommentTokens(content); //如果读取的是注释 或者空则跳过 if (this.inComment || !StringUtils.hasText(content)) { continue; } if (hasDoctype(content)) { //dtd 标志 isDtdValidated = true; break; } if (hasOpeningTag(content)) { //是否含有 < // End of meaningful data... break; } } return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD); //dtd 或者xsd(schema) } catch (CharConversionException ex) { // Choked on some character encoding... // Leave the decision up to the caller. return VALIDATION_AUTO; //采取自动 } finally { reader.close(); //关闭资源 } }
2.2资源解析-解析为document
DefaultDocumentLoader源码分析
//xml -》 document -》 bean @Override // 资源 对象解析器 错误处理器 xml验证 xml命名空间 //由resourceLoader =》 获取public Document loadDocument(InputSource inputSource, EntityResolver entityResolver, ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception { // 命名空间 和 验证模式(dtd xsd) -》 DocumentBuilderFactory DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware); if (logger.isDebugEnabled()) { logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]"); } DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler); return builder.parse(inputSource); }
2.3资源解析-beandefinition 注册
XmlBeanDefinitionReader 分析(资源文件读取 解析 及注册)
** * 资源文件读取 解析 及注册 */public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader { //1.从xml中加载 beandefinition 返回注册的beandefinition 数量 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<>(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()); } //1.DocumentLoader 转化、解析document //2.新建 BeanDefinitionDocumentReader (//定义读取document 并注册beandefinition功能) 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(); } } }}//注册beandefinition 个数public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); int countBefore = getRegistry().getBeanDefinitionCount(); //已加载bean 个数 //加载及注册bean documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); //此次注册个数 return getRegistry().getBeanDefinitionCount() - countBefore; }
0 0
- spring源码-1- xml的加载与注册
- Spring源码学习-3.IoC.资源的加载与注册
- Spring IOC 源码分析-xml配置文件加载-注册
- spring Ioc源码解读-xml资源加载与解析
- Spring源码之旅(3)_BeanDefinition的解析与注册
- spring源码之XmlBeanDefinitionReader与bean的注册
- Spring源码学习MVC:HandlerMapping的注册与查找
- 【spring源码分析】--Bean的解析与注册
- Spring源码阅读之-bean的解析与注册
- Spring源码阅读之Bean加载(xml)1
- Spring源码阅读 之加载XML配置文件
- spring、mybatis加载xml源码解析
- Spring IOC 源码阅读资源加载和注册
- Spring IOC 源码阅读资源加载和注册
- Spring源码分析之配置文件加载并注册Bean
- spring 加载过程中lazy-init 的使用与源码
- Spring源码浅析 -- XML配置文件的载入与解析
- Spring源码浅析 -- XML配置文件的载入与解析
- 十三、JDK的命令行工具
- while(cin>>word) 分析
- vmware虚拟机ubuntu和red hat等vmware tools安装问题
- jq实现二级下拉菜单动画效果
- Spark源码分析之分区器的作用
- spring源码-1- xml的加载与注册
- JAVA 读取Properties配置文件
- springmvc之@InitBinder注解
- Visual Basic快捷教程——函数与子程序
- 【C#】String 格式化使用说明
- Hadoop启动报Error: JAVA_HOME is not set and could not be found解决办法
- VxWorks驱动程序开发指南--驱动程序的组织结构
- 理解进程调度时机跟踪分析进程调度与进程切换的过程
- Java高级深入与JVM