Spring之数据交换格式与SpringIOC底层实现

一、目标

  1. XML和JSON
  2. Java反射机制
  3. 手写SpringIOC

二、什么是数据交换格式

客户端与服务器常用数据交换格式xml、json、html

三、数据交换格式用场景

移动端(安卓、IOS)通讯方式采用http协议+JSON格式 走restful风格。

很多互联网项目都采用Http协议+JSON

因为xml比较重WebService服务采用http+xml格式 银行项目使用比较多

移动端和PC端服务器接口设计

四、数据交换格式

4.1 JSON简单实用

4.1.1 什么是JSON

​ JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,相比于xml这种数据交换格式来说,因为解析xml比较的复杂,而且需要编写大段的代码,所以客户端和服务器的数据交换格式往往通过JSON来进行交换。

{
    "sites": [
        {
            "name": "test",
                "url": "www.test.com"
        },
        {
            "name": "test01",
                "url": "http://test01.com/"
        }
    ]
}

JSON:JavaScript 对象表示法(JavaScript Object Notation)

JSON的形式是用大括号“{}”包围起来的项目列表,每一个项目间用逗号(,)分隔,而项目就是用冒号(:)分隔的属性名和属性值。这是典型的字典表示形式,也再次表明javascript里的对象就是字典结构。不管多么复杂的对象,都可以用一句JSON代码来创建并赋值。在JSON中,名称 / 值对包括字段名称(在双引号中),后面写一个冒号,然后是值

4.1.2 JSON格式的分类

JSON有两种结构

json简单说就是javascript中的对象和数组,所以这两种结构就是对象和数组两种结构,通过这两种结构可以表示各种复杂的结构\

1、对象:对象在js中表示为“{}”括起来的内容,数据结构为 {key:value,key:value,…}的键值对的结构,在面向对象的语言中,key为对象的属性,value为对应的属性值,所以很容易理解,取值方法为 对象.key 获取属性值,这个属性值的类型可以是 数字、字符串、数组、对象几种。

2、数组:数组在js中是中括号“[]”括起来的内容,数据结构为 [“java”,“javascript”,“vb”,…],取值方式和所有语言中一样,使用索引获取,字段值的类型可以是 数字、字符串、数组、对象几种。
经过对象、数组2种结构就可以组合成复杂的数据结构了。

4.1.3 常用JSON解析框架

  1. fastjson(阿里)
  2. gson(谷歌)
  3. jackson(SpringMVC自带)

4.1.4 使用fastjson解析json

4.1.4 .1 导入依赖

<dependency>
    <!--fastjson-1.1.43依赖-->
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.1.43</version>
</dependency>

4.1.4.2 使用fastjson API

//把JSON文本parse为JSONObject或者JSONArray 
public static final Object parse(String text); 
//把JSON文本parse成JSONObject  
public static final JSONObject parseObject(String text)//把JSON文本parse为JavaBean  
public static final <T> T parseObject(String text, Class<T> clazz); 
//把JSON文本parse成JSONArray
public static final JSONArray parseArray(String text);  
//把JSON文本parse成JavaBean集合
public static final <T> List<T> parseArray(String text, Class<T> clazz);  
//将JavaBean序列化为JSON文本 
public static final String toJSONString(Object object); 
//将JavaBean序列化为带格式的JSON文本 
public static final String toJSONString(Object object, boolean prettyFormat); 
//将JavaBean转换为JSONObject或者JSONArray。
public static final Object toJSON(Object javaObject);

4.1.4.3 解析json

public class jsondemo01 {
    static String JSONSTR = "{\"sites\":[{\"name\":\"蚂蚁课堂\",\"url\":\"www.itmayiedu.com\"},{\"name\":\"每特教育\",\"url\":\"http://meiteedu.com/\"}]}";

    public static void main(String[] args) {
        // 将json字符串转为jsonbject
        JSONObject jsonObject = JSONObject.parseObject(JSONSTR);
        JSONArray sites = jsonObject.getJSONArray("sites");
        for (Object object: sites) {
            JSONObject stObject  = (JSONObject) object;
            String name = stObject.getString("name");
            String url = stObject.getString("url");
            System.out.println(name+"-----------------"+url);
        }
    }
}

4.1.4.4 组装json

public class JosnDemo02 {
    //    static String JSONSTR = "{\"sites\":[{\"name\":\"蚂蚁课堂\",\"url\":\"www.itmayiedu.com\"},{\"name\":\"每特教育\",\"url\":\"http://meiteedu.com/\"}]}";
    public static void main(String[] args) {
        //创建JSON对象
        JSONObject jsonObject = new JSONObject();
        //创建JSON数组
        JSONArray objects = new JSONArray();
        //创建数组内部对象
        JSONObject bean1 = new JSONObject();
        bean1.put("name","蚂蚁课堂");
        bean1.put("url","www.itmayiedu.com");
        JSONObject bean2 = new JSONObject();
        bean2.put("name","每特教育");
        bean2.put("url","http://meiteedu.com");
        objects.add(bean1);
        objects.add(bean2);
        jsonObject.put("sites",objects);
        System.out.println(jsonObject);
    }

4.2 XML简单使用

4.2.1 什么是XML?

它是可扩展标记语言(Extensible Markup Language,简称XML),是一种标记语言。

XML 全称为可扩展的标记语言。主要用于描述数据和用作配置文件。

XML 文档在逻辑上主要由一下 5 个部分组成:

  1. XML 声明:指明所用 XML 的版本、文档的编码、文档的独立性信息
  2. 文档类型声明:指出 XML 文档所用的 DTD
  3. 元素:由开始标签、元素内容和结束标签构成
  4. 注释:以结束,用于对文档中的内容起一个说明作用
  5. 处理指令:通过处理指令来通知其他应用程序来处理非 XML 格式的数据,格式为XML 文档的根元素被称为文档元素,它和在其外部出现的处理指令、注释等作为文档实体的子节点,根元素本身和其内部的子元素也是一棵树。

4.2.2 XML样例

<?xml version="1.0" encoding="UTF-8"?>
<students>
    <student1 id="001">
        <微信公众号>@残缺的孤独</微信公众号>
        <学号>20140101</学号>
        <地址>北京海淀区</地址>
        <座右铭>要么强大,要么听话</座右铭>
    </student1>
    <student2 id="002">
        <新浪微博>@残缺的孤独</新浪微博>
        <学号>20140102</学号>
        <地址>北京朝阳区</地址>
        <座右铭>在哭泣中学会坚强</座右铭>
    </student2>
</students>

4.2.3 XML解析方式

  1. Dom4j
  2. Sax
  3. Pull

4.2.4 Dom4j与Sax区别

dom4j 不适合大文件的解析,因为它是一下子将文件加载到内存中,所以有可能出现内存溢出,但是,dom4j可以对xml进行灵活的增删改查和导航。

sax是基于事件来对xml进行解析的(缓存解析),所以他可以解析大文件的xml,sax没有这么强的灵活性,所以sax经常是用来解析大型xml文件。

4.2.5 使用dom4j写入xml

导入依赖

<!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
<dependency>
    <groupId>xml-apis</groupId>
    <artifactId>xml-apis</artifactId>
    <version>1.0.b2</version>
</dependency>
<dependency>
    <groupId>dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>1.6.1</version>
</dependency>
public class XmlDemo {
    public static void main(String[] args) throws IOException {
        File file = new File("F:\\java_demo\\jsondemo\\src\\main\\resources\\dom4j.xml");
        // 创建Document 自己创建Document对象
        Document document = DocumentHelper.createDocument();
        //其中students是根节点,可以继续添加其他节点等操作。
        // 添加根节点
        Element root = document.addElement("students");
        // 在根节点下添加第一个子节点
        Element person1 = root.addElement("person").addAttribute("attr","root noe");
        person1.addElement("people").addAttribute("id","child one ").addText("父节点的子节点one");
        person1.addElement("people").addAttribute("id","child two ").addText("父节点的子节点two");
        // 在根节点下添加第一个子节点
        Element person2 = root.addElement("person").addAttribute("attr","root noe");
        person2.addElement("people").addAttribute("id","child one ").addText("父节点的子节点one");
        person2.addElement("people").addAttribute("id","child two ").addText("父节点的子节点two");
        //创建打印流
        OutputFormat prettyPrint = OutputFormat.createPrettyPrint();
        //创建XMLWriter
        XMLWriter xmlWriter = new XMLWriter(new FileOutputStream(file), prettyPrint);
        //将document写入到xml中
        xmlWriter.write(document);
    }
}

4.2.6 解析xml代码

public class XmlDemo02 {
    public static void main(String[] args) throws DocumentException {
        //创建SAXReader
        SAXReader saxReader = new SAXReader();
        //读取xml文件 拿到decument
        Document read = saxReader.read("F:\\java_demo\\jsondemo\\src\\main\\resources\\test.xml");
        //获取dom节点 获取root节点
        Element rootElement = read.getRootElement();
        getNodes(rootElement);
    }

    private static void getNodes(Element rootElement) {
        System.out.println("当前节点名称"+rootElement.getName());
        //获取属性ID
        List<Attribute> attributes = rootElement.attributes();
        for (Attribute attribute:
        attributes) {
            System.out.println("属性:" +attribute.getName()+"---"+attribute.getText());
        }
        //判断rootElement是否还有文本内容
        if (!rootElement.getTextTrim().equals("")){
            System.out.println(rootElement.getName() + "--" + rootElement.getText());
        }
        //创建迭代器
        Iterator iterator = rootElement.elementIterator();
        //判断是否还有下一个 顺序迭代
        while (iterator.hasNext()){
            //获取下一个元素
            Element next = (Element)iterator.next();
            getNodes(next);
        }
    }
}

4.2.7 XML与JSON区别

Xml是重量级数据交换格式,占宽带比较大。

JSON是轻量级交换格式,xml占宽带小。

所有很多互联网公司都会使用json作为数据交换格式

很多银行项目,大多数还是在使用xml。

五、 Java反射机制

5.1 什么是Java反射

就是正在运行,动态获取这个类的所有信息。

5.2 反射机制的作用

  1. 反编译:.class–>.java
  2. 通过反射机制访问java对象的属性,方法,构造方法等;

5.3 反射机制的应用场景

  1. Jdbc 加载驱动
  2. Spring ioc
  3. 框架

5.4 反射机制获取类有三种方法

public class ReflexDemo01 {
    public static void main(String[] args) throws ClassNotFoundException {
        //反射获取的方式
        //第一种方式
        Class<?> userClass = Class.forName("entity.User");
        //第二种方式: java中每个类型都有class 属性.
        Class<User> userClass1 = User.class;
        //第三种方式:java语言中任何一个java对象都有getClass 方法
        User user = new User();
        //userClass2是运行时类 (user的运行时类是User)
        Class<? extends User> userClass2 = user.getClass();
    }
}

5.5 反射创建对象的方式

public class ReflexDemo02 {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException {
        Class<?> userClass = Class.forName("entity.User");
        // 创建此Class 对象所表示的类的一个新实例 调用了User的无参数构造方法. 测试将无参构造函数删除
//        User  user =(User) userClass.newInstance();
//        user.setUserId("1001");
//        user.setUsername("小明");
//        System.out.println(user.getUserId()+"---------------"+user.getUsername());
        
        //实例化有参构造函数
        Constructor<?> constructor = userClass.getConstructor(String.class, String.class);
        User user = (User) constructor.newInstance("1001", "xiaoming");
        System.out.println(user);
    }
}

5.6 反射创建api

方法名称作用
getDeclaredMethods []获取该类的所有方法
getReturnType()获取该类的返回值
getParameterTypes()获取传入参数
getDeclaredFields()获取该类的所有字段
setAccessible允许访问私有成员

5.7 使用反射为类私有属性赋值

public class ReflexDemo02 {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        Class<?> userClass = Class.forName("entity.User");
        //使用反射实例化对象 无参数构造函数
        Object newInstance  = userClass.newInstance();
        //获取当前类的 userId字段
        Field userId = userClass.getDeclaredField("userId");
        //允许操作私有成员
        userId.setAccessible(true);
        //设置值
        userId.set(newInstance,"1001");
        User user = (User) newInstance;
        System.out.println("userId"+user.getUserId());
    }
}

六、 手写SpringIOC框架

6.1 什么是SpringIOC

什么是SpringIOC,就是把每一个bean(实体类)与bean(实体了)之间的关系交给第三方容器进行管理。

xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<!--声明-->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                      http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    <bean id="user1"  class="entity.User">
        <property name="userId" value="0001"></property>
        <property name="username" value="余胜军"></property>
    </bean>
    <bean id="user2" class="entity.User">
        <property name="userId" value="0002"></property>
        <property name="username" value="张三"></property>
    </bean>
</beans>
public class SpringReader {
    public static void main(String[] args) {
        //FileSystemXmlApplicationContext  从文件系统中加载配置文件
        //1.读取springxml配置 ClassPathXmlApplicationContext 从类路径下加载配置文件
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        //2.获取bean对象
        User user =(User) classPathXmlApplicationContext.getBean("user1");
        System.out.println(user);
    }
}

6.2 什么是SpringIOC底层实现原理

  1. 读取bean的XML配置文件
  2. 使用beanId查找bean配置,并获取配置文件中class地址。
  3. 使用Java反射技术实例化对象
  4. 获取属性配置,使用反射技术进行赋值。

详细步骤

//1.利用传入的参数获取xml文件的流,并且利用dom4j解析成Document对象
//2.对于Document对象获取根元素对象<beans>后对下面的<bean>标签进行遍历,判断是否有符合的id.
//3.如果找到对应的id,相当于找到了一个Element元素,开始创建对象,先获取class属性,根据属性值利用反射建立对象.
/*4.遍历<bean>标签下的property标签,并对属性赋值.注意,需要单独处理int,float类型的属性.
因为在xml配置中这些属性都是以字符串的形式来配置的,因此需要额外处理.*/
/*5.如果属性property标签有ref属性,说明某个属性的值是一个对象,那么根据id(ref属性的值)去获取ref对应的对象,再给属性赋值.*/
/*6.返回建立的对象,如果没有对应的id,或者<beans>下没有子标签都会返回null*/

6.3 代码实现

//建立实体类
public class User {
    private String userId;
    private String username;
}
//读取Spring配置文件
public class ClassPathXmlApplicationContext {
    private String xmlPath;
    
    public ClassPathXmlApplicationContext() {
    }
    public ClassPathXmlApplicationContext(String xmlPath) {
        this.xmlPath = xmlPath;
    }
    public Object getBean(String beadId)  {
        // 解析xml器
        SAXReader saxReader = new SAXReader();
        // 从项目根目录路径下 读取
        Document read = null;
        try {
            read = saxReader.read(this.getClass().getClassLoader().getResourceAsStream(xmlPath));
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        // 获取根节点资源
        Element root = read.getRootElement();
        List<Element> elements = root.elements();
        Object obj =null;
        for (Element element: elements) {
            String id = element.attributeValue("id");
            if (StringUtils.isEmpty(id)){
                return null;
            }
            if(!beadId.equals(id)){
                continue;
            }
            // 获取实体bean class地址
            String beanPath = element.attributeValue("class");
            // 使用反射实例化bean
            Class<?> aClass = null;
            try {
                aClass = Class.forName(beanPath);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            //实例化
            try {
                obj = aClass.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            // 获取子类对象
            List<Element> attributes  = element.elements();
            if (attributes.size()<0){
                return null;
            }
            for (Element et : attributes) {
                //使用反射技术为方法赋值
                String name = et.attributeValue("name");
                String value = et.attributeValue("value");
                Field field = null;
                try {
                    field = aClass.getDeclaredField(name);
                    field.setAccessible(true);
                    field.set(obj,value);
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }

            }
        }
        return obj;
    }
}
//入口
public class StringIOCDemo {
    public static void main(String[] args){
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        User userId1 =(User) classPathXmlApplicationContext.getBean("user1");
        System.out.println(userId1);
    }
}
    e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

        }
    }
    return obj;
}

}




```java
//入口
public class StringIOCDemo {
    public static void main(String[] args){
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        User userId1 =(User) classPathXmlApplicationContext.getBean("user1");
        System.out.println(userId1);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值