org.springframework.beans paketi JavaBeans sinf standarti asosida ishlaydi. JavaBean – bu argumentlarsiz boshlang'ich construktorga ega sinf bo'lib, nomlash konventsiyasiga rioya qiladi, bunda masalan bingoMadness nomidagi property uchun setBingoMadness(…) va getBingoMadness() nomli setter va getterlar bo'ladi. JavaBeans va spetsifikatsiya haqida koʻproq maʼlumot olish uchun javabeansni koʻrib chiqing.
Beans paketidagi muhim sinflardan biri BeanWrapper interfeysi va uning mos keluvchi implementatsiyasi (BeanWrapperImpl)dir. javadoc'da aytilganidek, BeanWrapper alohida yoki ommaviy tarzda property qiymatlarini o'rnatish va olish, property descriptor'larini olish va propertylarni so'roqlash uchun foydalanish imkonini beradi. Bundan tashqari, BeanWrapper nested propertylarni qo'llab-quvvatlaydi, bu esa sub-property uchun cheksiz chuqurlikdagi propertylarni o'rnatishga imkon beradi. BeanWrapper shuningdek, JavaBeans PropertyChangeListeners va VetoableChangeListenersni target sinfda qo'shimcha kodga ehtiyoj sezmasdan qo'shish imkoniyatini qo'llab-quvvatlaydi. So'nggi, ammo muhim xususiyatlaridan biri: BeanWrapper indekslangan propertylarni o'rnatishni qo'llab-quvvatlaydi. BeanWrapper odatda ilova kodi orqali to'g'ridan-to'g'ri ishlatilmaydi, balki DataBinder va BeanFactory orqali ishlatiladi.
BeanWrapper qanday ishlashini nomidan ham tushunish mumkin: u bean'ni o'rab olib, unga o'rnatish va olish kabi ma'lum operatsiyalarni bajaradi.
Asosiy va nested propertylarni o'rnatish va olish
Propertylarni o'rnatish va olish BeanWrapper ichida setPropertyValue va getPropertyValue ortiqcha yuklangan metodlari orqali amalga oshiriladi. Ularning Javadoc'ida batafsil ma'lumot berilgan. Quyida bu konventsiyalarning ba'zi misollari keltirilgan:
| Ifoda | Izoh |
|---|---|
|
|
|
|
|
|
|
|
uchinchi indekslangan property |
|
|
|
(Agar siz BeanWrapper bilan to'g'ridan-to'g'ri ishlashni rejalashtirmasangiz, bu keyingi qism juda muhim emas. Agar siz faqat DataBinder va BeanFactory dan va ularning odatiy implementatsiyalaridan foydalansangiz, to'g'ridan-to'g'ri PropertyEditors ga o'tish kerak.)
Quyida ikkita sinf misoli BeanWrapper dan foydalanib propertylarni o'rnatish va olishni ko'rsatadi:
public class Company {
private String name;
private Employee managingDirector;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Employee getManagingDirector() {
return this.managingDirector;
}
public void setManagingDirector(Employee managingDirector) {
this.managingDirector = managingDirector;
}
}
class Company {
var name: String? = null
var managingDirector: Employee? = null
}
public class Employee {
private String name;
private float salary;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public float getSalary() {
return salary;
}
public void setSalary(float salary) {
this.salary = salary;
}
}
class Employee {
var name: String? = null
var salary: Float? = null
}
Quyidagi kod bo'laklari Company va Employees ni ishlatib hosil qilingan instance'larning ba'zi propertylarini olish va ulardan foydalanishni ko'rsatadi:
BeanWrapper company = new BeanWrapperImpl(new Company());
// kompaniya nomini o'rnatish...
company.setPropertyValue("name", "Some Company Inc.");
// ... bu quyidagicha amalga oshirilishi ham mumkin:
PropertyValue value = new PropertyValue("name", "Some Company Inc.");
company.setPropertyValue(value);
// Yaxshi, endi direktor yaratib, uni kompaniyaga bog'laymiz:
BeanWrapper jim = new BeanWrapperImpl(new Employee());
jim.setPropertyValue("name", "Jim Stravinsky");
company.setPropertyValue("managingDirector", jim.getWrappedInstance());
// managingDirector uchun company orqali salaryni olish
Float salary = (Float) company.getPropertyValue("managingDirector.salary");
val company = BeanWrapperImpl(Company())
// kompaniya nomini o'rnatish...
company.setPropertyValue("name", "Some Company Inc.")
// ... bu quyidagicha amalga oshirilishi ham mumkin:
val value = PropertyValue("name", "Some Company Inc.")
company.setPropertyValue(value)
// Yaxshi, ko'ramiz, direktor yaratib, uni kompaniyaga bog'laymiz:
val jim = BeanWrapperImpl(Employee())
jim.setPropertyValue("name", "Jim Stravinsky")
company.setPropertyValue("managingDirector", jim.wrappedInstance)
// managingDirector uchun company orqali salaryni olish
val salary = company.getPropertyValue("managingDirector.salary") as Float?
Ichki PropertyEditor implementatsiyalari
Spring PropertyEditor kontseptsiyasidan obyekt va String oʻrtasida oʻzgartirishlarni amalga oshirish uchun foydalanadi. Propertylarni obyektning o'zi kabi ko'rsatishdan boshqa tarzda ko'rsatishi qulay bo'lishi mumkin. Masalan, Dateni inson ko'rinishi uchun o'qilishi mumkin bo'lgan shaklda (masalan, String: '2007-14-09') taqdim etish mumkin, lekin biz hali ham inson ko'rinishidagi shaklni asl sanaga qaytarishimiz mumkin (yoki, undan ham yaxshisi, inson ko'rinishidagi har qanday sanani asl Date obyektlariga qaytarishimiz mumkin). Bunday ishlash logikasiga maxsus java.beans.PropertyEditor tipidagi tahrirlovchilarni ro'yxatdan o'tkazib erishish mumkin. BeanWrapper yoki muqobilan, ma'lum bir IoC-konteynerida (avvalgi bobda eslatilganidek) maxsus tahrirlovchilarni ro'yxatdan o'tkazish, unga propertyni kerakli turga qanday o'zgartirishni bilish imkonini beradi. PropertyEditor haqida koʻproq maʼlumot olish uchun, Oracle'dan java.beans paketi boʻyicha javadocni koʻrib chiqing.
Spring'dagi propertyni tahrirlash xususiyatini qo'llashning bir necha misollari:
-
Beanlarning propertylarini o'rnatish
PropertyEditorimplementatsiyasi orqali amalga oshiriladi. Agar siz XML faylda deklaratsiya qilingan ba'zi bir bean uchun property qiymatiniStringturida ishlatsangiz, Spring (agar tegishli property setter parametriClassbo'lsa)ClassEditorni sinf parametriniClassobyektiga aylantirishga harakat qilish uchun ishlatadi. -
Spring MVC ramkasi ichidagi HTTP so'rovning parametrlarini tahlil qilish
PropertyEditororqali amalga oshiriladi, bu barchaCommandControllerning subclass'larida qo'lda biriktiriladi.
Spring bir qator o'rnatilgan PropertyEditor implementatsiyalari ega, bu ishlashni osonlashtiradi. Bularning barchasi org.springframework.beans.propertyeditors paketida joylashgan. Ularning ko'plari (ammo hammasi emas, quyidagi jadvalda ko'rsatilganidek) BeanWrapperImpl tomonidan sukut bo'yicha ro'yxatdan o'tkaziladi. Agar property editorini muayyan tarzda sozlash kerak bo'lsa, siz o'zingizning variantingizni ro'yxatdan o'tkazishingiz mumkin, bu sukut bo'yicha variantni almashtirish uchun. Quyidagi jadvalda Spring tomonidan taqdim etilgan turli PropertyEditor implementatsiyalari tasvirlangan:
| Sinf | Izoh |
|---|---|
|
|
Baitu massivlar uchun tahrirlovchi. Stringlarni ularga mos keluvchi bayt ko'rinishlariga o'zgartiradi. |
|
|
Sinflarni ifodalovchi stringlarni real sinflarga o'zgartiradi va aksincha. Agar sinf topilmasa, |
|
|
|
|
|
Kollektsiyalar uchun property tahrirlovchi, har qanday asl |
|
|
To'g'rilangan |
|
|
Har qanday |
|
|
Stringlarni |
|
|
Bir yo'nalishli property tahrirlovchi bo'lib, u stringni qabul qiladi va (oraliq |
|
|
Stringlarni |
|
|
Stringlarni |
|
|
Stringlarni ( |
|
|
Stringlarni tahrirlaydigan property tahrirlovchi. Ixtiyoriy ravishda bo'sh stringni |
|
|
Biror URL-manzilning string ko'rinishini real |
Spring kerak bo'lishi mumkin bo'lgan property tahrirlovchilar uchun qidirish yo'lini o'rnatish uchun java.beans.PropertyEditorManagerdan foydalanadi. Qidirish yo'li sun.bean.editorsni ham o'z ichiga oladi, bu Font, Color va koʻpgina primitiv turlar uchun PropertyEditor implementatsiyalarini oʻz ichiga oladi. JavaBeans sinfining standart infratuzilmasi, agar ular o'zlari ishlov beradigan sinf bilan bir xil paketda joylashgan bo'lsa va shu sinf nomiga Editor qo'shilgan nom bilan bir xil bo'lsa, PropertyEditor sinflarini avtomatik ravishda aniqlaydi (aniq ro'yxatdan o'tkazishga ehtiyoj sezmasdan). Misol uchun, sizda quyidagi sinf va paket strukturasiga ega bo'lishingiz mumkin, bu yetarli bo'ladi, shunda SomethingEditor sinfi Something turidagi propertylar uchun PropertyEditor sifatida aniqlanadi va ishlatiladi.
com
chank
pop
Something
SomethingEditor // Something uchun PropertyEditor sinfi
Bu holda, shuningdek, JavaBeans sinfi BeanInfo standart mexanizmini (bir oz darajada bu yerda tavsiflangan) ishlatishingiz mumkin. Quyidagi misol BeanInfo mexanizmidan foydalanib, bir yoki bir nechta PropertyEditor instance'larini bog'liq sinf property'lariga aniq ro'yxatdan o'tkazish uchun foydalanadi:
com
chank
pop
Something
SomethingBeanInfo // Something uchun BeanInfo sinfi
Quyidagi SomethingBeanInfo sinfiga tegishli Java manba kodi CustomNumberEditorni Something sinfining age propertysi bilan bog'laydi:
public class SomethingBeanInfo extends SimpleBeanInfo {
public PropertyDescriptor[] getPropertyDescriptors() {
try {
final PropertyEditor numberPE = new CustomNumberEditor(Integer.class, true);
PropertyDescriptor ageDescriptor = new PropertyDescriptor("age", Something.class) {
@Override
public PropertyEditor createPropertyEditor(Object bean) {
return numberPE;
}
};
return new PropertyDescriptor[] { ageDescriptor };
}
catch (IntrospectionException ex) {
throw new Error(ex.toString());
}
}
}
class SomethingBeanInfo : SimpleBeanInfo() {
override fun getPropertyDescriptors(): Array<PropertyDescriptor> {
try {
val numberPE = CustomNumberEditor(Int::class.java, true)
val ageDescriptor = object : PropertyDescriptor("age", Something::class.java) {
override fun createPropertyEditor(bean: Any): PropertyEditor {
return numberPE
}
}
return arrayOf(ageDescriptor)
} catch (ex: IntrospectionException) {
throw Error(ex.toString())
}
}
}
Maxsus PropertyEditor implementatsiyalarini ro'yxatdan o'tkazish
Bean propertylarini string qiymatlari sifatida o'rnatishda, Spring IoC konteyneri oxir-oqibat, bu stringlarni murakkab property turiga aylantirish uchun JavaBeans PropertyEditorning standart implementatsiyasidan foydalanadi. Spring bir nechta moslashtirilgan PropertyEditor implementatsiyalarini oldindan ro'yxatdan o'tkazadi (masalan, sinf nomini string sifatida ifodalab, uni Class obyektiga aylantirish uchun). Bundan tashqari, JavaBeans ning PropertyEditor uchun standart qidiruv mexanizmi PropertyEditorni nomlanganini toʻgʻri qilib qoʻyish va unga qoʻllab-quvvatlashni taʼminlaydigan sinf bilan bir xil paketga joylashtirishga imkon beradi, shunda u avtomatik ravishda topilishi mumkin.
Boshqa PropertyEditorsni ro'yxatdan o'tkazishga ehtiyoj tug'ilganda bir nechta mexanizmlar mavjud. Qo'lda foydalanishning eng sodda usuli, odatda qulay va tavsiya etilmaydi, BeanFactoryga havola mavjud bo'lsa, ConfigurableBeanFactory interfeysidagi registerCustomEditor() metodidan foydalanishdan iborat. Yana bir qulayroq mexanizm maxsus CustomEditorConfigurer nomli bean fabrikasi post-protsessoridan foydalanishni o'z ichiga oladi. Garchi BeanFactoryni amalga oshirish orqali bean fabrikasi post-protsessorlarini ishlatish mumkin bo'lmasa ham, CustomEditorConfigurer ichki property o'rnatishni o'z ichiga oladi, shuning uchun uni ApplicationContext bilan ishlatishni, uni boshqa har qanday bean sifatida joylashtirish mumkin bo'lgan holatlarda, kuchli tavsiya etamiz va u avtomatik topiladi va qo'llaniladi.
Barcha bean fabrikalari va ilova kontekstlari avtomatik ravishda property o'zgartirishlarni ishlashni qo'llash uchun BeanWrapperdan foydalanish tufayli bir qator ichki property tahrirlovchilarni qo'llaydi. Bundan tashqari, ApplicationContext resurslarni topishni ilova konteksti turiga moslashtirish uchun qo'shimcha tahrirlovchilarni almashtiradi yoki qo'shadi.
JavaBeans sinfining standart PropertyEditor instance'lari string sifatida ifodalangan property qiymatlarini haqiqiy murakkab property turiga aylantirish uchun ishlatiladi. CustomEditorConfigurer dan foydalanish orqali ApplicationContext ga qo'shimcha PropertyEditor instance'larini qo'llab-quvvatlashni qulay tarzda qo'shishingiz mumkin.
Quyidagi misolda, ExoticType maxsus sinfi va DependsOnExoticType sinfi belgilangan boʻlib, unga property sifatida ExoticType oʻrnatilishi kerak:
package example;
public class ExoticType {
private String name;
public ExoticType(String name) {
this.name = name;
}
}
public class DependsOnExoticType {
private ExoticType type;
public void setType(ExoticType type) {
this.type = type;
}
}
package example
class ExoticType(val name: String)
class DependsOnExoticType {
var type: ExoticType? = null
}
Agar hammasi to'g'ri o'rnatilgan bo'lsa, property tipiga string qiymatini tayinlashimiz kerak, bu PropertyEditorni haqiqiy ExoticType instance'iga aylantiradi. Quyidagi bean ta'rifi bu munosabatni qanday o'rnatishni ko'rsatadi:
<bean id="sample" class="example.DependsOnExoticType">
<property name="type" value="aNameForExoticType"/>
</bean>
PropertyEditor implementatsiyasi quyidagicha ko'rinishi mumkin:
// string ko'rinishini ExoticType obyektiga o'zgartiradi
package example;
public class ExoticTypeEditor extends PropertyEditorSupport {
public void setAsText(String text) {
setValue(new ExoticType(text.toUpperCase()));
}
}
// string ko'rinishini ExoticType obyektiga o'zgartiradi
package example
import java.beans.PropertyEditorSupport
class ExoticTypeEditor : PropertyEditorSupport() {
override fun setAsText(text: String) {
value = ExoticType(text.toUpperCase())
}
}
Va nihoyat, quyidagi misolda yangi PropertyEditorni ApplicationContext da ro'yxatdan o'tkazish va uni kerakli vaqtda foydalana olish imkoniyatini koʻrsatadi:
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="example.ExoticType" value="example.ExoticTypeEditor"/>
</map>
</property>
</bean>
PropertyEditorRegistrar dan foydalanish
Spring konteyneriga property tahrirlovchilarni ro'yxatdan o'tkazishning boshqa bir mexanizmi PropertyEditorRegistrar ni yaratish va undan foydalanishdir. Ushbu interfeys ayniqsa, bir xil property tahrirlovchilar to'plamini bir necha turli vaziyatlarda ishlatish kerak bo'lsa, foydalidir. Siz bir nechta mos keluvchi ro'yxatdan o'tkazuvchini (registrar) yozishingiz va uni har bir holatda qayta ishlatishingiz mumkin. PropertyEditorRegistrar instance'lari Spring'ning BeanWrapper (va DataBinder) tomonidan amalga oshirilgan PropertyEditorRegistry interfeysi bilan birgalikda ishlaydi. PropertyEditorRegistrar instance'lari ayniqsa CustomEditorConfigurer bilan birgalikda, unga setPropertyEditorRegistrars(..) propertysini taqdim etadigan holda foydalidirlar. PropertyEditorRegistrarni CustomEditorConfigurer ga qo'shilgan holda, ularning funksiyasi DataBinder va Spring MVC kontrollerlar bilan birgalikda osongina ishlatilishi mumkin. Bundan tashqari, bu maxsus tahrirlovchilarda sinxronlash zaruratini bartaraf etishga imkon beradi: PropertyEditorRegistrar bin yaratishga harakat qilganda har safar yangi PropertyEditor instance'larini yaratishi kutiladi.
Quyidagi misolda maxsus PropertyEditorRegistrar implementatsiyasini qanday yaratish mumkinligi ko'rsatilgan:
package com.foo.editors.spring;
public final class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar {
public void registerCustomEditors(PropertyEditorRegistry registry) {
// yangi PropertyEditor instance'larini yaratish kutiladi
registry.registerCustomEditor(ExoticType.class, new ExoticTypeEditor());
// bu holatda kerak bo'lgancha ko'plab maxsus property tahrirlovchilarni ro'yxatdan o'tkazishingiz mumkin...
}
}
package com.foo.editors.spring
import org.springframework.beans.PropertyEditorRegistrar
import org.springframework.beans.PropertyEditorRegistry
class CustomPropertyEditorRegistrar : PropertyEditorRegistrar {
override fun registerCustomEditors(registry: PropertyEditorRegistry) {
// yangi PropertyEditor instance'larini yaratish kutiladi
registry.registerCustomEditor(ExoticType::class.java, ExoticTypeEditor())
// bu holatda kerak bo'lgancha ko'plab maxsus property tahrirlovchilarni ro'yxatdan o'tkazishingiz mumkin...
}
}
org.springframework.beans.support.ResourceEditorRegistrarda PropertyEditorRegistrar implementatsiyasining misolini ko'ring. E'tibor bering, u registerCustomEditors(…) metodining implementatsiyasida har bir property tahrirlovchini yangi nusxalarini yaratadi.
Quyidagi misolda CustomEditorConfigurerni qanday sozlash va unga CustomPropertyEditorRegistrardan nusxa olib kelish ko'rsatilgan:
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="propertyEditorRegistrars">
<list>
<ref bean="customPropertyEditorRegistrar"/>
</list>
</property>
</bean>
<bean id="customPropertyEditorRegistrar"
class="com.foo.editors.spring.CustomPropertyEditorRegistrar"/>
Va nihoyat (va bu bobning mavzusidan biroz cheklangan holda), Spring'dan veb-ramka MVC'dan foydalanadiganlar uchun, PropertyEditorRegistrarni web loyihalarda foydalanish juda qulay bo'lishi mumkin. Quyidagi misolda PropertyEditorRegistrar'dan @InitBinder metodiga implementatsiyada foydalanilgan:
@Controller
public class RegisterUserController {
private final PropertyEditorRegistrar customPropertyEditorRegistrar;
RegisterUserController(PropertyEditorRegistrar propertyEditorRegistrar) {
this.customPropertyEditorRegistrar = propertyEditorRegistrar;
}
@InitBinder
void initBinder(WebDataBinder binder) {
this.customPropertyEditorRegistrar.registerCustomEditors(binder);
}
// foydalanuvchi ro'yxatdan o'tkazish bilan bog'liq boshqa metodlar
}
@Controller
class RegisterUserController(
private val customPropertyEditorRegistrar: PropertyEditorRegistrar) {
@InitBinder
fun initBinder(binder: WebDataBinder) {
this.customPropertyEditorRegistrar.registerCustomEditors(binder)
}
// foydalanuvchi ro'yxatdan o'tkazish bilan bog'liq boshqa metodlar
}
Bu uslubda PropertyEditorni ro'yxatdan o'tkazish kodni soddalashtirishi mumkin (metod @InitBinder implementatsiyasi bor-yo'g'i bir qatorni tashkil etadi) va PropertyEditorni ro'yxatdan o'tkazish uchun mavjud umumiy kodni sinfga inkapsullash va keyin uni bir nechta kontrollerlar tomonidan foydalanishga imkon berishi mumkin.
GO TO FULL VERSION