JavaRush /Kurslar /All lectures for AZ purposes /Spring-də Tip Dəyişməsi

Spring-də Tip Dəyişməsi

All lectures for AZ purposes
Səviyyə , Dərs
Mövcuddur

Spring 3-də core.convert paketi təqdim edildi ki, bu da ümumi tip dəyişmə sistemi təmin edir. Sistem, mənbə kodunun tip dəyişməsini həyata keçirmək üçün SPI (xidmət təmin edici interfeysi) və API interfeysi təyin edir. Spring konteynerində bu sistemi xüsusiyyətlərin istənilən tiplərini təmin etmək üçün hissələrin dəyər sətirlərinin çevrilməsi üçün PropertyEditor əvəzinə istifadə edə bilərsiniz. Eyni zamanda, tip dəyişmənin tələb olunduğu hər hansı tətbiqin hər hansı bir yerində bu API interfeysini də istifadə edə bilərsiniz.

SPI interfeysi Converter

Tip dəyişmə məntiqini həyata keçirmək üçün SPI interfeysi sadə və ciddi tipli, interfeys təyinində göstərildiyi kimi:

package org.springframework.core.convert.converter;
public interface Converter<S, T> {
    T convert(S source);
}

Öz çevricinizi yaratmaq üçün Converter interfeysini həyata keçirərək S vasitəsilə çevirdiyiniz tip və T ilə çevirdiyiniz tip kimi parametrizə edin. Belə çevriciləri də asanlıqla istifadə edə bilərsiniz, əgər S kolleksiyasını və ya massivini T kolleksiyası və ya massivinə çevirmək lazımdırsa, əgər ki, array və ya kolleksiya çevricisi də qeydiyyatdan keçmişdirsə (bu həmçinin DefaultConversionService vasitəsilə standart olaraq təmin edilir).

Hər bir convert(S) çağırışı üçün mənbə arqumenti heç vaxt boş (null) deyil. Sizin Converter dəyişmə uğurlu olmadığında hər hansı bir yoxlanılmayan istisna verə bilər. Xüsusilə, o, səhv mənbə dəyərini bildirmək üçün IllegalArgumentException istisnası verməlidir. Converter implementasiyanızın təhlukəsiz axınlı olmasına diqqət edin.

core.convert.support paketində bir neçə rahat çevrici həyata keçirilməsi təmin edilib. Bunlara sətirlərdən rəqəmlərə və digər ümumi tiplərə çevricilər daxildir. Aşağıdakı siyahı Converter-in tipik bir həyata keçirilməsi olan StringToInteger sinifini göstərir:

package org.springframework.core.convert.support;
final class StringToInteger implements Converter<String, Integer> {
    public Integer convert(String source) {
        return Integer.valueOf(source);
    }
}

ConverterFactory istifadə edilməsi

Bütün siniflər iyerarxiyası üçün tip çevirmə məntiqini mərkəzləşdirmək vacibdirsə (məsələn, String obyektlərindən Enum obyektlərinə çevirmə zamanı), ConverterFactory həyata keçirə bilərsiniz, aşağıdakı nümunədə göstərildiyi kimi:

package org.springframework.core.convert.converter;
public interface ConverterFactory<S, R> {
    <T extends R> Converter<S, T> getConverter(Class<T> targetType);
}

S-ni çevirdiyiniz tip olaraq, R-ni isə çevrilə biləcək siniflər diapazonunu müəyyən edən əsas tip olaraq parametrizə edin. Daha sonra getConverter(Class<T>) həyata keçirin, harada ki, T R-nin subclassıdır.

Məsələn, StringToEnumConverterFactory nəzər salaq:

package org.springframework.core.convert.support;
final class StringToEnumConverterFactory implements ConverterFactory<String, Enum> {
    public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {
        return new StringToEnumConverter(targetType);
    }
    private final class StringToEnumConverter<T extends Enum> implements Converter<String, T> {
        private Class<T> enumType;
        public StringToEnumConverter(Class<T> enumType) {
            this.enumType = enumType;
        }
        public T convert(String source) {
            return (T) Enum.valueOf(this.enumType, source.trim());
        }
    }
}

GenericConverter istifadə edilməsi

Əgər mürəkkəb Converter implementasiyasına ehtiyacınız varsa, GenericConverter interfeysindən istifadə edin. GenericConverter daha çevik, lakin Converterdən daha az ciddi tipli imzaya malikdir və bir neçə mənbə və hədəf tipi arasında çevirməni dəstəkləyir. Bundan əlavə, GenericConverter mənbə və hədəf sahəsinin kontekstini istifadə üçün təqdim edir. Bu kontekst, sahə anotasiya əsasında və ya sahənin imzasında elan olunan ümumi məlumatlar əsasında tip çevirməyə imkan verir. Aşağıdakı siyahı GenericConverter interfeysinin təyinini göstərir:

package org.springframework.core.convert.converter;
public interface GenericConverter {
    public Set<ConvertiblePair> getConvertibleTypes();
    Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
}

GenericConverter-i həyata keçirmək üçün getConvertibleTypes() funksiyası dəstəklənən mənbə→hədəf tip cütlərini qaytarmalıdır. Daha sonra convert(Object, TypeDescriptor, TypeDescriptor) həyata keçirin ki, çevirmə məntiqi əlavə olunsun. Mənbə TypeDescriptor mənbə sahəsindəki şəkildən tipik qiymətə giriş imkanı təqdim edir. Hədəf TypeDescriptor isə çevrilmiş qiyməti təyin edilməsi gərək olan sahəyə giriş imkanı yaradır.

Yaxşı bir GenericConverter nümunəsi Java massivini kolleksiyaya çevirən bir çevricidir. Belə bir ArrayToCollectionConverter hədəf kolleksiyasının tip elementini təyin etmək üçün kolleksiya tipini bildirən sahənin öz-özünü təhlilini yerinə yetirir. Bu, kolleksiyanın hədəf sahəyə təyin olunmazdan əvvəl mənbə massivinin hər bir elementini kolleksiya element tipinə çevirmək imkanı verir.

GenericConverter daha mürəkkəb bir SPI interfeysi olduğuna görə, onu yalnız zərurət olduqda istifadə etməliyik. Tip dəyişmə üçün əsas ehtiyaclar üçün Converter və ya ConverterFactory istifadə edin.

ConditionalGenericConverter istifadə edilməsi

Bəzən Converter-in yalnız müəyyən şərt yerinə yetirildikdə işə salınması lazım olur. Məsələn, hədəf sahədə müəyyən anotasiya varsa, Converter-i işə salmağınız lazım ola bilər və ya hədəf sinifdə müəyyən bir metod müəyyən olunarsa (məsələn, static valueOf metodu), həmin Converter-i işə salmaq lazım ola bilər. ConditionalGenericConverter belə xüsusi uyğunluq kriteriyalarını təyin etməyə imkan verən GenericConverterConditionalConverter interfeyslərinin birləşməsidir:

public interface ConditionalConverter {
    boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);
}
public interface ConditionalGenericConverter extends GenericConverter, ConditionalConverter {
}

Yaxşı bir ConditionalGenericConverter nümunəsi, qalıcı bir obyektin identifikatorunu obyektin göstəricisinə çevirən IdToEntityConverter-dir. Belə bir IdToEntityConverter yalnız hədəf obyekt tipi statik axtarış metodu (məsələn, findAccount(Long)) elan edirsə, uyğun ola bilər. matches(TypeDescriptor, TypeDescriptor) realizasiyasında həmin axtarış metodunun yoxlanışını edə bilərsiniz.

ConversionService API

ConversionService proqram işləmə zamanı mənbə kodunun tip dəyişmə məntiqini həyata keçirmək üçün birləşmiş bir API təyin edir. Çevricilər adətən növbəti fasad interfeysindən işə salınır:

package org.springframework.core.convert;
public interface ConversionService {
    boolean canConvert(Class<?> sourceType, Class<?> targetType);
    <T> T convert(Object source, Class<T> targetType);
    boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType);
    Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
}

Çoğu ConversionService realizasiyası eyni zamanda çevriciləri qeyd etmək üçün SPI interfeys təqdim edən ConverterRegistry-i həyata keçirir. Daxili olaraq ConversionService realizasiyası qeydiyyatdan keçmiş çevricilərinə tip dəyişmə məntiqini həyata keçirmək üçün nümayəndəlik edir.

ConversionService-in etibarlı realizasiyası core.convert.support paketində təqdim edilir. GenericConversionService əksər mühitlər üçün uyğun ümumi məqsədli bir realizasiyadır. ConversionServiceFactory ümumi ConversionService konfiqurasiyalarını yaratmaq üçün rahat bir fabrik təqdim edir.

ConversionService konfiqurasiyası

ConversionService bir halda saxlanılan obyekt deyil, hansı ki, tətbiq işə salındıqda yaradılır və müxtəlif axınlar arasında paylaşılır. Spring tətbiqində ConversionService oxşar tətbiqçinin hər bir Spring konteyneri (və ya ApplicationContext) üçün konfiqurasiya edilir. Spring bu ConversionService-i müəyyən edir və hər dəfə çərçivə tip dəyişməsi etməsi lazım olduqda istifadə edir. Həmçinin, bu ConversionService-i istənilən birinizə dərhal daxil edə bilərsiniz.

Əgər Spring-də bir ConversionService qeydiyyatdan keçməmişsə, o zaman PropertyEditor-ə əsaslanan orijinal sistem istifadə olunur.

Spring-də standart bir ConversionService qeydiyyatdan keçirmək üçün aşağıdakı bean təyinini id kimi conversionService göstərərək əlavə edin:

<bean id="conversionService"
    class="org.springframework.context.support.ConversionServiceFactoryBean"/>

Standart ConversionService sətirlər, rəqəmlər, enumlar, kolleksiyalar, xəritələr və digər yaygın tipləri çevirmə qabiliyyətinə malikdir. Varsayılan çevriciləri öz xüsusi çevricilərinizlə tamamlamaq və ya əvəz etmək üçün converters əmlakını təyin edin. Əmlak dəyərləri hər hansı bir Converter, ConverterFactory və ya GenericConverter interfeysini həyata keçirə bilər.

<bean id="conversionService"
        class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="example.MyCustomConverter"/>
        </set>
    </property>
</bean>

Spring MVC tətbiqində ConversionService tez-tez istifadə olunur.

Bəzi hallarda çevirmə zamanı formatlaşdırmadan istifadə etmək olar.

ConversionService-in proqramlı istifadəsi

ConversionService nümunəsi ilə düyməli şəkildə işləmək üçün, onu başqa hər hansı bir bean kimi daxil edin. Aşağıdakı nümunə, bunu necə edəcəyinizi göstərir:

Java
@Service
public class MyService {
    public MyService(ConversionService conversionService) {
        this.conversionService = conversionService;
    }
    public void doIt() {
        this.conversionService.convert(...)
    }
}
Kotlin
@Service
class MyService(private val conversionService: ConversionService) {
    fun doIt() {
        conversionService.convert(...)
    }
}

Çoğu hallarda, convert metodunu istifadə edərək, targetType təyin etməklə kifayətlənə bilərsiniz, ancaq o, daha mürəkkəb tiplərlə, məsələn, parametrlənmiş elementin kolleksiyası ilə işləməyəcək. Məsələn, Integer tipli List-i String tipli List-ə çevirmək lazımdırsa, mənbə və hədəf tiplərinin formal təyinini təqdim etməlisiniz.

Xoşbəxtlikdən, TypeDescriptor bunu asanlıqla həyata keçirmək üçün müxtəlif seçimlər təqdim edir, aşağıdakı nümunədə göstərildiyi kimi:

Java
DefaultConversionService cs = new DefaultConversionService();
List<Integer> input = ...
cs.convert(input,
    TypeDescriptor.forObject(input), // List<Integer> tipli təsvir
    TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(String.class)));
Kotlin
val cs = DefaultConversionService()
val input: List<Integer> = ...
cs.convert(input,
        TypeDescriptor.forObject(input), // List<Integer> tipli təsvir
        TypeDescriptor.collection(List::class.java, TypeDescriptor.valueOf(String::class.java)))

Qeyd edək ki, DefaultConversionService əksər mühitlər üçün uyğun olan çevriciləri avtomatik qaydada qeyd edir. Bunlara kolleksiya çevriciləri, skalar çevricilər və Object-to-String əsas çevriciləri daxildir. Eyni çevriciləri herhangi bir ConverterRegistry-də DefaultConversionService sinfinin statik addDefaultConverters metodu ilə qeyd edə bilərsiniz.

Dəyər tipləri üçün çevricilər massivlər və kolleksiyalar üçün təkrar istifadə olunur, ona görə də Collection tipi S ilə Collection tipi T arasında çevrici yaratmağa ehtiyac yoxdur, əgər standart kolleksiya emalı uyğun olacaqsa.

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION