Proz S11

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 1

11. JavaBeans

11.1 Wprowadzenie

JavaBeans

to model przeno

ś

nych komponentów, stworzony w j

ę

zyku

Java (od 1996 r.), przeznaczony do tworzenia małych,
komponentów

programowych

wielokrotnego

u

ż

ytku,

w

szczególno

ś

ci wykorzystywanych w narz

ę

dziach programowania

wizualnego (np. BeanBox, VisualAge, JBuilder).

Bean

jest komponentem programowym – mo

ż

e by

ć

obiektem

wizualnym lub niewizualnym (jak np. kolejka czy stos), który mo

ż

e

wchodzi

ć

w skład apletów i aplikacji.


Pakiet

java.beans

nale

ż

y do podstawowego “Core API”

ś

rodowiska

Java.

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 2


Ziarno (Bean)

jest klas

ą

, z której mo

ż

na korzysta

ć

w narz

ę

dziu

projektowym (w fazie tworzenia programu), gdy

ż

posiada ona:

1.

gwarantowane cechy podstawowe, takie jak

serializacja

i

klonowanie

;

2.

implementuje

ustalone konwencje (nazw)

;

3.

deklaratywna (abstrakcyjna) posta

ć

składowych 3 rodzajów:

a. zdarzenia,
b. własno

ś

ci,

c. metody.

4.

korzysta z

mechanizmu introspekcji i refleksji

(meta-danych).

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 3

Gwarantowane cechy podstawowe:

bezparametrowy konstruktor (wzorce „Factory“),

interfejs

Clonable

, metoda

Clone

;

interfejs

Serializable

, pusty bez metod (serializacja składowych za

wyj

ą

tkiem

transient

i

static

) - metody

writeObject,

readObject;

lub

interfejs

Externalizable

, metody

writeExternal,

readExternal

.


Konwencje nazw

Zdarzenie

E

para metod

addEListener, removeEListener

Własno

ść

P

para metod

(

getP, setP

), wzgl

ę

dnie (

isP, setP

) dla

logicznego (

Boolean

)

P

:

- własno

ść

zwi

ą

zana – wymaga powiadamiania obserwatorów

zdarzenia typu

PropertyChange

-

własno

ść

z ograniczeniem - z prawem weta klientów, realizowana

poprzez wyj

ą

tek

PropertyVetoException

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 4

11.2 Definiowanie zdarze

ń

dla klasy ziarna

EventObject

Klasa

java.util.EventObject

jest bazow

ą

klas

ą

dla reprezentacji zdarze

ń

dla komponentów „ziaren” (Bean).

public class EventObject extends Object

implements java.io.Serializable {

public EventObject (Object source);
public Object getSource();
public String toString();
}

Mo

ż

na korzysta

ć

bezpo

ś

rednio z tej klasy dla wyra

ż

enia zdarzenia, ale

zwykle jednak tworzy si

ę

jej klasy pochodne dla specyficznych rodzajów

zdarze

ń

. Wtedy obiekt obsługi zdarzenia (obserwator) uzyskuje w

powiadomieniu o zdarzeniu obiekt specyficznej klasy pochodnej od

EventObject

.

Np.

public class HireEvent extends EventObject {

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 5

private long hireDate;
public HireEvent (Object source) {
super (source);
hireDate = System.currentTimeMillis();
}
public HireEvent (Object source, long hired) {
super (source);
hireDate = hired;
}
public long getHireDate () {
return hireDate;
}
}

EventListener

Pusty interfejs

EventListener

słu

ż

y do zaznaczania klasy jako

potencjalnego obserwatora zdarze

ń

. Konkretny rodzaj obsługi zdarze

ń

wynika z implementowania specyficznego interfejsu

EventTypeListener

,

pochodnego od

EventListener.

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 6

Np. dla nowego zdarzenia

HireEvent

odpowiedni interfejs nazywałby si

ę

HireListener

. Taki interfejs deklaruje metody obsługi tego zdarzenia. Np.

public interface HireListener extends java.util.EventListener {
public abstract void hired (HireEvent e);

// Metoda obsługi zdarzenia

}

Ź

ródło zdarzenia

Obiekty obserwatorów rejestruj

ą

si

ę

w obiekcie-

ź

ródle zdarzenia lub

wyrejestrowuj

ą

dzi

ę

ki odpowiednim metodom rejestracji, tworzonym

według wzoru:

public synchronized void addListenerType(ListenerType l);
public synchronized void removeListenerType(ListenerType l);

Przykładowy kod obu metod dla naszego komponentu:

private Vector hireListeners = new Vector();
public synchronized void addHireListener (HireListener l) {
hireListeners.addElement (l);
}
public synchronized void removeHireListener (HireListener l) {
hireListeners.removeElement (l);

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 7

}

Po zaj

ś

ciu zdarzenia wymagane jest powiadomienie obserwatorów tego

zdarzenia. Np. zrealizujemy metod

ę

dla rozgłaszania zdarzenia:

protected void notifyHired () {
Vector l;

// Utwórz obiekt opisu zdarzenia:

HireEvent h = new HireEvent (this);

// Kopiuj wektor z obiektami obsługi – zabezpiecza to przed zmianą
// obserwatorów podczas rozgłaszania:

synchronized (this) {
l = (Vector)hireListeners.clone();
}

// Powiadom po kolei wszystkich obserwatorów:

for (int i=0; i<l.size(); i++) {
HireListener hl = (HireListener)l.elementAt (i);
hl.hired(h);
}
}

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 8

11.3 Własno

ś

ci

Jest to publiczna cecha klasy ziarna, reprezentowana zwykle przez
nie-publiczne pole. Mo

ż

e mie

ć

dost

ę

p: read-write, read-only, lub

write-only. Wyró

ż

nia si

ę

4 rodzaje własno

ś

ci:

zwykłe,

indeksowane (indeksery),

zwi

ą

zane,

ograniczone.

Zwykłe własno

ś

ci

Dla własno

ś

ci P o dost

ę

pie „read-write” wymagana jest definicja pary

metod – konwencj

ą

jest nazywanie ich:

setP, getP

.

Np. własno

ść

salary :

float salary;
public void setSalary (float newSalary) {
salary = newSalary;
}

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 9

public float getSalary () {
return salary;
}

Własno

ś

ci typu logicznego mog

ą

zamieni

ć

metod

ę

getP

na

isP

. Np.

boolean trained;
public void setTrained (boolean trained) {
this.trained = trained;
}
public boolean isTrained () {
return trained;
}

Indeksery

Indekser to własno

ść

przechowuj

ą

ca tablic

ę

warto

ś

ci. Konwencja:

public void setPropertyName (PropertyType[] list)
public void setPropertyName (PropertyType element, int position)
public PropertyType[] getPropertyName ()
public PropertyType getPropertyName (int position)

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 10

Np. indekser

item

w klasie

List

mo

ż

e wygl

ą

da

ć

nast

ę

puj

ą

co:

public class ListBean extends List {
public String[] getItem () {
return getItems ();
}
public synchronized void setItem (String item[]) {
removeAll();
for (int i=0;i<item.length;i++)
addItem (item[i]);
}
public void setItem (String item, int position) {
replaceItem (item, position)
}
}

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 11

Własno

ś

ci zwi

ą

zane

Teraz uczynimy własno

ść

salary

własno

ś

ci

ą

zwi

ą

zan

ą

. Je

ś

li dwa obiekty

korzystaj

ą

z tej własno

ś

ci to o jej zmianie, powodowanej przez jeden z

nich, jest powiadamiany drugi obiekt.
W

tym

celu

nale

ż

y

zrealizowa

ć

list

ę

obserwatorów

dla

PropertyChangeEvent

poprzez klas

ę

PropertyChangeSupport

.

Najpierw tworzymy list

ę

obserwatorów:

private PropertyChangeSupport changes = new PropertyChangeSupport
(this);

Nale

ż

y ni

ą

zarz

ą

dza

ć

:

public void addPropertyChangeListener ( PropertyChangeListener p) {
changes.addPropertyChangeListener (p);
}
public void removePropertyChangeListener (PropertyChangeListener p) {
changes.removePropertyChangeListener (p);
}

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 12

Je

ś

li zajdzie zdarzenie (tu jest nim wywołanie metody

setSalary

),

sprawdzamy czy warto

ść

własno

ś

ci uległa zmianie i je

ś

li tak, to

powiadamiamy obserwatorów:

public void setSalary (float salary) {
Float oldSalary = new Float (this.salary);
this.salary = salary;
changes.firePropertyChange (
"salary", oldSalary, new Float (this.salary));
}

Po stronie obserwatora potrzebna jest metoda

propertyChange

:

public void propertyChange(PropertyChangeEvent e);

W metodzie tej sprawdzamy metod

ą

getPropertyName

to czy otrzymali

ś

my

zdarzenie wła

ś

ciwego typu -

PropertyChangeEvent

.

Własno

ś

ci z ograniczeniami

Te własno

ś

ci s

ą

podobne do własno

ś

ci zwi

ą

zanych ale dodatkowo do listy

PropertyChangeListener

ziarno zarz

ą

dza list

ą

VetoableChangeListener

.

Wtedy przed wykonaniem zmiany własno

ś

ci ziarno pyta obserwatorów na

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 13

li

ś

cie

VetoableChangeListener

o pozwolenie. Je

ś

li odpowied

ź

jest

negatywna to ziarno zgłasza wyj

ą

tek

PropertyVetoException

, deklarowany

przez metod

ę

setP

.

Np. uzupełniamy własno

ść

salary

o :

private VetoableChangeSupport vetoes = new VetoableChangeSupport (this);
public void addVetoableChangeListener ( VetoableChangeListener v) {
vetoes.addVetoableChangeListener (v);
}
public void removeVetoableChangeListener (VetoableChangeListener v){
vetoes.removeVetoableChangeListener (v);
}

Zmieniamy metod

ę

setSalary

:

public void setSalary (float salary) throws PropertyVetoException {
Float oldSalary = new Float(this.salary);
vetoes.fireVetoableChange("salary", oldSalary, new Float(salary));
this.salary = salary;
changes.firePropertyChange("salary", oldSalary, new Float(this.salary));
}

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 14

Po

stronie

obserwatora

dodajemy

metod

ę

interfejsu

VetoableChangeListener

o nazwie

vetoableChange

:

public void vetoableChange(PropertyChangeEvent e)
throws PropertyVetoException;


Mo

ż

liwe jest te

ż

rozdzielenie obu list – zdarzenia zmiany własno

ś

ci i

zdarzenia wetowalnej zmiany własno

ś

ci – zarz

ą

dzanie oddzieln

ą

list

ą

dla

ka

ż

dej własno

ś

ci. Wzorzec tego rozwi

ą

zania:

public void addPropertyNameListener ( PropertyChangeListener p);
public void removePropertyNameListener ( PropertyChangeListener p);

public void addPropertyNameListener (VetoableChangeListener v);
public void removePropertyNameListener (VetoableChangeListener v);

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 15

11.4 Trwało

ść

/ serializacja

Ziarna s

ą

obiektami ze stanen

i powinny by

ć

trwałymi obiektami

.

1) Standardowa serializacja - interfejs

Serializable

Jest to zdolno

ść

obiektu do zapami

ę

tania swojego stanu w celu

ź

niejszego odtworzenia. W tym celu komponenty korzystaj

ą

z

mechanizmu

serializacji w j

ę

zyku Java

.

Podstawowe interfejsy w zakresie serializacji to

ObjectInput

i

ObjectOutput

a podstawowe klasy implementuj

ą

ce te interfejsy to

ObjectInputStream

i

ObjectOutputStream

.

Obiekt klasy implementuj

ą

cej

Serializable

jest serializowany metod

ą

ObjectOutput.writeObject

(z

obiektem

b

ę

d

ą

cym

parametrem)

i

deserializowany metod

ą

ObjectInput.readObject

.

Standardowa realizacja mechanizmu serializacji pozwala zapami

ę

ta

ć

wszystkie

niestatyczne

i

nietymczasowe (non-transient)

pola obiektu w

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 16

pliku binarnym o formacie danych przyj

ę

tym w metodach

writeObject /

readObject.

Plik posiada rozszerzenie

.ser

.


Je

ś

li w polu serializowanego obiektu referowany jest inny obiekt, to

równie

ż

ten inny obiekt jest rekursywnie zapami

ę

tywany - ta

dekompozycja jest kontynuowana, a

ż

pozostan

ą

wył

ą

cznie dane typów

prostych, które s

ą

bezpo

ś

rednio zapami

ę

tywane.

Przykład

. Utwórzmy obiekty klasy

TreeNode

:

TreeNode top = new TreeNode("top");
top.addChild(new TreeNode("left child"));
top.addChild(new TreeNode("right child"));

Zapami

ę

tujemy te obiekty:

FileOutputStream fOut = new FileOutputStream("test.ser");
ObjectOutput out = new ObjectOutputStream(fOut);
out.writeObject(top);

// Zapisz obiekt – zapisze również jego 2

// podobiekty

out.flush();
out.close();

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 17

Po zako

ń

czeniu programu i ponownym jego restarcie mo

ż

liwe b

ę

dzie

odtworzenie obiektu na podstawie pliku test.ser.

FileInputStream fIn = new FileInputStream("test.ser");
ObjectInputStream in = new ObjectInputStream(fIn);
TreeNode n = (TreeNode)in.readObject();

W metodzie

readObject()

nast

ę

puje alokacja pami

ę

ci dla obiektu ziarna i

wywoływany jest bezargumentowy konstruktor jego klasy.

2) Interfejs

Externalizable

Je

ś

li plik z serializowanym obiektem ma posiada

ć

specyficzny format, to

programista powinien skorzysta

ć

z interfejsu

Externalizable

i odpowiednio

zdefiniowa

ć

jego 2 metody:

readExternal

i

writeExternal

. Klasa

serializowanego obiektu musi posiada

ć

bezargumentowy konstruktor.

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 18

3) Trwało

ść

długo-okresowa

Poj

ę

cie to oznacza model trwałego pami

ę

tania ziaren w formacie XML.

XMLEncoder, XMLDecoder

Klasa

XMLEncoder

przeznaczona jest to wypisywania serializowalnych

obiektów do plików tekstowych w formacie XML.


Przykład.

Wypisanie ziarna i jego własno

ś

ci w postaci XML:

XMLEncoder encoder = new XMLEncoder(
new BufferedOutputStream(
new FileOutputStream( "Beanarchive.xml" ) ) );
encoder.writeObject( object );
encoder.close();

Klasa

XMLDecoder

przeznaczona jest do odtworzenia obiektu z

dokumentu XML, wcze

ś

niej utworzonego przez

XMLEncoder.

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 19

Przykład

XMLDecoder decoder = new XMLDecoder(
new BufferedInputStream(
new FileInputStream( "Beanarchive.xml" ) ) );

Object object = decoder.readObject();
decoder.close();

Znaczniki

XML

Dla reprezentacji ziarna w j

ę

zyku XML u

ż

ywane s

ą

nast

ę

puj

ą

ce znaczniki:

W preambule XML podana jest wersja XML i rodzaj kodowania.

Znacznik

<java>

zawiera wszystkie elementy obiektu ziarna.

Znacznik

<object>

reprezentuje zbiór wywoła

ń

metod niezb

ę

dnych do

rekonstrukcji obiektu z jego serializowanej postaci :

<object class="javax.swing.JButton" method="new">

<string>Ok</string>

</object>

lub wyra

ż

enia

<object class="javax.swing.JButton">

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 20

<void method="setText">
<string>Cancel</string>
</void>
</object>

Znaczniki dla definiowania typów prostych:

o

<boolean>

o

<byte>

o

<char>

o

<short>

o

<int>

o

<long>

o

<float>

o

<double>

Np.

<int>5555</int>

Znacznik

<class>

dla reprezentacji instancji klasy

Class

:

<class>java.swing.JFrame</class>

Znacznik

<array>

dla reprezentacji tablicy:

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 21

<array class="java.lang.String" length="5">

</array>

Przykład archiwum w XML generowanego przez komponent

SimpleBean

:

<?xml version="1.0" encoding="UTF-8" ?>
<java>
<object class="javax.swing.JFrame">
<void method="add">
<object class="java.awt.BorderLayout" field="CENTER"/>
<object class="SimpleBean"/>
</void>
<void property="defaultCloseOperation">
<object class="javax.swing.WindowConstants" field="DISPOSE_ON_CLOSE"/>
</void>
<void method="pack"/>
<void property="visible">
<boolean>true</boolean>
</void>
</object>
</java>

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 22

4) Problem serializacji

Jak zapewni

ć

serializowalno

ść

obiektu naszej klasy?

1. Czy nasza klasa implementuje interfejs

Serializable

(bezpo

ś

rednio lub

po

ś

rednio) lub

Externalizable

?

2. Czy wszystkie pola klasy

s

ą

serializowalne

?

Pola typów prostych (tzw. „dla warto

ś

ci”) s

ą

zawsze serializowalne.

Pozostałe pola, b

ę

d

ą

ce typu klas, nale

ż

y sprawdza

ć

indywidualnie. Np.

klasa

Image

nie jest serializowalna. Nale

ż

y wtedy zdecydowa

ć

, czy

nale

ż

y i jak zapami

ę

tywa

ć

takie pola – przy odtwarzaniu wczytywa

ć

dane z osobnego pliku, stawia

ć

je na warto

ś

ci domy

ś

lne zaznaczy

ć

pola

jako

transient

, itd.

3. Upewni

ć

si

ę

, czy chcemy zapami

ę

ta

ć

wszystkie pola, które nie s

ą

zaznaczone jako

transient

lub

static

.

4. Czy odpowiada nam

domy

ś

lny mechanizm serializacji

, czy te

ż

chcemy

zapami

ę

ta

ć

obiekt w innej strukturze, np. dokonuj

ą

c jego kompresji lub

szyfrowania?

5. Jak zainicjalizowa

ć

pola

transient

i

static

po deserializacji obiektu

?

6. Czy proces deserializacji ma by

ć

uzupełniony o walidacj

ę

?

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 23

Walidacja deserializowanego obiektu

zwykle polega na sprawdzeniu jego

poprawno

ś

ci - zgodno

ś

ci z zadanym modelem dla danego typu. W tym

celu nale

ż

y utworzy

ć

i zarejestrowa

ć

metod

ę

walidacji.

Przykład.

Chcemy odtworzy

ć

obiekt klasy

Date

, ale ma on odpowiada

ć

„ostatniej” dacie a nie “pierwszej dacie”.
W tym celu mo

ż

emy wprowadzi

ć

pole charakteryzowane jako

transient

,

które jest zerowane podczas deserializacji.

public class TreeNode implements Serializable {
Vector children;
TreeNode parent;
String name;
transient Date date;

// Pole przejściowe - nietrwałe

public TreeNode(String s) {
children = new Vector(5);
name = s;
initClass();
}
private void initClass () {

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 24

date = new Date();

// Tu nadajemy nową wartość polu przejściowemu

}
...
private void writeObject(ObjectOutputStream s)
throws IOException {
s.defaultWriteObject();
}
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException {
s.defaultReadObject();
initClass();
}
}

Uwaga: metody

writeObject

i

readObject

nadpisywane s

ą

parami – w

przeciwnym razie nadpisanie metody

writeObject

nie byłoby tu potrzebne.

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 25

5) Odtworzenie / utworzenie ziarna metod

ą

-

Beans.instantiate

Zamiast tworzenia instancji ziarna operatorem

new

mo

ż

na te

ż

skorzysta

ć

z

metody

Beans.instantiate

. Jest to typowy sposób odtworzenia obiektu

ziarna po uprzedniej serializacji. W ten sposób nie musimy zna

ć

nazw

wszystkich potencjalnych klas ziaren w momencie tworzenia kodu.

Np. utworzenie obiektu klasy

TextField

bez korzystania z

new

:

Component c = (Component)Beans.instantiate(null, "java.awt.TextField");

Jest to równowa

ż

ne w działaniu z kodem:

Component c = new TextField();

Aby przekona

ć

si

ę

o ró

ż

nicy utwórzmy klas

ę

pochodn

ą

MyTextField

:

public class MyTextField extends java.awt.TextField {
}

Nast

ę

pnie w poni

ż

szym programie dokonamy serializacji obiektu klasy

MyTextField:

import java.awt.*;
import java.io.*;

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 26

public class TfSaver {
public static void main(String args[]) {
MyTextField mtf = new MyTextField();

// Ustaw własności:

Font ft = new Font("Serif", Font.ITALIC, 36);
mtf.setFont(ft);
mtf.setText("Hello World");

// Serializuj:

try {
FileOutputStream f = new FileOutputStream("MyTextField.ser");
ObjectOutputStream s = new ObjectOutputStream(f);
s.writeObject(mtf);
s.flush();
} catch (Exception e) {
System.out.println(e);
}
System.exit(0);
}
}

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 27

Aplikacja korzystaj

ą

ca z instancji

MyTextField

b

ę

dzie miała ju

ż

ustawione

własno

ś

ci

font

i

text

(na czcionk

ę

36-pt, italic, Serif i napis "Hello World").


W celu odtworzenia zastosujemy wywołanie

Beans.instantiate

o postaci:

Component c = (Component)Beans.instantiate(null, "MyTextField");

Dzi

ę

ki metodzie

Beans.instantiate

mamy wi

ę

ksz

ą

elastyczno

ść

tworzenia

instancji: je

ś

li istnieje plik o nazwie

NazwaKlasy.ser

(w tym przypadku

MyTextField.ser

) to nast

ą

pi deserializacja obiektu na podstawie danych z

tego pliku; w przeciwnym razie obiekt ziarna zostanie zainicjalizowany
bezargumentowym konstruktorem w tej klasie.

Gdy istnieje

MyTextField.ser

:

Gdy nie ma pliku

MyTextField.ser:

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 28

6) Zarz

ą

dzanie wersjami klas ziaren

Ewentualne zmiany, dokonywane w definicji klasy, mog

ą

dotyczy

ć

struktury danych lub metod.
Je

ś

li zmieniamy struktur

ę

trwałych danych klasy ziarna to obiekty

wcze

ś

niejszych wersji tej klasy nie mog

ą

by

ć

deserializowane.

Nawet dodanie metody do klasy ziarna czyni obiekt wcze

ś

niejszej wersji

niemo

ż

liwy do deserializacji – próba deserializacji zako

ń

czy si

ę

wyj

ą

tkiem

java.io.InvalidClassException

.


Jednak dodanie lub usuni

ę

cie metody nie ma wpływu na informacj

ę

o

stanie obiektu (metody wyra

ż

aj

ą

zachowanie obiektu a to nie jest

serializowane) i z tego punktu widzenia obiekty dwóch wersji klasy,

ż

ni

ą

ce si

ę

jedynie metodami, powinny by

ć

zgodne w procesie

deserializacji.
Aby zapewni

ć

mo

ż

liwo

ść

odtworzenia stanu obiektu “poprzedniej” wersji

klasy w obiekcie “nowej” wersji tej klasy nale

ż

y doda

ć

pole statyczne

zawieraj

ą

ce warto

ść

Stream Unique Identifier (SUID)”:

Np.

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 29

private static final long serialVersionUID = -2966288784432217853L;

Warto

ść

pola jest regenerowana podczas deserializacji i jest

porównywana z aktualn

ą

definicj

ą

klasy.

Warto

ś

ci SUID s

ą

generowane przez program

serialver

z argumentem,

b

ę

d

ą

cym nazw

ą

klasy, w wyniku algorytmu z funkcj

ą

mieszaj

ą

c

ą

(„hash”).


Program

serialver

mo

ż

e by

ć

tez wywołany jawnie z opcj

ą

–show

i wtedy

pojawi si

ę

graficzny interfejs, który pozwoli programi

ś

cie przej

ąć

warto

ść

SUID, wygenerowan

ą

dla zadanej klasy i umie

ś

ci

ć

j

ą

w kodzie programu.

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 30

11.5 Introspekcja i refleksja

1) Mechanizm refleksji

Nale

ż

y on do podstawowych elementów j

ę

zyka – jego API stanowi

pakiet

java.lang.reflection

. Umo

ż

liwia on m.in.:

Okre

ś

lenie

klasy

obiektu.

Np.

TextField t = new TextField();
Class c = t.getClass();

// Klasa na podstawie obiektu

Class s = c.getSuperclass();

// Klasa bazowa

Class c = java.awt.Button.class;

// Jawnie znana klasa

Class c = Class.forName(strg);

// Nazwa to strg

Informowanie o

modyfikatorach klasy, polach, metodach,

konstruktorach i klasie bazowej

.

Informowanie o przynale

ż

no

ś

ci

stałych i metod do interfejsu

.

Utworzenie obiektu

klasy nieznanej podczas programowania.

Np.

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 31

Class cl = Class.forName(className);
obiekt = cl.newInstance();

Pobranie i ustawienie warto

ś

ci pola, nawet gdy podczas

programowania nie jest znana nazwa tego pola.

Wywołanie metody, nawet gdy nie jest znana jej nazwa.

Utworzenie i modyfikacj

ę

tablicy o elementach nieznanego typu.

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 32

2) Interfejs

BeanInfo

BeanInfo

pozwala rozszerzy

ć

mechanizm refleksji w odniesieniu do ziaren.

Dla pewnej klasy programisty

Beanclass

mo

ż

na stworzy

ć

klas

ę

BeanclassBeanInfo

i zaimplementowa

ć

we własny sposób metody

BeanInfo

.

Istnieje klasa

SimpleBeanInfo

, z której mo

ż

e dziedziczy

ć

nasza klasa

BeanclassBeanInfo

i wtedy wystarczy nadpisa

ć

jedynie niektóre z metod

BeanInfo

.


Tryb pracy ziarna: “w czasie projektowania” i “w czasie wykonania”

Podczas projektowania klasa ziarna musi udost

ę

pnia

ć

narz

ę

dziu

projektowemu informacje pozwalaj

ą

ce na edycj

ę

(i ustawianie) własno

ś

ci

oraz definicje rozszerze

ń

własnych programisty.

Musi te

ż

udost

ę

pnia

ć

metody i zdarzenia tak, aby program projektowy

Builder” mógł wygenerowa

ć

wła

ś

ciwy kod metod klasy ziarna.


Metoda

Beans.isDesignTime

pozwala sprawdzi

ć

tryb pracy ziarna.

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 33

Interfejs

BeanInfo

dostarcza

w

fazie

projektowej

(narz

ę

dziom

programowania wizualnego) wybranych informacji (meta-danych) o klasie
ziarna

Beanclass

.


Jawna

specyfikacja

klasy

BeanclassBeanInfo

jest

nadpisaniem

standardowej

introspekcji

i

blokuje mechanizm refleksji

w fazie

projektowej.


Własna implementacja interfejsu

BeanInfo

umo

ż

liwia:

o

Specyfikacj

ę

własnej ikonki dla ziarna;

o

Dostarczenie dodatkowego opisu ziarna;

o

Dostarczenie opisów cech (klasy pochodne od

FeatureDescriptor

)



BeanDescriptor



EventSetDescriptor



PropertyDescriptor



MethodDescriptor

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 34

3) Introspekcja

Jest to proces

pozyskiwania informacji

o własno

ś

ciach, metodach i

zdarzeniach danego ziarna. Do tego celu słu

ż

y klasa

Introspector

.

Innym sposobem introspekcji jest skorzystanie z mechanizmu

refleksji

(“Reflection”).

Klasa

Introspector

odwołuje si

ę

do wła

ś

ciwej klasy-implementacji

BeanInfo

dla klasy ziarna – dzi

ę

ki metodzie

getBeanInfo

posiadaj

ą

cej parametr typu

Class

:

TextField tf = new TextField ();
BeanInfo bi = Introspector.getBeanInfo (tf.getClass());

Je

ś

li nie zdefiniowano

specyficznej klasy implementuj

ą

cej interfejs

BeanInfo

dla klasy ziarna, to

Introspector

korzysta z mechanizmu refleksji

w celu pobrania opisów zdarze

ń

, własno

ś

ci i metod klasy ziarna.

Opis zdarze

ń

Metoda

getEventSetDescriptors

podaje wszystkie zdarzenia zgłaszane

przez

zadan

ą

klas

ę

ziarna.

Dla

ka

ż

dej

pary

metod

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 35

add/removeListenerTypeListener

(zwracaj

ą

cych

void

) powstaje jeden opis

zdarzenia:

EventSetDescriptor[] esd = bi.getEventSetDescriptors();
for (int i=0;i<esd.length;i++) System.out.print (esd[i].getName() + " ");
System.out.println ();

Wynik wykonania powy

ż

szego kodu dla klasy

TextField

:

text mouse key component action focus mouseMotion

Opis własno

ś

ci

Metoda

getPropertyDescriptors

podaje wszystkie własno

ś

ci klasy ziarna.

Np.

public void setPropertyName(PropertyType value);
public PropertyType getPropertyName();
public boolean isPropertyName();
PropertyDescriptor[] pd = bi.getPropertyDescriptors();
for (int i=0;i<pd.length;i++) System.out.print (pd[i].getName() + " ");
System.out.println ();

Wynik wykonania powy

ż

szego kodu dla klasy

TextField

:

selectionStart enabled text preferredSize

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 36

foreground visible background selectedText
echoCharacter font columns echoChar name
caretPosition selectionEnd minimumSize editable

Opis metod

Metoda

getMethodDescriptors

podaje wszystkie publiczne metody klasy

ziarna. Pozwala o wywoła

ć

te metody bez znajomo

ś

ci ich nazwy. Dla

ka

ż

dej metody pobieramy typy jej parametrów dzi

ę

ki metodzie

getParameterDescriptors

.

MethodDescriptor[] md = bi.getMethodDescriptors();
for (int i=0;i<md.length;i++) System.out.print (md[i].getName() + " ");
System.out.println ();

Wynik wykonania powy

ż

szego kodu dla klasy

TextField

to wydruk nazw

155 metod, w wi

ę

kszo

ś

ci dziedziczonych z klasy C

omponent.

Lista metod

obejmuje równie

ż

metody

add/removeListenerTypeListener

.

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 37

Specyficzna klasa implementuj

ą

ca

BeanInfo

Definiuj

ą

c własn

ą

klas

ę

implementuj

ą

c

ą

BeanInfo

mo

ż

emy ograniczy

ć

elementy klasy ziarna udost

ę

pniane edytorom projektowym.

Dla klasy ziarna o przykładowej nazwie

SizedTextField

wła

ś

ciwa nazwa

klasy implementuj

ą

cej

BeanInfo

wynosi

SizedTextFieldBeanInfo

.


Np. gdy chcemy w trybie introspekcji udost

ę

pni

ć

jedynie jedn

ą

własno

ść

tej klasy - length - to zdefiniujemy nast

ę

puj

ą

c

ą

klas

ę

typu

BeanInfo

:

import java.beans.*;
public class SizedTextFieldBeanInfo extends SimpleBeanInfo {
private final static Class beanClass = SizedTextField.class;
public PropertyDescriptor[] getPropertyDescriptors() {
try {
PropertyDescriptor length = new PropertyDescriptor("length",

beanClass);

PropertyDescriptor [] rv = {length};
return rv;
} catch (IntrospectionException e) {
throw new Error(e.toString());

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 38

}
}
}

Teraz zamiast 17 własno

ś

ci klasy

TextField

, jedyn

ą

wy

ś

wietlan

ą

własno

ś

ci

ą

stworzonej klasy pochodnej b

ę

dzie nowa własno

ść

: length.

Oczywi

ś

cie w klasie

SizedTextField

nale

ż

y jeszcze zdefiniowa

ć

metody

set/getLength

. Jednak wszystkie własno

ś

ci i metody tej klasy s

ą

nadal

dost

ę

pne dla programu i mog

ą

by

ć

wywoływane w wykonywanym

programie. Równie

ż

mechanizm refleksji “widzi” wszystkie publiczne

metody.

Mo

ż

na przekaza

ć

do edytora projektu czytelniejsz

ą

nazw

ę

klasy. Np. dla

klasy

SizedTextField

czytelniejsze jest oddzielenie słów składowych:

public BeanDescriptor getBeanDescriptor() {
BeanDescriptor bd = new BeanDescriptor(beanClass);
bd.setDisplayName

("Sized Text Field")

;

return bd;
}

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 39

Mo

ż

na przekaza

ć

ikonk

ę

dla klasy ziarna, przy pomocy nast

ę

puj

ą

cej

metody dodanej do klasy implementuj

ą

cej

BeanInfo

:

public Image getIcon (int iconKind) {
if (iconKind == BeanInfo.ICON_COLOR_16x16) {
Image img = loadImage("sized.gif");
return img;
}
return null;
}

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 40

11.6 Przykład klasy ziarna

Klasy ziaren nie musz

ą

reprezentowa

ć

graficznych obiektów, chocia

ż

takie

jest ich typowe zastosowanie – w tej technologii stworzono pakiety AWT i
Swing dla

ś

rodowiska Java. Dobr

ą

reguł

ą

dla stwierdzenia, czy warto

implementowa

ć

klas

ę

jako ziarno, jest pozytywna odpowied

ź

na pytanie,

czy warto stosowa

ć

technik

ę

„drag-and-drop” do pochwycenia obiektu tej

klasy z zestawu komponentów i przeniesienia go do przestrzeni roboczej
projektu, podczas tworzenia aplikacji.

Klasa

Hire

, zrealizowana w technologii ziarna, symuluje minimalny zestaw

operacji dla zatrudnienia pracownika.

package hire;
import java.util.*;
public class HireEvent extends EventObject {
private long hireDate;
public HireEvent(Object source) {
super(source);
hireDate = System.currentTimeMillis();

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 41

}
public long getHireDate() {
return hireDate;
}
}


Obserwatorzy

zainteresowani

procesem

zatrudnienia

musz

ą

zaimplementowa

ć

odpowiedni interfejs i zarejestrowa

ć

si

ę

w celu

uzyskania powiadomie

ń

o zaj

ś

ciu zdarzenia:

package hire;
import hire.*;
public interface HireListener extends java.util.EventListener {
public abstract void hired(HireEvent e);
}

W klasie Hire zarz

ą

dzamy list

ą

obserwatorów:

package hire;
...
public class Hire implements Serializable {

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 42

...
private Vector hireListeners = new Vector();
private PropertyChangeSupport changes =

new PropertyChangeSupport(this);

public Hire() {
}
public synchronized void addHireListener(HireListener l) {
hireListeners.addElement(l);
}
public synchronized void removeHireListener(HireListener l) {
hireListeners.removeElement(l);
}

Powiadomienie obserwatorów nast

ę

puje dzi

ę

ki metodzie

notifyHired():

protected void notifyHired() {
Vector l;
HireEvent h = new HireEvent(this);
synchronized(this) {
l = (Vector)hireListeners.clone();

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 43

}
for (int i = 0; i < l.size(); i++) {
HireListener hl = (HireListener)l.elementAt(i);
hl.hired(h);
}
}

Własno

ść

salary

w klasie

Hire

jest zwi

ą

zana:

public void addPropertyChangeListener( PropertyChangeListener p) {
changes.addPropertyChangeListener(p);
}
public void removePropertyChangeListener( PropertyChangeListener p) {
changes.removePropertyChangeListener(p);
}
public void setSalary(float salary) {
float old = this.salary;
this.salary = salary;
changes.firePropertyChange("salary", new Float(old), new Float(salary));
}
public float getSalary() {

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 44

return salary;
}


Z klas

ą

ziarna zwi

ą

zana jest klasa implementuj

ą

ca

BeanInfo

– jak dot

ą

d

udost

ę

pniaj

ą

ca (publikuj

ą

ca) jedynie własno

ść

salary

:

package hire;
import java.beans.*;
public class HireBeanInfo extends SimpleBeanInfo {
public PropertyDescriptor[] getPropertyDescriptors() {
try {
PropertyDescriptor pd1 = new PropertyDescriptor("salary", Hire.class);
pd1.setBound(true);
return new PropertyDescriptor[] {pd1};
} catch (Exception e) {
return null;
}
}
}

background image

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 45

11.7 BeanContext

Pakiet

java.beans.beancontext

zawiera

interfejsy

i

klasy

przeznaczone do grupowania ziaren w hierarchi

ę

i dodawanie ziaren

do kontenera:

Hierarchia ziaren mo

ż

e stanowi

ć

abstrakcyjne

ś

rodowisko

(kontekst)

funkcjonowania poszczególnych ziaren JavaBeans

Elementy maszyny wirtualnej Java wspomagaj

ą

dynamiczne

dodawanie dowolnych usług

do

ś

rodowiska JavaBeans.

JVM

udost

ę

pnia

ziarnom

mechanizmy

poszukiwania

i

wywoływania usług

w

ś

rodowisku JavaBeans.


BeanContext

- logiczne poł

ą

czenie ziaren w posta

ć

“kontekstu”, z

którym poszczególne ziarna mog

ą

si

ę

kontaktowa

ć

.

Dwa rodzaje kontekstu

BeanContext

:

- tylko zawieranie - interfejs

BeanContext

;

- zawieranie i usługi - interfejs

BeanContextServices.

11. JavaBeans

W. Kasprzak: Programowanie zdarzeniowe.

11- 46

Oba interfejsy posiadaj

ą

standardowe implementacje:

BeanContext



BeanContextSupport

BeanContextServices



BeanContextServicesSupport


Interfejs

BeanContextChild

umo

ż

liwia zagnie

ż

d

ż

oym ziarnom

JavaBeans komunikacj

ę

z obejmuj

ą

cym je kontekstem

BeanContext

.


Wyszukiwarka

Podobne podstrony:
Proz-S11
Proz S2 id 402992 Nieznany
Proz S12 id 402989 Nieznany
Proz S6
Sm s11 lvl2 v11
chemia proz maj 2011 cke id 112 Nieznany
Proz-S6
01 L B R 1 s01 s11
sm s11 lvl25 v12
S11 Teoria
Proz S9 id 402999 Nieznany
Proz S8 id 402998 Nieznany
Proz S13 id 402990 Nieznany
Proz S4 id 402994 Nieznany
Proz-S0
Proz S3 id 402993 Nieznany
Proz S0
Proz S14 id 402991 Nieznany

więcej podobnych podstron