序列化代理模式
来源:互联网 发布:淘宝长图 编辑:程序博客网 时间:2024/05/22 15:49
实现
java.io.Serializable
接口, 会增加出错和出现安全问题的可能性, 因为它开放了实例的另一种来源 ---- 反序列化. 有一种方法可以减少风险, 那就是序列化代理模式.类图如下:
小二, 上代码 !
import java.io.InvalidObjectException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;/** * 1. 序列化Person时, 会调用调用writeReplace()生成一个PersonProxy对象, 然后对此对象进行序列化 (不是对Person类对象进行序列化, * 由序列化文件的内容可以得知, 可以查看序列化生成的文件, 文件中内容为如下图 (代码之后的图) * 2. 反序列化时, 会调用PersonProxy的readResolve()方法生成一个Person对象, * 最后返回此对象的拷贝 (通过PersonProxy类的readResolve方法和main方法中的输出可以看出) * 3. 因此, Person类的序列化工作完全交给PersonProxy类, 正如此模式的名称所表达的一样 */public class Person implements Serializable { private final String name; private final String hobby; private final int age; public Person(String name, String hobby, int age) { System.out.println("Person(String name, String hobby, int age)"); //约束条件 if(age < 0 || age > 200) { throw new IllegalArgumentException("非法年龄"); } this.name = name; this.hobby = hobby; this.age = age; } public String getName() { return name; } public String getHobby() { return hobby; } public int getAge() { return age; } private static class PersonProxy implements Serializable { private final String name; private final String hobby; private final int age; public PersonProxy(Person original) { System.out.println("PersonProxy(Person original)"); this.name = original.getName(); this.hobby = original.getHobby(); this.age = original.getAge(); } private Object readResolve() { System.out.println("PersonProxy.readResolve()"); Person person = new Person(name, hobby, age); System.out.println("resolveObject: " + person); return person; } } private Object writeReplace() { System.out.println("Person.writeReplace()"); return new PersonProxy(this); //readObject的时候是调用, PersonProxy的readResolve() } //此方法不会执行, private void writeObject(ObjectOutputStream out) { System.out.println("Person.writeObject()"); } //防止攻击者伪造数据, 企图违反约束条件 (如: 违反年龄约束) private Object readObject(ObjectInputStream in) throws InvalidObjectException { System.out.println("Person.readObject()"); throw new InvalidObjectException("Proxy required"); }}
序列化文件中的内容:
客户程序如下:
import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;public class Main { public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException { Person person = new Person("张三", "足球" ,25); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("serial.ser")); out.writeObject(person); out.flush(); out.close(); Thread.sleep(1000); ObjectInputStream in = new ObjectInputStream(new FileInputStream("serial.ser")); Person deserPerson = (Person) in.readObject(); System.out.println("main: " + person); in.close(); if(person == deserPerson) { System.out.println("序列化前后是同一个对象"); } else { //程序会走这一段, 反序列化会创建对象, 但是不会执行类的构造方法, 而是使用输入流构造对象 System.out.println("序列化前后不是同一个对象, 哈哈哈"); } }}
此模式工作原理如下:
- 序列化Person时, 会调用调用writeReplace()生成一个PersonProxy对象, 然后对此对象进行序列化 (不是对Person类对象进行序列化, 由序列化文件的内容可以得知, 可以查看序列化生成的文件, 文件中内容为如下图
- 反序列化时, 会调用PersonProxy的readResolve()方法生成一个Person对象, 最后返回此对象的拷贝 (通过PersonProxy类的readResolve方法和main方法中的输出可以看出)
- 因此, Person类的序列化工作完全交给PersonProxy类, 正如此模式的名称所表达的一样
本文参考: 《Effective Java 第2版》第78条 『考虑使用序列化代理代替序列化实例』
作者:元亨利贞o
链接:http://www.jianshu.com/p/a3b3dd80c8d6
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
阅读全文
0 0
- 序列化代理模式
- 序列化代理模式
- 序列化及其代理
- Serializable:序列化代理
- 代理模式--动态代理
- 代理模式-静态代理
- 代理模式-静态代理
- 代理模式 & 动态代理
- 代理模式--静态代理
- 代理模式--动态代理
- 代理模式(动态代理)
- 代理模式-动态代理
- 代理模式-动态代理
- 代理模式动态代理
- 代理模式-静态代理
- 代理模式-动态代理
- 代理模式 -动态代理
- 代理模式---动态代理
- C6748_NMI
- Eclipse4.5.0安装Spring插件springsource-tool-suite
- eclipse没有自动编译出.class文件
- 网络编程系列文章(一)之Socket实现异步TCP服务器
- Ajax请求中的async:false/true的作用
- 序列化代理模式
- 线性表的顺序存储实现c语言
- constraint的一些用法总结
- 第五届图灵杯1861
- 3、条件加载Bean——@Conditional
- 剑指_18.删除链表中的重复数字
- 记一次小米2S的刷机过程
- 获取之前发布的webService服务
- cjqyzUsers