浅析Spring工厂的反射和配置文件
作者:CrazyDragon_King 发布时间:2023-06-22 20:52:23
反射和配置文件
学习 Spring 的时候,虽然可以知道是通过反射和配置文件的方式来获取 JavaBean 对象,但是一直没有机会自己尝试一次,探究以下内部原理,虽然有人推荐阅读源码,但是可能还是感觉学的不好,一直没有尝试过。现在刚好学习设计模式刚好遇到了这部分的内容了,感觉自己对这个有了一个较好的理解了。
设计模式中,为了满足开闭原则,大都引入了抽象层,如工厂方法模式、抽象工厂模式等。客户端针对抽象层编程,而在程序运行的时候再指定其子类,根据里氏代换原则和面向对象的多态性,子类对象再运行时将覆盖父类对象。如果需要对系统进行扩展,只需要修改子类类名即可。在具体实现时,通过引入配置文件可以使得用户再不修改客户端任何代码的前提下增加或替换子类,
其基本实现过程过程为:
客户端针对抽象层编程,客户端代码中不能出现具体的类名,即客户端不直接实例化对象。
引入纯文本格式的配置文件,通常是 XML 文件,将具体类类名存储在配置文件中。
通过 DOM(Document Object Model,文档对象模型)、SAX(SimpleAPI for XML)等 XML 解析技术获取存储在配置文件中类名。
在客户端代码中通过反射机制根据类名创建对象,用反射所创建的对象代替父类对象的引用,程序运行时,将调用子类方法来实现业务功能。
如果需要扩展功能,只需要添加一个新的子类继承抽象父类,再修改配置文件,重新运行程序即可;如果需要替换功能,只需要另一个子类类名替换存储再配置文件中的原有子类类名。无论是扩展还是替换都无须修改既有类库和客户端源码,完全符合开闭原则。
Talk is cheap, show me the code.
直接通过代码来理解上面的内容吧。
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean>com.reflect.Dog</bean>
</beans>
测试实体类
package com.reflect;
public class Dog {
private String name;
private Integer age;
public Dog() {}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Dog [name=" + name + ", age=" + age + "]";
}
}
对象工厂类(类似Spring工厂的简单实现)
package com.reflect;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.*;
public class Factory {
public static Object getBean() {
try {
Document doc = DocumentBuilderFactory
.newInstance()
.newDocumentBuilder()
.parse("src/beans.xml");
//获取包含类名的文本节点
NodeList nodeList = doc.getElementsByTagName("bean");
Node node = nodeList.item(0).getFirstChild();
String name = node.getNodeValue();
//通过类名生成实例对象并将其返回
Class<?> clazz = Class.forName(name);
return clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
测试类
package com.reflect;
public class Test {
public static void main(String[] args) {
Dog dog = null;
dog = (Dog)Factory.getBean();
dog.setName("小黑");
dog.setAge(12);
System.out.println(dog.toString());
}
}
项目目录结构
注意这里需要使用 dom4j 的jar包,下载导入即可!
运行结果
现在需求变了,不想使用 Dog 类,而要使用 HuntDog 类,只要增加 HuntDog 类, 并继承 Dog 类即可,项目源码不需要改动,满足开闭原则。
package com.reflect;
public class HuntDog extends Dog {
private String name;
private Integer age;
public HuntDog() {}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "HuntDog [name=" + name + ", age=" + age + "]";
}
public void say() {
System.out.println("Hello, I am HuntDog: "+this.toString());
}
}
修改 XML 如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean>com.reflect.HuntDog</bean>
</beans>
修改后的运行结果
来源:https://blog.csdn.net/qq_40734247/article/details/102810935


猜你喜欢
- 背景公司的开发框架集成了附件本地存储,阿里云,华为云等,现项目有要求附件存储与应用部署环境不能是同一台服务器,也不能使用云存储,经过技术选型
- .NET开发人员首选的方法,通过COM组件调用Office软件本身来实现文件的创建和读写,但是数据量较大的时候异常缓慢;如下代码所示已经做了
- C#是一种编译型的语言,程序执行,首先要经过编译器编译,如何让C#像一种脚本一样,在要执行的时候,进行编译,这里,我们可以用Microsof
- File存储(内部存储)一旦程序在设备安装后,data/data/包名/ 即为内部存储空间,对外保密。Context提供了2个方法来打开输入
- 理解枚举类型枚举类型是Java 5中新增特性的一部分,它是一种特殊的数据类型,之所以特殊是因为它既是一种类(class)类型却又比类类型多了
- 问题: 在win10系统中,使用IDEA 查看源码的时候,经常跳转代码,这样会让使用者感觉和方便,但是当你想要返回上次跳转的位置时,却不知道
- 一、简介:介绍两种使用 BitmapTransformation 来实现 Glide 加载圆形图片和圆角图片的方法。Glide 并不能直接支
- Android Studio是谷歌推出一个Android集成开发工具,基于IntelliJ IDEA。它类似于Eclipse ADT,And
- Java基础面试题及答案集锦(基础题122道,代码题19道),具体详情如下所示:1、面向对象的特征有哪些方面1.抽象:抽象就是忽略一个主题中
- 本文实例讲述了java两种单例模式用法。分享给大家供大家参考,具体如下:按照加载方式的不同,单例模式有两种实现:private:只能在同一个
- 本文实例讲述了Android实现取消GridView中Item选中时默认的背景色。分享给大家供大家参考,具体如下:1. 取消Gr
- 一、为什么要编码不知道大家有没有想过一个问题,那就是为什么要编码?我们能不能不编码?要回答这个问题必须要回到计算机是如何表示我们人类能够理解
- Android设备多分辨率的问题 Android浏览器默认预览模式浏览 会缩小页面 WebView中则会以原始大小显示 Android浏览器
- 简介Java 在 1.5 引入了泛型机制,泛型本质是参数化类型,也就是说变量的类型是一个参数,在使用时再指定为具体类型。泛型可以用于类、接口
- 欢迎访问我的GitHub这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demo
- 结构图: 抽象对象: abstract class Component  
- 默认配置默认配置比较低,打开稍大点的项目就很容易卡掉,所以最好扩大一下内存。IntelliJ IDEA的VM配置IntelliJ IDEA2
- 一、线程间的共享1.1 ynchronized内置锁用处Java支持多个线程同时访问一个对象或者对象的成员变量关键字synchronized
- 一、创建项目1.File->new->project;2.选择“Spring Initializr”,点击next;(jdk1.
- 我们经常看到使用了ViewPager的App,在每页上面都会有一个滑块来标志当前处于哪一页。在PagerView包里有android.sup