org.springframework.beans
paketi JavaBeans sinifi standartına riayət edir. JavaBean – heç bir arqumenti olmayan default konstruktoru olan bir sinifdir ki, burada bingoMadness
adlı mülk setBingoMadness(…)
setter və getBingoMadness()
getter-ə malik olacaq adlandırma konvensiyasına uyğun gəlir. JavaBeans və spesifikasiyası haqqında daha ətraflı məlumat üçün javabeans saytına bax.
Binlər paketindəki vacib siniflərdən biri BeanWrapper
interfeysi və onun müvafiq reallaşdırması olan BeanWrapperImpl
dır. Javadoc-a görə, BeanWrapper
xüsusiyyət dəyərlərini tək-tək və ya kütləvi şəkildə təyin etmə və əldə etmə funksionallığını, xüsusiyyət deskriptorlarını əldə etmə və onları oxumaq və ya yazmağın mümkün olub-olmadığını sorğulamaq üçün xüsusiyyətləri sorğulama funksionallığını təklif edir. Həmçinin, BeanWrapper
iç-içə xüsusiyyətlər dəstəyini təklif edir, yəni xüsusiyyətlərin subxüsusiyyətlər üçün təyin olunmasına imkan yaradır. BeanWrapper
həmçinin JavaBeans-in standart PropertyChangeListeners
və VetoableChangeListeners
əlavə etmə imkanı təqdim edir, hədəf sinifdə əlavə kod yazmağa ehtiyac olmadan. Axırda, amma qeyri-əhmiyyətsiz bir məsələdə, BeanWrapper
indekslənmiş xüsusiyyətlərin təyin edilməsini dəstəkləyir. BeanWrapper
adətən birbaşa tətbiqetmə kodu ilə istifadə olunmur, lakin DataBinder
və BeanFactory
tərəfindən istifadə olunur.
BeanWrapper
necə işlədiyini onun adı ilə bir qədər anlamaq olar: o, binə müəyyən hərəkətlər etmək üçün onu bükür, məsələn, xüsusiyyətlər təyin etmək və ya əldə etmək.
Əsas və iç-içə xüsusiyyətlərin təyin edilməsi və əldə edilməsi
Xüsusiyyətlərin təyin edilməsi və əldə edilməsi BeanWrapper
-dəki setPropertyValue
və getPropertyValue
metodlarının yüklənməsi ilə həyata keçirilir. Javadoc-da bunlar haqqında daha ətraflı məlumat ala bilərsiniz. Aşağıdakı cədvəl bu konvensiyalara bəzi nümunələr göstərir:
İfade | Izahat |
---|---|
|
|
|
|
|
|
|
|
(Aşağıdakı bölmə BeanWrapper
ilə birbaşa işləməyi planlaşdırmırsınızsa, çox da əhəmiyyətli deyil. Sadəcə DataBinder
və BeanFactory
və onların default reallaşdırmalarını istifadə edirsinizsə, birbaşa PropertyEditors
bölümünə keçməlisiniz.)
Aşağıdakı iki sinif nümunəsi BeanWrapper
istifadə edərək xüsusiyyətlərin əldə edilməsini və təyin edilməsini göstərir:
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
}
Aşağıdakı kod parçaları Company
və Employees
yaradılan nümunələrində bəzi xüsusiyyətlərin əldə edilməsi və onlarla manipulyasiya nümunələrini göstərir:
BeanWrapper company = new BeanWrapperImpl(new Company());
// şirkət adını təyin etmək...
company.setPropertyValue("name", "Some Company Inc.");
// ... bu da başqa cür edilir:
PropertyValue value = new PropertyValue("name", "Some Company Inc.");
company.setPropertyValue(value);
// Yaxşı, gəlin bir direktor yaradıb onu şirkətə təyin edək:
BeanWrapper jim = new BeanWrapperImpl(new Employee());
jim.setPropertyValue("name", "Jim Stravinsky");
company.setPropertyValue("managingDirector", jim.getWrappedInstance());
// şirkət vasitəsilə managingDirector üçün salary əldə etmək
Float salary = (Float) company.getPropertyValue("managingDirector.salary");
val company = BeanWrapperImpl(Company())
// şirkət adını təyin etmək...
company.setPropertyValue("name", "Some Company Inc.")
// ... bu da başqa cür edilir:
val value = PropertyValue("name", "Some Company Inc.")
company.setPropertyValue(value)
// Yaxşı, gəlin bir direktor yaradıb onu şirkətə təyin edək:
val jim = BeanWrapperImpl(Employee())
jim.setPropertyValue("name", "Jim Stravinsky")
company.setPropertyValue("managingDirector", jim.wrappedInstance)
// şirkət vasitəsilə managingDirector üçün salary əldə etmək
val salary = company.getPropertyValue("managingDirector.salary") as Float?
Daxili PropertyEditor
reallaşdırmaları
Spring, Object
və String
arasında dönüşüm icra etmək üçün PropertyEditor
anlayışını istifadə edir. Bəzən obyektlərdən fərqli şəkildə xüsusiyyətləri göstərmək faydalıdır. Məsələn, Date
bir çox oxunaqlı şəkildə (məsələn, String
: '2007-14-09'
) təmsil oluna bilər, eyni zamanda oxunaqlı forması ilkin tarixə geri dönüşüm edə bilər (və ya daha yaxşı, hər hansı bir tarix insan oxumağına bərabər formadan Date
obyektlərinə geri dönüşüm edə bilər). Bu cür işləməni təmin etmək üçün xüsusi java.beans.PropertyEditor
tipli redaktorlar qeydiyyatdan keçirmək olar. BeanWrapper
-a və ya alternativ olaraq müəyyən bir IoC konteynerində (öncəki bölmədə qeyd edildiyi kimi) xüsusi redaktorları qeydiyyatdan keçirmək ona xüsusiyyətləri istədiyiniz tipə necə transformasiya etməyi söyləyir. PropertyEditor
haqqında daha ətraflı məlumat üçün Oracle-dən java.beans
paketi üzrə javadoc saytına bax.
Spring-də xüsusiyyətlərin redaktə edilmə funksionallığı üçün bir neçə nümunə:
-
Bin xüsusiyyətləri
PropertyEditor
reallaşdırmaları vasitəsi ilə təyin olunur. Əgər XML faylında hər hansı bir bin üçün xüsusiyyət dəyəri olaraqString
istifadə edirsinizsə, Spring (əgər müvafiq xüsusiyyətin setteriClass
parametrinə malikdirsə)ClassEditor
istifadə edərək, parametriClass
obyektinə transformasiya etməyə çalışır. -
Spring MVC çərçivəsində HTTP sorğularının sintaksisinə baxmaq üçün müxtəlif
PropertyEditor
reallaşdırmaları istifadə olunur, hansılar ki manual olaraqCommandController
alt siniflərində bağlı ola bilərlər.
Spring, istifadəni asanlaşdırmaq üçün bir sıra daxili PropertyEditor
reallaşdırmalarına malikdir. Onların hamısı org.springframework.beans.propertyeditors
paketində yerləşirlər. Onların əksəriyyəti (amma hamısı deyil, aşağıdakı cədvəldə qeyd edildiyi kimi) default olaraq BeanWrapperImpl
tərəfindən qeydiyyatdan keçirilir. Xüsusiyyət redaktorunun müəyyən bir qaydada təyin edildiyi hallarda, default varianta üstünlük vermək üçün öz versiyanızı qeydiyyatdan keçirə bilərsiniz. Aşağıdakı cədvəl Spring tərəfindən təmin edilən müxtəlif PropertyEditor
reallaşdırmalarını təsvir edir:
Sinif | Izahat |
---|---|
|
Bait massivləri üçün redaktor. Strinqləri onların byte təmsillərinə çevirir. Default olaraq |
|
Strinqləri sinifləri təmsil edərək real siniflərə və əksinə pars edir. Sinif tapılmazsa, |
|
|
|
Kolleksiyalar üçün xüsusiyyət redaktoru, hər hansı bir orijinal |
|
|
|
|
|
Strinqləri |
|
Bir istiqamətli xüsusiyyət redaktoru, bu stringi alıb (ara |
|
Strinqləri |
|
Strinqləri |
|
|
|
Strinqləri düzəltmək üçün xüsusiyyət redaktoru. Opsiyonel olaraq boş stringi |
|
Hər hansı bir URL ünvanının strinq təmsilini real |
Spring, ehtiyac duyulacaq xüsusiyyət redaktorları axtarış yolunu təyin etmək üçün java.beans.PropertyEditorManager
istifadə edir. Axtarış yolu həmçinin sun.bean.editors
u da əhatə edir, bu da Font
, Color
və əksər primitiv tiplər üçün PropertyEditor
reallaşdırmalarını əhatə edir. Standart JavaBeans sinifinin infrastrukturu PropertyEditor
siniflərini avtomatik olaraq aşkar edir (onları açıq şəkildə qeydiyyatdan keçirməyə ehtiyac olmadan), əgər bunlar özləri idarə etdiyi siniflə eyni pakettə yerləşir və həmin siniflə eyni adı daşıyıb Editor
artırması ilə tamamlanırsa. Məsələn, aşağıdakı sinif və paket strukturlarına malik olmaq kifayət edər ki, SomethingEditor
sinifi aşkar edilsin və Something
tipli xüsusiyyətlər üçün PropertyEditor
kimi istifadə olunsun.
com chank pop Something SomethingEditor // Something sinifi üçün PropertyEditor
Bu halda həm də JavaBeans sinifinin BeanInfo
standart mexanizmini istifadə etmək də mümkündür (bir qədər burada təsvir edilmişdir). Aşağıdakı nümunədə BeanInfo
mexanizmi bir və ya bir neçə PropertyEditor
nümunəsi ilə əlaqəli sinifin xüsusiyyətlərinə açıq şəkildə qeydiyyatdan keçmək üçün istifadə olunur:
com chank pop Something SomethingBeanInfo // Something sinifi üçün BeanInfo
Aşağıdakı Java mənbə kodu SomethingBeanInfo
sinifinə aid kod nümunəsi CustomNumberEditor
-i Something
sinifinin age
xüsusiyyəti ilə əlaqələndirir:
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())
}
}
}
Xüsusi PropertyEditor
reallaşdırmalarının əlavə qeydiyyatı
String dəyərlər kimi bin xüsusiyyətlərini təyin edərkən, Spring IoC konteyneri sonda bu stringləri mülkiyyətin mürəkkəb tipinə çevirmək üçün JavaBeans PropertyEditor
standart reallaşdırmalarından istifadə edir. Spring, əvvəlcədən qeydiyyatdan keçmiş bir neçə xüsusi PropertyEditor
reallaşdırmalarına (məsələn, string olaraq ifadə olunmuş sinif adını Class
obyektinə çevirmək üçün) malikdir. Bundan başqa, JavaBeans'ndəki PropertyEditor
axtarışı üçün standart mexanizm, müəyyən coğrafi tərin eyni paketində yerləşdirməklə və dəstək verdiyi siniflə uyğun adlandırma apararaq, avtomatik aşkar edilə biləcək şəkildə PropertyEditor
qeydiyyatdan keçirməyə imkan verir.
Başqa xüsusi PropertyEditors
qeydiyyatdan keçirmək zərurəti meydana gəldikdə bəzi mexanizmlər mövcuddur. Ən əl əməyi tələb edən yanaşma, adətən əlverişli və ya tövsiyə edilən sayılmır, BeanFactory
-a bir link varsa, ConfigurableBeanFactory
interface-inin registerCustomEditor()
metodundan istifadə etməklə həyata keçirilir. Digər (bir az daha əlverişli) mexanizm xüsusi bin fabriki sonrası işləyici (bean factory post-processor) istifadə etməkdir ki, bu da CustomEditorConfigurer
adlanır. BeanFactory
reallaşdırmaları ilə istifadə etmək mümkün olmasa da, CustomEditorConfigurer
iç-içə xüsusiyyətlər qeydiyyatdan keçirən tərtibatı malikdir, buna görə də, kontekstə uyğun olaraq ApplicationContext
ilə istifadə etməyi, bu halarda xüsusi bin kimi istifadə edildikdə və avtomatik aşkar edilərək tətbiq olunduqda qüvvədə olmaq tövsiyə edilir.
Diqqət yetirin ki, bütün bin fabrikləri və tətbiq kontekstləri BeanWrapper
istifadə etməklə xüsusiyyətlərin çevrilməsini idarə etməklə bir sıra daxili xüsusiyyət redaktorlarının istifadəsini avtomatik olaraq həyata keçirir. Həmçinin, ApplicationContext
eyni zamanda resurs axtarışını tətbiq konteksti tipinə uyğun şəkildə idarə etmək üçün əlavə redaktorlar da əlavə edir və ya onları ləğv edir.
String olaraq ifadə olunmuş mülkiyyət dəyərlərini faktiki mülkiyyətin mürəkkəb tipinə çevirmək üçün JavaBeans sinifinin standart PropertyEditor
nümunələri istifadə olunur. ApplicationContext
-də əlavə PropertyEditor
nümunələrinə dəstək əlavə etmək üçün CustomEditorConfigurer
adlı bin fabriki post-prosessor istifadə edilə bilər.
Aşağıdakı nümunəni nəzərdən keçirin ki, burada xüsusi ExoticType
sinifi və başqa bir sinif DependsOnExoticType
təyin olunmuşdur, hansı ki, ExoticType
mülkiyyəti təyin etməlidir:
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
}
Hər şey düzgün qurulubsa, bizə bir stringi type xüsusiyyətinə təyin etmək imkanı verilməlidir ki, PropertyEditor
onu əsl ExoticType
nümunəsinə çevirsin. Aşağıdakı bin təyini bu əlaqəni necə təyin etməyi göstərir:
<bean id="sample" class="example.DependsOnExoticType">
<property name="type" value="aNameForExoticType"/>
</bean>
PropertyEditor
reallaşdırması aşağıdakı kimi olabilər:
// strinq təmsilini ExoticType obyektinə çevirir
package example;
public class ExoticTypeEditor extends PropertyEditorSupport {
public void setAsText(String text) {
setValue(new ExoticType(text.toUpperCase()));
}
}
// strinq təmsilini ExoticType obyektinə çevirir
package example
import java.beans.PropertyEditorSupport
class ExoticTypeEditor : PropertyEditorSupport() {
override fun setAsText(text: String) {
value = ExoticType(text.toUpperCase())
}
}
Sonda, ApplicationContext
-də yeni PropertyEditor
qeydiyyatdan keçirmək üçün CustomEditorConfigurer
istifadə edərək, onun lazım olduğunda istifadə olunmasının necə təmin olunacağını göstərən nümunə:
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="example.ExoticType" value="example.ExoticTypeEditor"/>
</map>
</property>
</bean>
PropertyEditorRegistrar
istifadəsi
Redaktorların Spring konteynerində qeydə alınmasının başqa bir mexanizmi PropertyEditorRegistrar
yaratmaq və istifadə etməkdir. Bu interface xüsusilə bir neçə müxtəlif vəziyyətdə eyni xüsusiyyət redaktorları dəstini istifadə etmək istəyirsinizsə faydalıdır. Uyğun bir qeydiyyatçı (registrar) yazıb hər bir vəziyyətdə onu təkrar istifadə edə bilərsiniz. PropertyEditorRegistrar
nümunələri PropertyEditorRegistry
interface ilə işləyir, hansı ki, Spring BeanWrapper
və DataBinder
tərəfindən reallaşdırılır. PropertyEditorRegistrar
nümunələri xüsusən CustomEditorConfigurer
ilə birlikdə istifadə edildikdə faydalıdır, hansı ki, setPropertyEditorRegistrars(..)
adlı xassəsi təqdim edir. CustomEditorConfigurer
-ə bu şəkildə əlavə olunmuş PropertyEditorRegistrar
nümunələri asanlıqla Spring-in DataBinder
və MVC kontrollerları ilə birlikdə istifadə edilə bilər. Bundan başqa, bu, xüsusi redaktorlarda sinxronizasiya ehtiyacını aradan qaldırır: PropertyEditorRegistrar
-ın hər dəfə bir yeni bin yaradılmaq üçün yeni PropertyEditor
nümunələri yaratması gözlənilir.
Aşağıdakı nümunədə PropertyEditorRegistrar
-ın öz reallaşdırmasını necə yaratmaq göstərilib:
package com.foo.editors.spring;
public final class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar {
public void registerCustomEditors(PropertyEditorRegistry registry) {
// yeni PropertyEditor nümunələrinin yaradılması gözlənilir
registry.registerCustomEditor(ExoticType.class, new ExoticTypeEditor());
// lazım olan qədər xüsusi xüsusiyyət redaktorları qeydiyyatdan keçirmək olar...
}
}
package com.foo.editors.spring
import org.springframework.beans.PropertyEditorRegistrar
import org.springframework.beans.PropertyEditorRegistry
class CustomPropertyEditorRegistrar : PropertyEditorRegistrar {
override fun registerCustomEditors(registry: PropertyEditorRegistry) {
// yeni PropertyEditor nümunələrinin yaradılması gözlənilir
registry.registerCustomEditor(ExoticType::class.java, ExoticTypeEditor())
// lazım olan qədər xüsusi xüsusiyyət redaktorları qeydiyyatdan keçirmək olar...
}
}
org.springframework.beans.support.ResourceEditorRegistrar
daxilində PropertyEditorRegistrar
reallaşdırmasını da nəzərdən keçirin. O, registerCustomEditors(…)
metodunu reallaşdırmasında hər xüsusiyyət redaktoru üçün yeni nümunələr necə yaratdığını qeyd edin.
Aşağıdakı nümunə CustomEditorConfigurer
-i necə təyin etməyi və ona CustomPropertyEditorRegistrar
nümunəsini necə daxil etməyi göstərir:
<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"/>
Nəhayət (və bu bölmənin mövzusundan bir qədər uzaqlaşaraq) aranızdan Spring-in veb-çərçivə MVC hissəsini istifadə edənlər üçün, PropertyEditorRegistrar
-ı internet tətbiqi daxilində məlumatların toplanması, işlənməsi və təfsiri ilə məşğul olan kontrollerlər ilə birgə istifadə etmək faydalı ola bilər. Aşağıdakı nümunədə PropertyEditorRegistrar
metodun @InitBinder
reallaşdırılmasında istifadə olunur:
@Controller
public class RegisterUserController {
private final PropertyEditorRegistrar customPropertyEditorRegistrar;
RegisterUserController(PropertyEditorRegistrar propertyEditorRegistrar) {
this.customPropertyEditorRegistrar = propertyEditorRegistrar;
}
@InitBinder
void initBinder(WebDataBinder binder) {
this.customPropertyEditorRegistrar.registerCustomEditors(binder);
}
// istifadəçi qeydiyyatı ilə əlaqəli digər metodlar
}
@Controller
class RegisterUserController(
private val customPropertyEditorRegistrar: PropertyEditorRegistrar) {
@InitBinder
fun initBinder(binder: WebDataBinder) {
this.customPropertyEditorRegistrar.registerCustomEditors(binder)
}
// istifadəçi qeydiyyatı ilə əlaqəli digər metodlar
}
Bu tərz PropertyEditor
qeydiyyatı, kodu qısa (metodun @InitBinder
reallaşdırılması cəmi bir sətirdir) və PropertyEditor
qeydiyyatının ümumi kodunu bir sinifdə kapsulləşdirərək həmin sinifin bir çox kontrollerlər tərəfindən paylaşmasını mümkün edir.
GO TO FULL VERSION