Inleiding tot Kryo

1. Overzicht

Kryo is een Java-serialisatieframework met de nadruk op snelheid, efficiëntie en een gebruiksvriendelijke API.

In dit artikel zullen we de belangrijkste kenmerken van het Kryo-framework onderzoeken en voorbeelden implementeren om de mogelijkheden ervan te demonstreren.

2. Maven Afhankelijkheid

Het eerste dat we moeten doen, is de kryo afhankelijkheid van onze pom.xml:

 com.esotericsoftware kryo 4.0.1 

De nieuwste versie van dit artefact is te vinden op Maven Central.

3. Kryo Basics

Laten we beginnen met te kijken hoe Kryo werkt en hoe we er objecten mee kunnen serialiseren en deserialiseren.

3.1. Invoering

Het framework biedt de Kryo class als het belangrijkste toegangspunt voor al zijn functionaliteit.

Deze klasse orkestreert het serialisatieproces en wijst klassen toe aan Serializer instanties die de details afhandelen van het converteren van de grafiek van een object naar een byte-weergave.

Zodra de bytes gereed zijn, worden ze naar een stream geschreven met behulp van een Uitvoer voorwerp. Op deze manier kunnen ze worden opgeslagen in een bestand, een database of via het netwerk worden verzonden.

Later, wanneer het object nodig is, wordt een Invoer instantie wordt gebruikt om die bytes te lezen en ze in Java-objecten te decoderen.

3.2. Objecten serialiseren

Laten we, voordat we in voorbeelden duiken, eerst een hulpprogramma-methode maken om enkele variabelen te initialiseren die we voor elk testgeval in dit artikel zullen gebruiken:

@Before public void init () {kryo = nieuwe Kryo (); output = nieuwe uitvoer (nieuwe FileOutputStream ("file.dat")); input = nieuwe invoer (nieuwe FileInputStream ("file.dat")); }

Nu kunnen we kijken hoe gemakkelijk het is om een ​​object te schrijven en te lezen met Kryo:

@Test openbare leegte gegevenObject_whenSerializing_thenReadCorrectly () {Object someObject = "Een string"; kryo.writeClassAndObject (output, someObject); output.close (); Object theObject = kryo.readClassAndObject (invoer); input.close (); assertEquals (theObject, "Some string"); }

Let op de oproep naar de dichtbij() methode. Dit is nodig sinds Uitvoer en Invoer klassen erven van OutputStream en InputStream respectievelijk.

Het serialiseren van meerdere objecten is op dezelfde manier eenvoudig:

@Test openbare ongeldige gegevenObjects_whenSerializing_thenReadCorrectly () {String someString = "Meerdere objecten"; Datum someDate = nieuwe datum (915170400000L); kryo.writeObject (output, someString); kryo.writeObject (output, someDate); output.close (); String readString = kryo.readObject (input, String.class); Datum readDate = kryo.readObject (input, Date.class); input.close (); assertEquals (readString, "Meerdere objecten"); assertEquals (readDate.getTime (), 915170400000L); }

Merk op dat we de juiste klasse doorgeven aan de readObject () methode, dit maakt onze code cast-vrij.

4. Serializers

In deze sectie laten we zien welke Serializers zijn al beschikbaar, en dan maken we onze eigen.

4.1. Standaard Serializers

Wanneer Kryo een object serialiseert, creëert het een instantie van een eerder geregistreerd Serializer class om de conversie naar bytes uit te voeren. Dit worden standaardserializers genoemd en kunnen zonder enige installatie van onze kant worden gebruikt.

De bibliotheek biedt al verschillende van dergelijke serializers die primitieven, lijsten, kaarten, enums, enz. Verwerken. Als er geen serialisator wordt gevonden voor een bepaalde klasse, dan is een FieldSerializer wordt gebruikt, die bijna elk type object aankan.

Laten we eens kijken hoe dit eruit ziet. Laten we eerst 'een Persoon klasse:

openbare klasse Persoon {private String name = "John Doe"; privé int leeftijd = 18; private date birthDate = nieuwe datum (933191282821L); // standaard constructeurs, getters en setters}

Laten we nu een object uit deze klasse schrijven en het dan teruglezen:

@Test openbare ongeldig gegevenPerson_whenSerializing_thenReadCorrectly () {Persoon persoon = nieuwe persoon (); kryo.writeObject (output, persoon); output.close (); Persoon readPerson = kryo.readObject (input, Person.class); input.close (); assertEquals (readPerson.getName (), "John Doe"); }

Merk op dat we niets hoefden op te geven om een Persoon object sinds een FieldSerializer wordt automatisch voor ons aangemaakt.

4.2. Aangepaste serialisatoren

Als we meer controle over het serialisatieproces nodig hebben, hebben we twee opties; we kunnen onze eigen schrijven Serializer class en registreer het bij Kryo of laat de class de serialisering zelf afhandelen.

Laten we, om de eerste optie te demonstreren, een klasse maken die zich uitbreidt Serializer:

public class PersonSerializer breidt Serializer uit {public void write (Kryo kryo, Output output, Person object) {output.writeString (object.getName ()); output.writeLong (object.getBirthDate (). getTime ()); } openbare persoon gelezen (Kryo kryo, invoerinvoer, klassetype) {Persoon persoon = nieuwe persoon (); person.setName (input.readString ()); lange geboortedatum = input.readLong (); person.setBirthDate (nieuwe datum (geboortedatum)); person.setAge (berekenAge (birthDate)); terugkeer persoon; } private int berekenAge (long birthDate) {// Sommige aangepaste logica retourneren 18; }}

Laten we het nu eens testen:

@Test openbare ongeldig gegevenPerson_whenUsingCustomSerializer_thenReadCorrectly () {Persoon persoon = nieuwe persoon (); person.setAge (0); kryo.register (Person.class, nieuwe PersonSerializer ()); kryo.writeObject (output, persoon); output.close (); Persoon readPerson = kryo.readObject (input, Person.class); input.close (); assertEquals (readPerson.getName (), "John Doe"); assertEquals (readPerson.getAge (), 18); }

Merk op dat de leeftijd veld is gelijk aan 18, ook al hebben we het eerder op 0 gezet.

We kunnen ook de @DefaultSerializer annotatie om Kryo te laten weten dat we de PersonSerializer elke keer dat het een Persoon voorwerp. Dit helpt om de oproep naar de registreren() methode:

@DefaultSerializer (PersonSerializer.class) openbare klasse Persoon implementeert KryoSerializable {// ...}

Laten we voor de tweede optie onze Persoon klasse om de KryoSerializable koppel:

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

Omdat de testcase voor deze optie gelijk is aan een vorige, wordt deze hier niet opgenomen. U kunt het echter vinden in de broncode van dit artikel.

4.3. Java Serializer

In sporadische gevallen kan Kryo een klasse niet serialiseren. Als dit gebeurt en het schrijven van een aangepaste serialisator geen optie is, kunnen we het standaard Java-serialisatiemechanisme gebruiken met een JavaSerializer. Dit vereist dat de klasse het Serialiseerbaar interface zoals gewoonlijk.

Hier is een voorbeeld dat de bovengenoemde serialisator gebruikt:

openbare klasse ComplexObject implementeert Serializable {private String name = "Bael"; // standaard getters en setters}
@Test openbare leegte gegevenJavaSerializable_whenSerializing_thenReadCorrectly () {ComplexClass complexObject = nieuwe ComplexClass (); kryo.register (ComplexClass.class, nieuwe JavaSerializer ()); kryo.writeObject (uitvoer, complexObject); output.close (); ComplexClass readComplexObject = kryo.readObject (input, ComplexClass.class); input.close (); assertEquals (readComplexObject.getName (), "Bael"); }

5. Conclusie

In deze tutorial hebben we de meest opvallende kenmerken van de Kryo-bibliotheek onderzocht.

We hebben meerdere eenvoudige objecten geserialiseerd en de FieldSerializer klasse om te gaan met een aangepaste. We hebben ook een aangepaste serialisator gemaakt en laten zien hoe u indien nodig kunt terugvallen op het standaard Java-serialisatiemechanisme.

Zoals altijd is de volledige broncode voor dit artikel te vinden op Github.


$config[zx-auto] not found$config[zx-overlay] not found