Spring 3 da core.convert paketi paydo bo‘ldi, u umumiy type konversiya tizimini taqdim etadi. Tizim type konversiya mantiqini amalga oshirish uchun SPI (xizmat ko‘rsatuvchi interfeysi) va loyihalash vaqtida type konversiyasini amalga oshiruvchi API-interfeysni belgilaydi. Spring konteynerida bu tizimdan PropertyEditor ni realizatsiya qilish alternatifi sifatida foydalanishingiz mumkin, binning xususiyat qiymatlarini kerakli xususiyat tyyplariga aylantirish uchun. Shuningdek, siz type konversiyasi talab qilinadigan joyda ilovangizning har qanday joyida ommaviy API-interfeysdan foydalanishingiz mumkin.
SPI-interfeys Converter
Type konversiya mantiqini amalga oshirish uchun SPI interfeysi sodda va kuchli tiplangan, quyidagi interfeys ta'rifida ko'rsatilganidek:
package org.springframework.core.convert.converter;
public interface Converter<S, T> {
T convert(S source);
}
O'zingizning konvertoringizni yaratish uchun Converter interfeysni amalga oshiring va S ni siz aylantirayotgan type sifatida va T ni siz aylantirayotgan type sifatida parametrlashtiring. Agarda S kolleksiyasini yoki massivini T massiviga yoki kolleksiyasiga aylantirish kerak bo‘lsa, bunday konverterdan tushunarli tarzda foydalanishingiz mumkin, agar massivlar yoki kolleksiyalar konvertori ham ro‘yxatdan o‘tkazilgan bo‘lsa (buni DefaultConversionService standart holatida amalga oshiradi).
Har bir convert(S) chaqirig'i uchun manba argumenti bo'sh emasligiga kafolat beriladi (null emas). Agarda konversiya amalga oshmadi, sizning Converter har qanday tekshirilmagan istisnoni chiqarishi mumkin. Ayniqsa, u manba qiymati noto‘g‘ri ekanligini bildirish uchun IllegalArgumentException istisnosini chiqarishi kerak. Sizning Converter realizatsiyangiz ko‘p oqimli xavfsiz ekanligiga e'tibor bering.
Barcha qulayliklar uchun bir nechta konverterlar core.convert.support paketida taqdim etilgan. Ular satrlarni raqamlarga va boshqa keng tarqalgan typelarga aylantirish konverterlarini o‘z ichiga oladi. Quyidagi listingda StringToInteger klassi ko‘rsatilgan, u Converter ni odatiy realizatsiyasi hisoblanadi:
package org.springframework.core.convert.support;
final class StringToInteger implements Converter<String, Integer> {
public Integer convert(String source) {
return Integer.valueOf(source);
}
}
ConverterFactory dan foydalanish
Agarda butun sinflar ierarxiyasi uchun konversiya mantiqini markazlashtirmoqchi bo‘lsangiz (masalan, String obyektlaridan Enum obyektlariga o‘tkazishda), ConverterFactory ni amalga oshirishingiz mumkin, quyidagi misolda ko‘rsatilganidek:
package org.springframework.core.convert.converter;
public interface ConverterFactory<S, R> {
<T extends R> Converter<S, T> getConverter(Class<T> targetType);
}
S ni siz aylantirayotgan type sifatida va R ni siz aylantirishingiz mumkin bo‘lgan klasslar oralig‘ini aniqlovchi bazoviy type sifatida parametrlashtiring. Keyin getConverter(Class<T>) ni amalga oshiring, bu yerda T R ning subsidiya sinfidir.
Misol sifatida StringToEnumConverterFactory ni ko‘rib chiqing:
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 dan foydalanish
Agarda sizga murakkab Converter realizatsiyasi kerak bo‘lsa, GenericConverter interfeysidan foydalaning. GenericConverter yanada moslashuvchan, lekin Converter ga nisbatan kamroq qattiq typelangan imzo bilan, bir nechta manba va maqsadli type orasida konversiyani qo‘llab-quvvatlaydi. Bundan tashqari, GenericConverter manba va maqsadli maydon kontekstini ochiq qiladi, bu konversiya mantiqini amalga oshirishda foydalanish mumkin bo‘ladi. Bunday kontekst sizga maydon yozuvi uzra e'lon qilingan umumiy ma’lumotlar yoki maydon imzosida e’lon qilingan ma’lumotlar asosida typelarni konvertatsiya qilish imkonini beradi. Quyidagi listingda GenericConverter interfeysini ta'rifi ko'rsatilgan:
package org.springframework.core.convert.converter;
public interface GenericConverter {
public Set<ConvertiblePair> getConvertibleTypes();
Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
}
GenericConverter ni amalga oshirish uchun getConvertibleTypes() funktsiyasi manba→maqsad type juftlarini qaytarishi kerak. Keyin convert(Object, TypeDescriptor, TypeDescriptor) ni amalga oshiring, konversiya mantiqini qo‘shish uchun. TypeDescriptor manbasiz typeni o‘z ichiga oladi, TypeDescriptor maqsad manzilga o‘rnatilishi kerak bo‘lgan o‘zgartirilgan qiymatni o‘rnatishda maqsadli maydon bilan ishlaydi.
GenericConverter ning yaxshi misoli Java massivni kolleksiyaga aylantiruvchi konverter hisoblanadi. Bunday ArrayToCollectionConverter kolleksiya maqsadli typeni aniqlash uchun kolleksiya element typini aniqlash uchun maydonning o‘zini analiz qiladi. Bu kolleksiya maqsadli maydoniga o‘rnatilgunga qadar manba massivining har bir elementini kolleksiya element typiga o‘zgartirish imkonini beradi.
GenericConverter murakkab SPI interfeysi, u faqat zarurat tug‘ilganda foydalanilishi kerak. Basic type konversiya ehtiyojlari uchun
Converter yoki
ConverterFactory dan foydalaning.
ConditionalGenericConverter dan foydalanish
Ba'zida Converter faqat ma'lum shart bajarganda ishlashi kerak. Masalan, Converter faqat maqsadli maydonda ma'lum bir anotatsiya bo‘lsa ishlashi mumkin yoki Converter faqat maqsadli klassda aniq bir metod mavjud bo‘lsa ishlashi mumkin (masalan, static valueOf metodi). ConditionalGenericConverter – bu GenericConverter va ConditionalConverter interfeyslari birikmasi bo‘lib, bunday maxsus moslik mezonlarini belgilash imkonini beradi:
public interface ConditionalConverter {
boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);
}
public interface ConditionalGenericConverter extends GenericConverter, ConditionalConverter {
}
ConditionalGenericConverter ning yaxshi misoli bu IdToEntityConverter, permanent entity identifikatorini entity havolasiga o‘tkazadi. Bunday IdToEntityConverter faqat maqsadli type entity static qidiruv metodini e’lon qilganda mos kelishi mumkin (masalan, findAccount(Long)). Siz matches(TypeDescriptor, TypeDescriptor) realizatsiyasida bunday qidiruv metodini amalga oshirishingiz mumkin.
ConversionService API si
ConversionService loyihalash vaqtida type konversiya mantiqini amalga oshirish uchun yagona API ni belgilaydi. Konvertorlar ko'pincha quyidagi fasade interfeysidan keyin amalga oshiriladi:
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);
}
Aksar ConversionService realizatsiyalari ConverterRegistry ni ham amalga oshiradi, bu konvertorlarni ro‘yxatdan o‘tkazish uchun SPI interfeysni taqdim etadi. Ichkarida ConversionService realizatsiyasi ro‘yxatdan o‘tkazilgan konvertorlarga type konversiya mantiqini amalga oshirishni delegatsiya qiladi.
ConversionService ni ishonchli realizatsiyasi core.convert.support paketida taqdim etilgan. GenericConversionService – bu umumiy maqsadli realizatsiya, ko'pgina muhitlarda foydalanish uchun mos keladi. ConversionServiceFactory ConversionService ning umumiy konfiguratsiyalarini yaratish uchun qulay zavod taqdim etadi.
ConversionService ni konfiguratsiyalash
ConversionService bu holatsiz obyekt bo'lib, ilova ishga tushirilganda yaratiladi va keyinchalik bir nechta oqimlar tomonidan birgalikda foydalaniladi. Spring ilovasida har bir Spring konteyneri (yoki ApplicationContext) uchun ConversionService ni konfiguratsiya qilish odatda amalga oshiriladi. Spring ushbu ConversionService ni aniqlaydi va frameworkga type konversiya kerak bo‘lgan har qanday vaqtda undan foydalanadi. Shuningdek, siz ushbu ConversionService ni har qanday biningizga in'ektsiya qilishingiz va uni bevosita chaqirishingiz mumkin.
ConversionService ro‘yxatdan o‘tkazilmagan bo‘lsa, unda
PropertyEditor ga asoslangan asl tizim ishlatiladi.
Springda standart ConversionService ni ro‘yxatdan o‘tkazish uchun quyidagi parolni qo‘shing, id ni conversionService ko‘rinishida belgilang:
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean"/>
Standart ConversionService satrlar, raqamlar, ko‘rsatkich turlari, kolleksiyalar, assotsiativ masslar va boshqa keng tarqalgan typelarni o‘zgartirishi mumkin. Standart konvertorlarni o‘zingizning maxsus konvertorlaringiz bilan qo‘shimcha yoki almashtirish uchun converters xususiyatini o‘rnating. Xususiyat qiymatlari har qanday interfeysni amalga oshiradigan qiymatlarni amalga oshirishi mumkin: Converter, ConverterFactory yoki GenericConverter.
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="example.MyCustomConverter"/>
</set>
</property>
</bean>
Spring MVC ilovasida ConversionService ni tez-tez ishlatishadi.
Ba'zi holatlarda o'zgartirish vaqtida formatlashni qo'llash mumkin.
Proqramik ravishda ConversionService dan foydalanish
ConversionService ni dasturiy ravishda ishlatish uchun, boshqalar binlar kabi unga murojaat qilishni in'ektsiya qilishingiz mumkin. Quyidagi misolda buni qanday qilish ko‘rsatilgan:
@Service
public class MyService {
public MyService(ConversionService conversionService) {
this.conversionService = conversionService;
}
public void doIt() {
this.conversionService.convert(...)
}
}
@Service
class MyService(private val conversionService: ConversionService) {
fun doIt() {
conversionService.convert(...)
}
}
Ko‘pgina foydalanish holatlari uchun convert metodini chaqirishingiz mumkin, targetType ni ko‘rsatish orqali, lekin u parametrlangan elementli kolleksiya kabi murakkab turlari bilan ishlamaydi. Misol uchun, agar siz List turidagi Integer ni dasturiy ravishda List turidagi String ga aylantirmoqchi bo‘lsangiz, unda asl va maqsadli typelarni rasmiy belgilashni taqdim etishingiz kerak.
Bunday qilish uchun, TypeDescriptor turli variantlarni taklif qilish orqali buni juda oddiy qiladi, quyidagi misolda ko‘rsatilgandek:
DefaultConversionService cs = new DefaultConversionService();
List<Integer> input = ...
cs.convert(input,
TypeDescriptor.forObject(input), // List<Integer> ning type deskriptori
TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(String.class)));
val cs = DefaultConversionService()
val input: List<Integer> = ...
cs.convert(input,
TypeDescriptor.forObject(input), // List<Integer> ning type deskriptori
TypeDescriptor.collection(List::class.java, TypeDescriptor.valueOf(String::class.java)))
E'tibor bering, DefaultConversionService avtomatik ravishda ko‘pgina muhitlarga mos keluvchi standart konvertorlarni ro‘yxatdan o‘tkazadi. Ularga kolleksiya konvertorlari, skalyar konvertorlar va asosiy Object-to-String konvertorlari kiradi. Siz DefaultConversionService sinfining addDefaultConverters statik metodidan foydalanib ushbu konvertorlarni har qanday ConverterRegistry da ro‘yxatdan o‘tkazishingiz mumkin.
Qayta ishlatiladigan qiymatlar typelari uchun konvertorlar massivlar va kolleksiyalar uchun qayta ishlatiladi, shuning uchun standart kolleksiya ishlovi mos bo‘ladi deb hisoblaganda S turidagi T turidagi kolleksiyaga yoki kolleksiyadan o‘zgartirish uchun maxsus konvertor yaratishning hojati yo‘q.
GO TO FULL VERSION