当前位置: 首页 > news >正文

网站一键提交网站开发培训训

网站一键提交,网站开发培训训,快速免费做网站,wordpress鼠标点击彩色一、简化Bean的注册 如果每次注册一个Bean,都要像上节一样,手动写PropertyValues相关的代码,那太复杂了,我们希望读取XML文件,自动注册Bean,这样对于使用者,甚至不知道有BeanDefinition的存在 二…

一、简化Bean的注册

如果每次注册一个Bean,都要像上节一样,手动写PropertyValues相关的代码,那太复杂了,我们希望读取XML文件,自动注册Bean,这样对于使用者,甚至不知道有BeanDefinition的存在

二、统一处理资源文件

新建资源接口,Spring对所有的资源文件,统一处理

  • 一个资源,最重要的就是拿到输入流,拿到输入流就可以读取文件
public interface Resource {InputStream getInputStream() throws IOException;
}

提供三个资源实现类,分别读取不同类型的文件,这就是策略模式

类路径下的文件(最常用)

public class ClassPathResource implements Resource{private final String path;private final ClassLoader classLoader;public ClassPathResource(String path) {this(path, null);}public ClassPathResource(String path, ClassLoader classLoader) {Assert.notNull(path, "Path must not be null");this.path = path;this.classLoader = classLoader != null ? classLoader : ClassUtil.getClassLoader();}@Overridepublic InputStream getInputStream() throws IOException {InputStream is = classLoader.getResourceAsStream(path);if (is == null) {throw new FileNotFoundException(path + " cannot be opened because it does not exist");}return is;}
}

文件系统下的文件

public class FileSystemResource implements Resource{private File file;public FileSystemResource(File file) {this.file = file;}@Overridepublic InputStream getInputStream() throws IOException {return Files.newInputStream(file.toPath());}
}

网络文件

public class UrlResource implements Resource{private final URL url;public UrlResource(URL url) {Assert.notNull(url,"URL must not be null");this.url = url;}@Overridepublic InputStream getInputStream() throws IOException {URLConnection con = url.openConnection();return con.getInputStream();}
}

资源加载器接口,简化资源类的使用,自动根据路径选择合适的加载类

  • 这又属于工厂方法设计模式
/*** @Author 孤风雪影* @Email gitee.com/efairy520* @Date 2025/1/2 22:16* @Version 1.0*/
public interface ResourceLoader {String CLASSPATH_URL_PREFIX = "classpath:";Resource getResource(String location);
}

资源加载器接口实现

  • 根据路径前缀,默认就是使用classpath策略
/*** @Author 孤风雪影* @Email gitee.com/efairy520* @Date 2025/1/2 22:18* @Version 1.0*/
public class DefaultResourceLoader implements ResourceLoader{@Overridepublic Resource getResource(String location) {Assert.notNull(location, "Location must not be null");if (location.startsWith(CLASSPATH_URL_PREFIX)) {//使用类路径加载器,去掉前缀return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()));}else {try {URL url = new URL(location);return new UrlResource(url);} catch (MalformedURLException e) {return new FileSystemResource(new File(location));}}}
}

三、从文件中读取Bean

定义BeanDefinitionReader接口,从文件中读取BeanDefinition,并且注册到Bean工厂,这里有三要素

  • 资源文件
  • Bean工厂
  • 读取BeanDefinition的逻辑(单个资源,多个资源,位置字符串)
/*** @Author 孤风雪影* @Email gitee.com/efairy520* @Date 2025/1/2 22:26* @Version 1.0*/
public interface BeanDefinitionReader {BeanDefinitionRegistry getRegistry();ResourceLoader getResourceLoader();void loadBeanDefinitions(Resource resource);void loadBeanDefinitions(Resource... resources);void loadBeanDefinitions(String location);
}

用抽象类AbstractBeanDefinitionReader实现接口,模板方法设计模式

  • Bean工厂和资源加载器都是确定的,抽象类直接实现
  • 只有加载BeanDefinition是不确定的逻辑,交给具体的策略子类实现
public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader {private final BeanDefinitionRegistry registry;private final ResourceLoader resourceLoader;public AbstractBeanDefinitionReader(BeanDefinitionRegistry registry, ResourceLoader resourceLoader) {this.registry = registry;this.resourceLoader = resourceLoader;}public AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {this(registry, new DefaultResourceLoader());}@Overridepublic BeanDefinitionRegistry getRegistry() {return registry;}@Overridepublic ResourceLoader getResourceLoader() {return resourceLoader;}}

XmlBeanDefinitionReader做具体实现,策略模式

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {public XmlBeanDefinitionReader(BeanDefinitionRegistry registry, ResourceLoader resourceLoader) {super(registry, resourceLoader);}public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {super(registry);}@Overridepublic void loadBeanDefinitions(Resource resource) {try {InputStream is = resource.getInputStream();doLoadBeanDefinitions(is);} catch (IOException e) {throw new RuntimeException("IOException parsing XML document from " + resource, e);}}@Overridepublic void loadBeanDefinitions(Resource... resources) {for (Resource resource : resources) {loadBeanDefinitions(resource);}}@Overridepublic void loadBeanDefinitions(String location) {ResourceLoader resourceLoader = getResourceLoader();Resource resource = resourceLoader.getResource(location);loadBeanDefinitions(resource);}/*** 真正解析XMl文件的方法** @param inputStream*/private void doLoadBeanDefinitions(InputStream inputStream) {Document doc = XmlUtil.readXML(inputStream);Element root = doc.getDocumentElement();NodeList childNodes = root.getChildNodes();for (int i = 0; i < childNodes.getLength(); i++) {// 判断元素if (!(childNodes.item(i) instanceof Element)) continue;// 判断对象if (!"bean".equals(childNodes.item(i).getNodeName())) continue;// 解析标签Element bean = (Element) childNodes.item(i);String id = bean.getAttribute("id");String name = bean.getAttribute("name");String className = bean.getAttribute("class");// 获取 Class,方便获取类中的名称Class<?> clazz = null;try {clazz = Class.forName(className);} catch (ClassNotFoundException e) {throw new RuntimeException("不存在的类名" + className);}// 优先级 id > name,此处是Bean自己的id和nameString beanName = StrUtil.isNotEmpty(id) ? id : name;if (StrUtil.isEmpty(beanName)) {beanName = StrUtil.lowerFirst(clazz.getSimpleName());}// 定义BeanBeanDefinition beanDefinition = new BeanDefinition(clazz);// 读取属性并填充for (int j = 0; j < bean.getChildNodes().getLength(); j++) {if (!(bean.getChildNodes().item(j) instanceof Element)) continue;if (!"property".equals(bean.getChildNodes().item(j).getNodeName())) continue;// 解析标签:propertyElement property = (Element) bean.getChildNodes().item(j);String attrName = property.getAttribute("name");String attrValue = property.getAttribute("value");String attrRef = property.getAttribute("ref");// 获取属性值:引入对象、值对象Object value = StrUtil.isNotEmpty(attrRef) ? new BeanReference(attrRef) : attrValue;// 创建属性信息PropertyValue propertyValue = new PropertyValue(attrName, value);beanDefinition.getPropertyValues().addPropertyValue(propertyValue);}if (getRegistry().containsBeanDefinition(beanName)) {throw new RuntimeException("Duplicate beanName[" + beanName + "] is not allowed");}// 注册 BeanDefinitiongetRegistry().registerBeanDefinition(beanName, beanDefinition);}}
}

BeanDefinitionReader接口、资源接口,层次结构图

请添加图片描述

四、测试

新建Person类

@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class Person {private String name;private int age;private Cat cat;
}

新建Cat类

@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class Cat {private String name;private int weight;
}

编写一个spring.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans><bean id="cat" class="cn.shopifymall.springframework.test.bean.Cat"><property name="name" value="tomcat"/><property name="weight" value="2000"/></bean><bean id="person" class="cn.shopifymall.springframework.test.bean.Person"><property name="name" value="10001"/><property name="age" value="18"/><property name="cat" ref="cat"/></bean></beans>

新建测试类

public class ApiTest {@Testpublic void testGetBeanFromXml() {// 1.初始化 BeanFactoryDefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();// 2. 读取配置文件&注册BeanXmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);reader.loadBeanDefinitions("classpath:spring.xml");// 3. 获取Bean对象调用方法Person person = (Person) beanFactory.getBean("person");System.out.println("person:" + person);}
}

控制台输出

person:Person(name=10001, age=18, cat=Cat(name=tomcat, weight=2000))

五、总结

  • 通过引入spring.xml配置文件,我们就可以简化Bean的注册
  • 用户只需要编写一个xml文件,由XmlBeanDefinitionReader自动解析xml文件,生成BeanDefinition并注册到BeanFactory
http://www.dtcms.com/a/615259.html

相关文章:

  • 网站模板插件网站现在用h5做的吗
  • 免费微网站开发网站建设维护是啥意思
  • 温州网站建设公司有哪些房产信息网准确吗
  • 免费建公司网站的攻略乐陵seo网站优化
  • 网站推广需求刷单类网站开发
  • 中国建设银行邀约提额网站如何制作私人网站
  • 【Linux日新月异(五)】CentOS 7防火墙深度解析:firewalld全面指南
  • 广州建设工程质量安全网站东莞互联网
  • C语言编译程序的工作原理与优化技巧 | 探索C语言编译过程中的核心技术
  • AlphaSteer: Learning Refusal Steering with Principled Null-Space Constraint
  • [c++]赋值运算符重载
  • 正负反馈的判别
  • 怎么自己建一个网站最有效的恶意点击
  • 专业的高端企业网站一起看在线观看免费
  • 【Git】2025全图文详解安装教程
  • 松江手机网站开发南阳网站推广排名
  • 关于网站设计的书籍哈尔滨网站制作软件
  • 好用的wordpress谷歌推广优化
  • 玄武网站制作收费报价东莞房产网
  • 九州建网站厦门seo排名公司
  • 浦江县建设局网站网站模板如何修改
  • 解码IPC-消息队列、共享内存与信号量集
  • 【MicroPython编程-ESP32篇】-WS2812B全彩LED驱动
  • 娱乐网站建设公司wordpress伪静态 page
  • 技术支持 上海做网站wordpress 文章 批量 分类
  • 惠州做网站的公司有哪些中建国际建设有限公司官网是央企吗
  • 一步一步学习使用LiveBindings() 实现对JSON数据的绑定
  • 优秀网站赏析网站开发属于专利吗
  • 网站任务界面郑州网站制作开发
  • dede网站版权信息修改平面设计师参考网站