Introduktion til Kryo

1. Oversigt

Kryo er en Java-serialiseringsramme med fokus på hastighed, effektivitet og en brugervenlig API.

I denne artikel udforsker vi nøglefunktionerne i Kryo-rammen og implementerer eksempler for at fremvise dens muligheder.

2. Maven-afhængighed

Den første ting, vi skal gøre, er at tilføje kryo afhængighed af vores pom.xml:

 com.esotericsoftware kryo 4.0.1 

Den seneste version af denne artefakt kan findes på Maven Central.

3. Kryo Basics

Lad os starte med at se på, hvordan Kryo fungerer, og hvordan vi kan serieisere og deserialisere objekter med det.

3.1. Introduktion

Rammen giver Kryo klasse som det vigtigste indgangssted for al dens funktionalitet.

Denne klasse orkestrerer serieiseringsprocessen og kortlægger klasser til Serializer forekomster, der håndterer detaljerne i konvertering af et objekts graf til en byterepræsentation.

Når byte er klar, skrives de til en stream ved hjælp af en Produktion objekt. På denne måde kan de gemmes i en fil, en database eller overføres via netværket.

Senere, når objektet er nødvendigt, an Indgang instans bruges til at læse disse bytes og afkode dem til Java-objekter.

3.2. Serialisering af objekter

Før vi dykker ned i eksempler, skal vi først oprette en hjælpemetode til at initialisere nogle variabler, vi bruger til hver testtilfælde i denne artikel:

@Før offentlig ugyldig init () {kryo = ny Kryo (); output = ny output (ny FileOutputStream ("file.dat")); input = ny input (ny FileInputStream ("file.dat")); }

Nu kan vi se, hvor let det er at skrive og læse et objekt ved hjælp af Kryo:

@Test offentligt ugyldigt givenObject_whenSerializing_thenReadCorrectly () {Object someObject = "Nogle streng"; kryo.writeClassAndObject (output, someObject); output.close (); Gør objekt mod objektet = kryo.readClassAndObject (input); input.close (); assertEquals (theObject, "Some string"); }

Læg mærke til opkaldet til tæt() metode. Dette er nødvendigt siden Produktion og Indgang klasser arver fra OutputStream og InputStream henholdsvis.

Serialisering af flere objekter er ligeledes ligetil:

@ Test offentligt ugyldigt givenObjects_whenSerializing_thenReadCorrectly () {String someString = "Flere objekter"; Date someDate = new Date (915170400000L); kryo.writeObject (output, someString); kryo.writeObject (output, someDate); output.close (); String readString = kryo.readObject (input, String.class); Dato readDate = kryo.readObject (input, Date.class); input.close (); assertEquals (readString, "Flere objekter"); assertEquals (readDate.getTime (), 915170400000L); }

Bemærk, at vi sender den passende klasse til readObject () metode gør dette vores kode kastfri.

4. Serializers

I dette afsnit viser vi hvilke Serializers er allerede tilgængelige, og så opretter vi vores egne.

4.1. Standard Serializers

Når Kryo serieliserer et objekt, opretter det en forekomst af en tidligere registreret Serializer klasse til at udføre konvertering til byte. Disse kaldes standard serialiserere og kan bruges uden opsætning fra vores side.

Biblioteket leverer allerede adskillige sådanne serialiseringer, der behandler primitiver, lister, kort, enums osv. Hvis der ikke findes nogen serializer for en given klasse, så FieldSerializer bruges, som kan håndtere næsten alle typer objekter.

Lad os se, hvordan det ser ud. Lad os først oprette en Person klasse:

offentlig klasse person {private String name = "John Doe"; privat int alder = 18; privat fødselsdato = ny dato (933191282821L); // standardkonstruktører, getters og settere}

Lad os nu skrive et objekt fra denne klasse og derefter læse det tilbage:

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

Bemærk, at vi ikke behøvede at specificere noget for at serieisere en Person objekt siden en FieldSerializer oprettes automatisk for os.

4.2. Custom Serializers

Hvis vi har brug for mere kontrol over serieiseringsprocessen, har vi to muligheder; vi kan skrive vores egne Serializer klasse og registrer det med Kryo eller lad klassen håndtere serialiseringen alene.

For at demonstrere den første mulighed, lad os oprette en klasse, der udvides Serializer:

offentlig klasse PersonSerializer udvider Serializer {public void write (Kryo kryo, Output output, Person object) {output.writeString (object.getName ()); output.writeLong (object.getBirthDate (). getTime ()); } offentlig person læst (Kryo kryo, Input input, Klassetype) {Person person = ny person (); person.setName (input.readString ()); lang fødselsdato = input.readLong (); person.setBirthDate (ny dato (fødselsdato)); person.setAge (beregneAge (fødselsdato)); tilbagevendende person } privat int beregneAge (lang fødselsdato) {// Noget tilpasset logik returnerer 18; }}

Lad os nu prøve det:

@ Test offentligt ugyldigt givenPerson_whenUsingCustomSerializer_thenReadCorrectly () {Person person = ny person (); person.setAge (0); kryo.register (Person.class, ny 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); }

Bemærk, at alder felt er lig med 18, selvom vi tidligere har sat det til 0.

Vi kan også bruge @DefaultSerializer kommentar for at lade Kryo vide, at vi vil bruge PersonSerializer hver gang det skal håndtere en Person objekt. Dette hjælper med at undgå opkald til Tilmeld() metode:

@DefaultSerializer (PersonSerializer.class) offentlig klasse Person implementerer KryoSerializable {// ...}

For den anden mulighed, lad os ændre vores Person klasse for at udvide KryoSerializable grænseflade:

public class Person implementerer KryoSerializable {// ... public void write (Kryo kryo, Output output) {output.writeString (name); // ...} offentlig ugyldig læsning (Kryo kryo, input input) {name = input.readString (); // ...}}

Da testsagen for denne mulighed er lig med en tidligere, er den ikke inkluderet her. Du kan dog finde den i kildekoden til denne artikel.

4.3. Java Serializer

I sporadiske tilfælde vil Kryo ikke være i stand til at serieisere en klasse. Hvis dette sker, og det ikke er en mulighed at skrive en tilpasset serializer, kan vi bruge standard Java-serialiseringsmekanismen ved hjælp af en JavaSerializer. Dette kræver, at klassen implementerer Serialiserbar interface som normalt.

Her er et eksempel, der bruger den førnævnte serializer:

offentlig klasse ComplexObject implementerer Serializable {private String name = "Bael"; // standard getters og setter}
@Test offentlig ugyldighed givetJavaSerializable_whenSerializing_thenReadCorrectly () {ComplexClass complexObject = ny ComplexClass (); kryo.register (ComplexClass.class, ny JavaSerializer ()); kryo.writeObject (output, complexObject); output.close (); ComplexClass readComplexObject = kryo.readObject (input, ComplexClass.class); input.close (); assertEquals (readComplexObject.getName (), "Bael"); }

5. Konklusion

I denne vejledning udforskede vi de mest bemærkelsesværdige funktioner i Kryo-biblioteket.

Vi serierede flere enkle objekter og brugte FieldSerializer klasse til at håndtere en brugerdefineret. Vi oprettede også en brugerdefineret serializer og demonstrerede, hvordan man om nødvendigt kan falde tilbage til standard Java-serialiseringsmekanismen.

Som altid kan den komplette kildekode til denne artikel findes på Github.