Pengantar Kryo

1. Ikhtisar

Kryo adalah framework serialisasi Java dengan fokus pada kecepatan, efisiensi, dan API yang ramah pengguna.

Dalam artikel ini, kita akan menjelajahi fitur-fitur utama dari kerangka Kryo dan menerapkan contoh untuk menunjukkan kemampuannya.

2. Ketergantungan Maven

Hal pertama yang perlu kita lakukan adalah menambahkan dependensi kryo ke pom.xml kita :

 com.esotericsoftware kryo 4.0.1 

Versi terbaru dari artefak ini dapat ditemukan di Maven Central.

3. Dasar-dasar Kryo

Mari kita mulai dengan melihat bagaimana Kryo bekerja dan bagaimana kita dapat membuat serial dan deserialisasi objek dengannya.

3.1. pengantar

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

Kelas ini mengatur proses serialisasi dan memetakan kelas ke instance Serializer yang menangani detail konversi grafik objek ke representasi byte.

Setelah byte siap, byte tersebut ditulis ke aliran menggunakan objek Output . Dengan cara ini mereka dapat disimpan dalam file, database, atau dikirim melalui jaringan.

Nanti, saat objek dibutuhkan, sebuah instance Input digunakan untuk membaca byte tersebut dan mendekodekannya menjadi objek Java.

3.2. Objek Serialisasi

Sebelum mempelajari contoh, pertama-tama mari buat metode utilitas untuk menginisialisasi beberapa variabel yang akan kita gunakan untuk setiap kasus pengujian di 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 sebuah 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 panggilan ke metode close () . Ini diperlukan karena kelas Output dan Input masing-masing mewarisi dari OutputStream dan InputStream .

Serialisasi beberapa objek juga sangat 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 bahwa kita meneruskan kelas yang sesuai ke metode readObject () , ini membuat kode kita bebas cast.

4. Serializers

Di bagian ini, kami akan menunjukkan Serializers mana yang sudah tersedia, dan kemudian kami akan membuatnya sendiri.

4.1. Serializers default

Ketika Kryo membuat serial objek, itu membuat instance dari kelas Serializer terdaftar sebelumnya untuk melakukan konversi ke byte. Ini disebut serializers default dan dapat digunakan tanpa pengaturan apa pun di pihak kami.

Library sudah menyediakan beberapa serializer yang memproses primitif, daftar, peta, enum, dll. Jika serializer tidak ditemukan untuk kelas tertentu, maka FieldSerializer digunakan, yang dapat menangani hampir semua jenis objek.

Mari kita lihat bagaimana tampilannya. Pertama, mari 'buat kelas Person :

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 kita tulis objek dari kelas ini dan kemudian membacanya kembali:

@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 bahwa kami tidak perlu menentukan apa pun untuk membuat serial objek Person karena FieldSerializer dibuat secara otomatis untuk kami.

4.2. Serializer Khusus

Jika kami membutuhkan lebih banyak kontrol atas proses serialisasi, kami memiliki dua opsi; kita dapat menulis kelas Serializer kita sendiri dan mendaftarkannya dengan Kryo atau membiarkan kelas tersebut menangani serialisasi dengan sendirinya.

Untuk mendemonstrasikan opsi pertama, mari buat kelas yang memperluas 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 bahwa bidang usia sama dengan 18, meskipun kita menyetelnya sebelumnya ke 0.

Kita juga dapat menggunakan anotasi @DefaultSerializer untuk memberi tahu Kryo bahwa kita ingin menggunakan PersonSerializer setiap kali ia perlu menangani objek Person . Ini membantu menghindari panggilan ke metode register () :

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

Untuk opsi kedua, mari ubah kelas Person untuk memperluas antarmuka 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(); // ... } }

Karena kasus uji untuk opsi ini sama dengan yang sebelumnya, tidak disertakan di sini. Namun, Anda dapat menemukannya di kode sumber untuk artikel ini.

4.3. Serializer Java

Dalam kasus sporadis, Kryo tidak akan dapat membuat serial kelas. Jika ini terjadi, dan menulis serializer kustom bukanlah pilihan, kita dapat menggunakan mekanisme serialisasi Java standar menggunakan JavaSerializer . Ini mengharuskan kelas mengimplementasikan antarmuka Serializable seperti biasa.

Berikut adalah contoh yang menggunakan serializer tersebut 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 menjelajahi fitur-fitur paling terkenal dari perpustakaan Kryo.

Kami membuat serial beberapa objek sederhana dan menggunakan kelas FieldSerializer untuk menangani objek khusus. Kami juga membuat serializer khusus dan mendemonstrasikan cara fallback ke mekanisme serialisasi Java standar jika diperlukan.

Seperti biasa, kode sumber lengkap untuk artikel ini dapat ditemukan di Github.