Pengenalan Kepada Kryo

1. Gambaran keseluruhan

Kryo adalah kerangka bersiri Java dengan fokus pada kelajuan, kecekapan, dan API yang mudah digunakan.

Dalam artikel ini, kami akan meneroka ciri utama kerangka Kryo dan menerapkan contoh untuk menunjukkan kemampuannya.

2. Ketergantungan Maven

Perkara pertama yang perlu kita lakukan ialah menambahkan kebergantungan kryo ke pom.xml kami :

 com.esotericsoftware kryo 4.0.1 

Versi terbaru artifak ini boleh didapati di Maven Central.

3. Asas Kryo

Mari kita mulakan dengan melihat bagaimana Kryo berfungsi dan bagaimana kita dapat membuat siri dan mendeserialisasi objek dengannya.

3.1. Pengenalan

Kerangka ini menyediakan kelas Kryo sebagai pintu masuk utama untuk semua fungsinya.

Kelas ini mengatur proses serialisasi dan memetakan kelas ke contoh Serializer yang menangani perincian menukar grafik objek menjadi representasi byte.

Setelah bait siap, mereka akan ditulis ke aliran menggunakan objek Output . Dengan cara ini mereka dapat disimpan dalam file, pangkalan data atau dikirim melalui jaringan.

Kemudian, ketika objek diperlukan, contoh Input digunakan untuk membaca byte dan mendekodekannya menjadi objek Java.

3.2. Objek Bersiri

Sebelum menyelami beberapa contoh, mari kita buat kaedah utiliti untuk memulakan beberapa pemboleh ubah yang akan kita gunakan untuk setiap kes ujian dalam artikel ini:

@Before public void init() { kryo = new Kryo(); output = new Output(new FileOutputStream("file.dat")); input = new Input(new FileInputStream("file.dat")); }

Sekarang, kita dapat melihat betapa mudahnya menulis dan membaca objek menggunakan Kryo:

@Test public void givenObject_whenSerializing_thenReadCorrectly() { Object someObject = "Some string"; kryo.writeClassAndObject(output, someObject); output.close(); Object theObject = kryo.readClassAndObject(input); input.close(); assertEquals(theObject, "Some string"); }

Perhatikan kaedah panggilan ke tutup () . Ini diperlukan kerana kelas Output dan Input mewarisi masing-masing dari OutputStream dan InputStream .

Serialisasi beberapa objek juga mudah:

@Test public void givenObjects_whenSerializing_thenReadCorrectly() { String someString = "Multiple Objects"; Date someDate = new Date(915170400000L); kryo.writeObject(output, someString); kryo.writeObject(output, someDate); output.close(); String readString = kryo.readObject(input, String.class); Date readDate = kryo.readObject(input, Date.class); input.close(); assertEquals(readString, "Multiple Objects"); assertEquals(readDate.getTime(), 915170400000L); }

Perhatikan bahawa kami melewati kelas yang sesuai ke kaedah readObject () , ini menjadikan kod kami bebas dari cor.

4. Serializer

Di bahagian ini, kami akan menunjukkan Serializer mana yang sudah ada, dan kemudian kami akan membuat sendiri.

4.1. Serializer Lalai

Apabila Kryo membuat siri objek, ia akan membuat contoh kelas Serializer yang terdaftar sebelumnya untuk melakukan penukaran kepada bait. Ini dipanggil serializer lalai dan boleh digunakan tanpa persediaan dari pihak kami.

Perpustakaan sudah menyediakan beberapa serializer seperti itu yang memproses primitif, daftar, peta, jumlah, dan lain-lain. Sekiranya tidak terdapat serializer untuk kelas tertentu, maka FieldSerializer digunakan, yang dapat menangani hampir semua jenis objek.

Mari lihat bagaimana rupa ini. Pertama, mari 'buat kelas Orang :

public class Person { private String name = "John Doe"; private int age = 18; private Date birthDate = new Date(933191282821L); // standard constructors, getters, and setters }

Sekarang, mari tulis objek dari kelas ini dan baca semula:

@Test public void givenPerson_whenSerializing_thenReadCorrectly() { Person person = new Person(); kryo.writeObject(output, person); output.close(); Person readPerson = kryo.readObject(input, Person.class); input.close(); assertEquals(readPerson.getName(), "John Doe"); }

Perhatikan bahawa kita tidak perlu menentukan apa-apa untuk membuat siri objek Person kerana FieldSerializer dibuat secara automatik untuk kita.

4.2. Serialisasi Custom

Sekiranya kita memerlukan lebih banyak kawalan terhadap proses siri, kita mempunyai dua pilihan; kita boleh menulis kelas Serializer kita sendiri dan mendaftarkannya dengan Kryo atau membiarkan kelas itu menangani siri bersiri itu sendiri.

Untuk menunjukkan pilihan pertama, mari buat kelas yang memanjangkan Serializer :

public class PersonSerializer extends Serializer { public void write(Kryo kryo, Output output, Person object) { output.writeString(object.getName()); output.writeLong(object.getBirthDate().getTime()); } public Person read(Kryo kryo, Input input, Class type) { Person person = new Person(); person.setName(input.readString()); long birthDate = input.readLong(); person.setBirthDate(new Date(birthDate)); person.setAge(calculateAge(birthDate)); return person; } private int calculateAge(long birthDate) { // Some custom logic return 18; } }

Sekarang, mari kita uji:

@Test public void givenPerson_whenUsingCustomSerializer_thenReadCorrectly() { Person person = new Person(); person.setAge(0); kryo.register(Person.class, new PersonSerializer()); kryo.writeObject(output, person); output.close(); Person readPerson = kryo.readObject(input, Person.class); input.close(); assertEquals(readPerson.getName(), "John Doe"); assertEquals(readPerson.getAge(), 18); }

Perhatikan bahawa bidang umur sama dengan 18, walaupun kita menetapkannya sebelumnya ke 0.

Kami juga dapat menggunakan anotasi @DefaultSerializer untuk memberi tahu Kryo bahawa kami ingin menggunakan PersonSerializer setiap kali ia diperlukan untuk menangani objek Person . Ini membantu mengelakkan kaedah panggilan ke daftar () :

@DefaultSerializer(PersonSerializer.class) public class Person implements KryoSerializable { // ... }

Untuk pilihan kedua, mari ubah suai kelas Person kami untuk memperluaskan antara muka KryoSerializable :

public class Person implements KryoSerializable { // ... public void write(Kryo kryo, Output output) { output.writeString(name); // ... } public void read(Kryo kryo, Input input) { name = input.readString(); // ... } }

Oleh kerana kes ujian untuk pilihan ini sama dengan yang sebelumnya, tidak disertakan di sini. Walau bagaimanapun, anda boleh mendapatkannya dalam kod sumber untuk artikel ini.

4.3. Serializer Java

Dalam kes sporadis, Kryo tidak akan dapat membuat siri kelas. Jika ini terjadi, dan menulis serializer khusus bukan pilihan, kita dapat menggunakan mekanisme serialisasi Java standard menggunakan JavaSerializer . Ini memerlukan kelas menerapkan antara muka Serializable seperti biasa.

Berikut adalah contoh yang menggunakan serializer yang disebutkan di atas:

public class ComplexObject implements Serializable { private String name = "Bael"; // standard getters and setters }
@Test public void givenJavaSerializable_whenSerializing_thenReadCorrectly() { ComplexClass complexObject = new ComplexClass(); kryo.register(ComplexClass.class, new JavaSerializer()); kryo.writeObject(output, complexObject); output.close(); ComplexClass readComplexObject = kryo.readObject(input, ComplexClass.class); input.close(); assertEquals(readComplexObject.getName(), "Bael"); }

5. Kesimpulan

Dalam tutorial ini, kami meneroka ciri-ciri perpustakaan Kryo yang paling terkenal.

Kami menyusun beberapa objek sederhana dan menggunakan kelas FieldSerializer untuk menangani objek khusus. Kami juga membuat serializer khusus dan menunjukkan bagaimana untuk kembali ke mekanisme serialisasi Java standard jika diperlukan.

Seperti biasa, kod sumber lengkap untuk artikel ini boleh didapati di Github.