Uvod u Kryo

1. Pregled

Kryo je Java serializacijski okvir s naglaskom na brzinu, učinkovitost i API-ju prilagođen korisniku.

U ovom ćemo članku istražiti ključne značajke Kryo okvira i primijeniti primjere kako bismo prikazali njegove mogućnosti.

2. Ovisnost Mavena

Prvo što moramo učiniti je dodati kryo ovisnost o našoj pom.xml:

 com.esotericsoftware kryo 4.0.1 

Najnovija verzija ovog artefakta može se naći na Maven Central.

3. Osnove Kryo-a

Krenimo od gledanja kako Kryo radi i kako njime možemo serializirati i deserializirati objekte.

3.1. Uvod

Okvir pruža Kryo klasa kao glavna ulazna točka za svu njezinu funkcionalnost.

Ovaj razred orkestrira postupak serializacije i preslikava nastavu u Serijalizator instance koje obrađuju detalje pretvaranja grafa objekta u bajtnu reprezentaciju.

Jednom kad su bajtovi spremni, zapisuju se u tok pomoću Izlaz objekt. Na taj se način mogu pohraniti u datoteku, bazu podataka ili prenijeti mrežom.

Kasnije, kada je objekt potreban, an Ulazni instanca se koristi za čitanje tih bajtova i njihovo dekodiranje u Java objekte.

3.2. Serijaliziranje objekata

Prije uranjanja u primjere, prvo stvorimo uslužni metod za inicijalizaciju nekih varijabli koje ćemo koristiti za svaki testni slučaj u ovom članku:

@Prije javne void init () {kryo = novi Kryo (); output = novi izlaz (novi FileOutputStream ("file.dat")); input = novi ulaz (novi FileInputStream ("file.dat")); }

Sada možemo pogledati kako je jednostavno pisati i čitati objekt koristeći Kryo:

@Test javna praznina givenObject_whenSerializing_thenReadCorrect () {Object someObject = "Neki niz"; kryo.writeClassAndObject (izlaz, nekiObject); output.close (); Objekt theObject = kryo.readClassAndObject (ulaz); input.close (); assertEquals (theObject, "Neki niz"); }

Primijetite poziv Zatvoriti() metoda. Ovo je potrebno od Izlaz i Ulazni klase nasljeđuju iz Izlazni tok i InputStream odnosno.

Serijalizacija više objekata slično je jednostavna:

@Test javna praznina givenObjects_whenSerializing_thenReadCorrect () {String someString = "Višestruki objekti"; Datum nekiDatum = novi datum (915170400000L); kryo.writeObject (izlaz, someString); kryo.writeObject (output, someDate); output.close (); Niz readString = kryo.readObject (ulaz, String.class); Datum čitanjaDatum = kryo.readObject (ulaz, Date.class); input.close (); assertEquals (readString, "Više objekata"); assertEquals (readDate.getTime (), 915170400000L); }

Primijetite da predajemo odgovarajući razred na readObject () metodom, ovo čini naš kod bez emitiranja.

4. Serijalizatori

U ovom ćemo odjeljku pokazati koji Serijalizatori su već dostupni, a zatim ćemo stvoriti vlastiti.

4.1. Zadani serilizatori

Kad Kryo serializira objekt, on stvara instancu prethodno registriranog Serijalizator klase da izvrši pretvorbu u bajtove. Oni se nazivaju zadanim serializatorima i mogu se koristiti bez ikakvih postavki s naše strane.

Biblioteka već nudi nekoliko takvih serializatora koji obrađuju primitive, popise, mape, enume itd. Ako za datu klasu nije pronađen serializator, tada FieldSerializer koristi se koji može rukovati gotovo bilo kojom vrstom predmeta.

Da vidimo kako ovo izgleda. Prvo, napravimo a Osoba razred:

javna klasa Osoba {private String name = "John Doe"; privatno int doba = 18; privatni Datum datum rođenja = novi datum (933191282821L); // standardni konstruktori, getteri i postavljači}

A sada, napišite objekt iz ove klase, a zatim ga pročitajte natrag:

@Test javna praznina givenPerson_whenSerializing_thenReadCorrect () {Person person = new Person (); kryo.writeObject (izlaz, osoba); output.close (); Osoba readPerson = kryo.readObject (ulaz, Person.class); input.close (); assertEquals (readPerson.getName (), "John Doe"); }

Primijetite da nismo morali navesti ništa da bismo serializirali a Osoba objekt od a FieldSerializer stvara se automatski za nas.

4.2. Prilagođeni serijalizatori

Ako trebamo veću kontrolu nad postupkom serializacije, imamo dvije mogućnosti; možemo sami napisati Serijalizator klase i registrirajte je kod Kryoa ili pustite da klasa sama riješi serializaciju.

Da bismo demonstrirali prvu opciju, stvorimo klasu koja se proteže Serijalizator:

javna klasa PersonSerializer proširuje Serializer {public void write (Kryo kryo, Output output, Person object) {output.writeString (object.getName ()); output.writeLong (object.getBirthDate (). getTime ()); } javno Čitanje osobe (Kryo kryo, ulazni ulaz, vrsta klase) {Osoba osoba = nova Osoba (); person.setName (input.readString ()); long birthDate = input.readLong (); person.setBirthDate (novi datum (datum rođenja)); person.setAge (izračunajAge (datum rođenja)); osoba za povratak; } private int CalcuAge (long birthDate) {// Neka prilagođena logika vraća 18; }}

Ajmo sada na test:

@Test javna praznina givenPerson_whenUsingCustomSerializer_thenReadCorrect () {Person person = new Person (); person.setAge (0); kryo.register (Person.class, novi PersonSerializer ()); kryo.writeObject (izlaz, osoba); output.close (); Osoba readPerson = kryo.readObject (ulaz, Person.class); input.close (); assertEquals (readPerson.getName (), "John Doe"); assertEquals (readPerson.getAge (), 18); }

Primijetite da dob polje jednako je 18, iako smo ga prethodno postavili na 0.

Također možemo koristiti @DefaultSerializer napomena da Kryo zna da želimo koristiti PersonSerializer svaki put kad treba obraditi a Osoba objekt. To pomaže u izbjegavanju poziva na Registar() metoda:

@DefaultSerializer (PersonSerializer.class) javna klasa Osoba implementira KryoSerializable {// ...}

Za drugu opciju, izmijenimo našu Osoba razred za proširenje KryoSerializable sučelje:

javna klasa Person implementira KryoSerializable {// ... public void write (Kryo kryo, Output output) {output.writeString (name); // ...} javno prazno čitanje (Kryo kryo, ulazni ulaz) {name = input.readString (); // ...}}

Budući da je testni slučaj za ovu opciju jednak prethodnom, ovdje nije uključen. Međutim, možete ga pronaći u izvornom kodu za ovaj članak.

4.3. Java Serializer

U sporadičnim slučajevima, Kryo neće moći serializirati razred. Ako se to dogodi, a pisanje prilagođenog serializatora nije opcija, možemo koristiti standardni mehanizam Java serializacije pomoću a JavaSerializer. To zahtijeva da klasa implementira Serijalizirati sučelje kao i obično.

Evo primjera koji koristi gore spomenuti serializator:

javna klasa ComplexObject implementira Serializable {private String name = "Bael"; // standardni geteri i postavljači}
@Test javna praznina givenJavaSerializable_whenSerializing_thenReadCorrect () {ComplexClass complexObject = new ComplexClass (); kryo.register (ComplexClass.class, novi JavaSerializer ()); kryo.writeObject (output, complexObject); output.close (); ComplexClass readComplexObject = kryo.readObject (ulaz, ComplexClass.class); input.close (); assertEquals (readComplexObject.getName (), "Bael"); }

5. Zaključak

U ovom uputstvu istražili smo najznačajnije značajke Kryo knjižnice.

Serijalizirali smo više jednostavnih objekata i koristili FieldSerializer razreda za rješavanje prilagođenog. Također smo stvorili prilagođeni serializator i pokazali kako se po potrebi vratiti na standardni mehanizam serializacije Java.

Kao i uvijek, cjeloviti izvorni kod za ovaj članak nalazi se na Githubu.