自己注册了个域名想做一个网站,怎么做简单的视频网站,技术博客 wordpress,一张图片切块做网站背景这一篇让我想起来学习 Spring 的时#xff0c;被 XML 支配的恐惧。明明是写Java#xff0c;为啥要搞个XML呢#xff1f;大佬们永远不知道#xff0c;我认为最难的是 XML 头#xff0c;但凡 Spring 用 JSON来做配置文件#xff0c;Java 界都有可能再诞生一个扛把子。
被 XML 支配的恐惧。明明是写Java为啥要搞个XML呢大佬们永远不知道我认为最难的是 XML 头但凡 Spring 用 JSON来做配置文件Java 界都有可能再诞生一个扛把子。
?xml version1.0 encodingUTF-8?那今天我就要来盘一下突破自己的心里障碍。把 Spring XML 的底裤都给扒掉最后会发现原来每个人的身上都有毛毛。
设计一下子
首先想想应该怎么设计这个模块BeanDefinitionRegistry 这个伙计是大门的保安把守着资源加载的大门。他的口头禅就是穿内裤者 或 不打领带者不得入内。 作为一个专业的前端后端运维测试攻城狮高内聚低耦合必须手到擒来面向接口编程更是基本操作。BeanDefinitionReader 接口就是我们的协议只要符合这个接口协议都能进入我们的大门。 这可是比武招亲严格多了你再有本事不按照规矩来那也是白搭。 BeanDefinitionReader 接口一放出去有两个年轻人三十多岁一个叫 XmlBeanDefinitionReader一个叫 ResouceLoader他们说要试试。这两个年轻人不知道天高地厚以为我的类图只有这么点。实际上我只是按照传统功夫的点到为止截图而已。 不仅如此我还有流程图。 上次我太将武德了右眼睛被人蹭了一下。今天我 18 岁老码农是乱打的类图流程图还有一个不知道什么图训练有素。现在我就是这么不讲武德来骗来偷袭年轻人。你们年轻人自己耗子尾汁。
实现一下子
首先我们来看看门面担当BeanDefinitionReader
public interface BeanDefinitionReader { void loadBeanDefinitions(String location) throws IOException;
}这家伙就一个方法简单得很但是别小看它这可是整个系统的总指挥
然后是我们的主角 XmlBeanDefinitionReader
public class XmlBeanDefinitionReader implements BeanDefinitionReader { private final BeanDefinitionRegistry beanDefinitionRegistry; public XmlBeanDefinitionReader(BeanDefinitionRegistry beanDefinitionRegistry) { this.beanDefinitionRegistry beanDefinitionRegistry; } Override public void loadBeanDefinitions(String location) throws IOException { ResourceLoader resourceLoader new DefaultResourceLoader(); loadBeanDefinitions(resourceLoader.getResource(location)); } private void loadBeanDefinitions(Resource resource) throws IOException { InputStream inputSteam resource.getInputSteam(); doLoadBeanDefinitions(inputSteam); } private void loadBeanDefinitions(Resource... resources) throws IOException { for (Resource resource : resources) { loadBeanDefinitions(resource); } } private void doLoadBeanDefinitions(InputStream inputStream) { Document document XmlUtil.readXML(inputStream); Element root document.getDocumentElement(); NodeList childNodes root.getChildNodes(); for (int i 0; i childNodes.getLength(); i) { Node item childNodes.item(i); if (!(item instanceof Element)) continue; if (!bean.equals(item.getNodeName())) continue; // bean 信息 Element element (Element) item; String id element.getAttribute(id); String name element.getAttribute(name); String className element.getAttribute(class); String beanName StrUtil.isNotBlank(id) ? id : name; Class? clazz; try { clazz Class.forName(className); } catch (ClassNotFoundException e) { throw new BeanException(e.getMessage()); } PropertyValues propertyValues new PropertyValues(); BeanDefinition beanDefinition new BeanDefinition(clazz, propertyValues); // properties 信息 NodeList propertyNodes element.getChildNodes(); for (int j 0; j propertyNodes.getLength(); j) { Node property propertyNodes.item(j); if (!(property instanceof Element)) continue; if (!property.equals(property.getNodeName())) continue; Element propertyElement (Element) property; String propertyName propertyElement.getAttribute(name); String value propertyElement.getAttribute(value); String ref propertyElement.getAttribute(ref); PropertyValue propertyValue; if (StrUtil.isNotBlank(ref)) { BeanReference beanReference new BeanReference(ref); propertyValue new PropertyValue(propertyName, beanReference); } else { propertyValue new PropertyValue(propertyName, value); } propertyValues.addPropertyValues(propertyValue); } // 注册 beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition); } }
}资源加载皮条哥就看你选的哪个小弟给你干活。目前他能 hold 住资源内容读取三兄弟。
public interface ResourceLoader { Resource getResource(String location);
}public class DefaultResourceLoader implements ResourceLoader { private final String CLASS_PATH_PREFIX classpath:; Override public Resource getResource(String location) { Objects.requireNonNull(location); if (location.startsWith(CLASS_PATH_PREFIX)) { String name location.substring(CLASS_PATH_PREFIX.length()); return new ClassPathResource(name, getClassLoader()); } try { URL url new URL(location); return new UrlResource(url); } catch (MalformedURLException e) { return new FileSystemResource(location); } } private ClassLoader getClassLoader() { ClassLoader contextClassLoader Thread.currentThread().getContextClassLoader(); if (contextClassLoader ! null) { return contextClassLoader; } return ClassUtil.class.getClassLoader(); }
}资源内容读取三兄弟
ClassPathResource专门找项目里的文件FileSystemResource负责找电脑里的文件UrlResource负责找网上的资源文件
public interface Resource { InputStream getInputSteam() throws IOException;
}public class ClassPathResource implements Resource { private final String name; private final ClassLoader classLoader; public ClassPathResource(String name, ClassLoader classLoader) { Objects.requireNonNull(name); this.name name; this.classLoader classLoader; } Override public InputStream getInputSteam() throws IOException { InputStream inputStream classLoader.getResourceAsStream(name); if (Objects.isNull(inputStream)){ throw new FileNotFoundException(Not found this file: name); } return inputStream; }
}public class FileSystemResource implements Resource { private final String path; private final File file; public FileSystemResource(String path) { this.path path; this.file new File(path); } Override public InputStream getInputSteam() throws IOException { return Files.newInputStream(file.toPath()); } public String getPath() { return path; }
}public class UrlResource implements Resource { private final URL url; public UrlResource(URL url) { this.url url; } Override public InputStream getInputSteam() throws IOException { URLConnection connection url.openConnection(); try { return connection.getInputStream(); } catch (IOException e) { if (connection instanceof HttpURLConnection) { ((HttpURLConnection) connection).disconnect(); } throw e; } }
}测试一下子
首先准备一张菜单吗告诉Spring
老板来一个testDao再来一个testService要加karl调料顺便把刚才的testDao也放进去
?xml version1.0 encodingUTF-8?
beans bean idtestDao classpri.hongweihao.smallspring.bean.TestDao/ bean idtestService classpri.hongweihao.smallspring.bean.TestService property namename valuekarl/ property nametestDao reftestDao/ /bean
/beans// 模拟dao对象
public class TestDao { public void test() { System.out.print(testDao); }
}// 模拟service对象
public class TestService { private final String name; private final TestDao testDao; public TestService(String name, TestDao testDao) { this.name name; this.testDao testDao; } public void test() { System.out.println(testService.name: this.name); this.testDao.test(); }
}开干我玩的就是真实
public class BeanFactoryTest { Test public void test() throws IOException { DefaultListableBeanFactory defaultListableBeanFactory new DefaultListableBeanFactory(); // 读取配置文件并自动注册 BeanDefinitionReader beanDefinitionReader new XmlBeanDefinitionReader(defaultListableBeanFactory); beanDefinitionReader.loadBeanDefinitions(classpath:spring.xml); // 从工厂中获取bean对象 TestService service (TestService) defaultListableBeanFactory.getBean(testService, , null); service.test(); /* 打印结果 testService.name: karl testDao */ }
}搞定是不是感觉XML也没那么可怕了
总结
XML配置其实就是一张菜单
Spring通过【资源】和【资源加载】帮我们找到这些配置文件然后通过大厨 XmlBeanDefinitionReader 解析配置最后把菜Bean放到厨房容器里
本文由 https://github.com/hongweihao/small-spring/tree/6_resource_load 赞注完成
本文完 | 求赞求关注求转发 !