SpringIoc以及set注入八种基本类型的简单实现
主要涉及到的技术以及API
反射、xml定义和解析、树模型
反射可以在代码运行状态下动态的创建对象以及调用方法。
API:Dom4j、Class、Field、Method。
请仔细阅读接下来的API详解,为代码的阅读进行铺垫。
Dom4j
org.dom4j.io.SAXreader - Xml读取工具。
- Document read(InputStream is) 读取输入流,并返回文档对象/文档树模型。
org.dom4j.Document - 文档对象/文档树模型。
- Element getRootElement() 通过文档对象,获取xml文档的根节点。
org.dom4j.Element - 元素/节点对象,一个Element对象就表示一个xml文档的节点。
- String getName() 获取当前节点的名称。
- List<Element> elements() 获取当前节点的所有子节点。
- String attributeValue("属性名称") 获取当前节点的属性值
Class
java.lang.Class - 类对象,该类的实例由Java虚拟机和类加载器自动构造。
- static Class forName(String className) 根据参数自定的类名创建类对象,类对象中记录了className指定类名的信息。
- T newInstance() 创建该class对象所记录类型的实例。
- Field getDeclaredField(String name) 根据参数指定的name获取类型的字段/成员变量。
- Method[] getMethods() 用于获取Class对象所表示类中的所有公共方法。
Field
java.lang.reflect.Field - 单个 字段/成员变量 对象
- void setAccessible(boolean falg)java是门安全的语言,字段默认不可暴力访问,想要通过这种方式访问某个字段,需要打开访问权限,传入true即可。
- Type getGenericType() 获取字段类型。
Method
java.lang.reflect.Method - 用于描述获取到的单个 成员方法 信息。
- String getName() 获取当前方法名称 如setName。
- Object invoke(Object obj, Object... args) 使用参数对象 obj 去调用该 Method 对象所表示的成员方法,实参传递 args。
- 若该 Method 对象表示Person类中setName()方法,则调用该方法就是 obj.setName()。
铺垫完毕 上代码
首先 - 目录结构

pom.xml

第一部分 - Person类
展开查看
public class Person {
private int age;
private String name;
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person() {
}
public Person(int age, String name) {
this.age = age;
this.name = name;
}
}
###第二部分 - xml文档

注意!!!
第三部分XmlUtil的代码中,由于MarkDown标签冲突原因,集合中的泛型并没有正常显示
如:
Map<String,Object> map = new HashMap<>();
List<Element> beans = rootElement.elements();
摘抄代码时,还请手动添加。
第三部分 - XmlUtil类
展开查看
public class XmlUtil {
//创建Map集合,用于bean对象的存储
Map map = new HashMap();
/**
* @param xmlName 想要解析的xml文档
* @throws Exception
*/
XmlUtil(String xmlName) throws Exception {
//加载输入流
InputStream is = getClass().getClassLoader().getResourceAsStream(xmlName);
//创建解析器
SAXReader saxReader = new SAXReader();
//解析输入流,得到整个文档
Document document = saxReader.read(is);
//调用init,并将文档树模型传入
init(document);
}
public void init(Document document) throws Exception {
//获取文档中的根元素,也就是xml中的beans标签
Element rootElement = document.getRootElement();
//通过根元素,获取文档中所有的bean标签
List<Element> beans = rootElement.elements();
//声明Class类型的引用
Class cls;
//声明实列引用,后续执行方法时用到
Object instance;
//声明String类型的beanId,充当Map集合中的key
String beanId;
//依次取出bean标签
for (Element bean:beans){
//获取bean标签的class属性值
String className = bean.attributeValue("class");
//获取bean标签的id属性值
beanId = bean.attributeValue("id");
//根据获取的class属性值创建Class对象
cls = Class.forName(className);
//根据cls记录的类创建实列
instance = cls.newInstance();
//获取bean标签下的所有property标签
List<Element> propertys = bean.elements();
//挨个取出property标签
for (Element property : propertys){
//获取property标签的name属性值
String name = property.attributeValue("name");
//然后从cls记录的类型中获取name中存储的字段
Field field = cls.getDeclaredField(name);
//如果字段是private修饰,需要手动打开访问权限
field.setAccessible(true);
//获取这个字段的类型,用于后续赋值时的类型判断
Type type = field.getGenericType();
//开始拼接set方法,拼接的方式是 "set"+字段 , 用于后续寻找想要使用的set方法
String methodName = "set" + name;
//获取cls记录类型的所有方法
Method[] methods = cls.getMethods();
String value = property.attributeValue("value");
//遍历所有的方法,并找到吻合的set方法
for (Method method : methods){
//获取方法名,调用String类中的compareToIgnoreCase方法与已经拼接好的 set 方法做比较
if (method.getName().compareToIgnoreCase(methodName) == 0) {
//使用已经获取到的字段类型与标签中读取到的值进行比较
//这里进行String类型的比较
if (type.equals(value.getClass())) {
method.invoke(instance, value);
//如果类型不一致,则进入下一个类型判断
}else if(type == Integer.TYPE){
int i = Integer.parseInt(value);
method.invoke(instance,i);
}
//。。。这里可以继续if else进行类型的判断
}
}
}
//所有流程执行完毕,将准备好的 beanId 以及 填充完毕的实列对象放入map集合中
map.put(beanId,instance);
}
}
/**
* @param beanId Map中的key
* @return 返回参数key所对应的对象/实列
*/
public Object getBean(String beanId){
return map.get(beanId);
}
//main方法中进行测试
public static void main(String[] args) throws Exception {
XmlUtil xmlUtil = new XmlUtil("beans.xml");
Object bean = xmlUtil.getBean("1002");
Person p = (Person)bean;
System.out.println(p);
}
}
###执行结果

泡吧一年半,丰富了自己的阅读,也学到很多。第一次写随笔,如有不足还请指出!
SpringIoc以及set注入八种基本类型的简单实现的更多相关文章
- Java的八种基本类型:(按字节来分)
Java的八种基本类型:(按字节来分) boolean 布尔型 1个字节 8bit(8位) byte 字节类型 1个字节 char 字符类型 2个字节 short ...
- 【Java中级】(一)面向对象的特性与八种基本类型
1.1.Java 基本数据类型: Java提供了8种基本类型.六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型. byte.short.int.long.float.double. ...
- HTTP协议八种请求类型介绍
HTTP 协议中共定义了八种方法或者叫“动作”来表明对 Request-URI 指定的资源的不同操作方式,具体介绍如下: OPTIONS:返回服务器针对特定资源所支持的HTTP请求方法.也可以利用向W ...
- String类型不属于八种基本类型
String不属于8种基本数据类型,String是一个对象.因为对象的默认值是null,所以String的默认值也是null:但它又是一种特殊的对象,有其它对象没有的一些特性. new String( ...
- http协议的八种请求类型
GET:向特定的资源发出请求. POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件).数据被包含在请求体中.POST请求可能会导致新的资源的创建和/或已有资源的修改. OPTIONS: ...
- Java八种基本类型
boolean 二进制位: true ,false byte 二进制位:8 -128 - 127 -2的7次方到2的7次方-1 char 二进制位:16 0 - 65535 short 二 ...
- 【转】MYSQL数据库四种索引类型的简单使用--MYSQL组合索引“最左前缀”原则
MYSQL数据库索引类型包括普通索引,唯一索引,主键索引与组合索引,这里对这些索引的做一些简单描述: (1)普通索引 这是最基本的MySQL数据库索引,它没有任何限制.它有以下几种创建方式: 创建索引 ...
- Java源码解读(一) 8种基本类型对应的封装类型
说起源码其实第一个要看的应该是我们的父类Object,这里就不对它进行描述了大家各自对其进行阅读即可. 一.八种基本类型 接下来介绍我们的八种基本类型(这个大家都知道吧):char.byte.shor ...
- JVM常量池和八种基本数据及字符串
迄今为止看到的对常量池和字符串最为透彻的解释,赞一个! 常量池(constant_pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据.它包括了关于类.方法.接口等中的常量, ...
随机推荐
- unity UI事件
由于工作需要到持续按键,所以了解了一下unity UI事件,本文主要转载于http://www.cnblogs.com/zou90512/p/3995932.html?utm_source=tuico ...
- spring cloud 2.x版本 Ribbon服务发现教程(内含集成Hystrix熔断机制)
本文采用Spring cloud本文为2.1.8RELEASE,version=Greenwich.SR3 前言 本文基于前两篇文章eureka-server和eureka-client的实现. 参考 ...
- ios swift多线程的实现 Multithreading
1.多线程的概念 Multithreading多线程是指从软件或硬件上,实现多个线程并发执行的技术.使得能够同步完成多项任务,提高资源使用效率. 1.1 任务.进程和线程 任务Task:应用程序完成的 ...
- 阿里规范不建议多表Join,可这SQL要怎么写?
阿里开发手册的描述,禁止多表join: 手册上写着[强制],相信很多同学项目里面的代码都不满足这个要求. 但是关键问题是:不用join,这SQL究竟要怎么写?! 分解关联查询 即对每个要关联的表进行单 ...
- 为啥不能#define private public了?
今天在写一个单元测试的时候出现了如下编译错误: 以前用gtest为了测试业务代码里的private函数和变量,一直是在单元测试代码通过#define private public这样的trick达到测 ...
- [翻译]Jupyter notebook .NET Core 内核预览1
当您想到Jupyter Notebooks时,您可能会考虑使用Python,R,Julia或Scala而不是.NET编写代码. 今天,我们很高兴宣布您可以在Jupyter Notebooks中编写.N ...
- [考试反思]1012csp-s模拟测试70:盘旋
这套题比较烂... 上来看到T2是原题,一想上一次考试遇到原题就不换,这次应该也是,于是直接开始码,码了一半然后换题了 T1打表找规律或者推式子都不难... T2水的一匹暴力剪枝即可,但是我并不知道数 ...
- [转载]2.2 UiPath条件判断活动Flow Decision的介绍和使用
一.Flow Decision介绍 FlowDecision节点是一个条件节点,它根据指定条件是否成立来控制流程的两个分支. 当条件为True时,流程执行一个分支 当条件为False时,流程执行另外一 ...
- java遍历一个实体
//遍历order,得到属性值不为空的属性,type:操作类型.0是新增,1是更新 private Map<String, Object> reflect(Order order,Stri ...
- thinkphp5中取消了3.2版本中的单字母函数,初用tp5可能不大适应,下边给出两者的对应参照表,以便查阅。
3.2版本 5.0版本 C config E exception G debug L lang T 废除 I input N 废除 D model M db A controller R action ...