SWT 17.6.99 JAVABEANS und Komposition • JAVABEANS Oliver Stiemerling Universität Bonn – Events – Properties – Reflection • Komposition – Alternative Ansätze – Vergleich Überblick JAVABEANS • Komponentenmodell: – Was ist eine Komponente? – Wie interagieren Komponenten? – Wie werden Komponenten "verdrahtet"? • JAVABEANS: – Komponente = Menge von Java Klassen (hauptsächlich GUI, aber auch unsichtbare Komponenten) – Interaktion über Events – Verdrahtung durch Entwicklungswerkzeug Event Interaktion: Grundlagen • Event "Quelle" (source) ruft eine Eventhandling Methode beim Event "Zuhörer" (listener) auf: e Instanz Komponente A handleSWTEvent(e); addSWTListener(l); removeSWTListener(l); SWTListener Interface Instanz Komponente B handleSWTEvent(e); actionPerformed(e); • Es wird keine Resultat zurückgegeben... Event Interaktion: Verbindungen • Multicast: – >1 Eventlistener – keine garantierte Reihenfolge! e Instanz Komponente A addSWTListener(l); removeSWTListener(l); • Fan-in: – Ein Listener hört auf >1 Quellen – Synchronisierung? – synchronized SWTListener Interface Instanz Komponente B handleSWTEvent(e); Event Interaktion: Elemente e Instanz Komponente A handleSWTEvent(e); addSWTListener(l); removeSWTListener(l); • • • • SWTListener Interface Instanz Komponente B handleSWTEvent(e); Event Klasse: SWTEvent Eventlistener Interface: SWTListener Eventsource Klasse: A Eventlistener Klasse: B Event Klasse: SWTEvent public class SWTEvent extends java.util.EventObject { private int info; // zusätzliche Informationen zum Ereignis public SWTEvent (Object source, int info) { super (source); this.info = info; } public int getInfo () {return info;} } Eventlistener Interface: SWTListener public interface SWTListener extends java.util.EventListener { public void handleEvent (SWTEvent e); } Eventsource Klasse: A public class A { Vector listeners = new Vector (); public void synchronized addSWTListener (SWTListener listener) { listeners.addElement (listener); } public void synchronized removeSWTListener (SWTListener listener) { listeners.removeElement (listener); } private void fireSWTEvent () { SWTEvent e = new SWTEvent (this, 9999); int n = listeners.size (); for (int i = 0; i < n; i++) { (SWTListener) listeners.elementAt (i).handleEvent(e); } } } Daran erkennt man eine Event Quelle! Eventlistener Klasse: B public class B implements SWTListener { ... public void handleEvent(SWTEvent e) { doSomething(); ... } } Daran erkennt man einen Event Listener! Zusammenfassung Events • Events werden durch void method calls realisiert • multicast und fan-in sind möglich • 4 Implementierungselemente: – Event Klasse – EventListener Inferface – Eventsource Klasse (Methodensignaturen) – Eventlistener Klasse (implementiert Interface) • "Umverdrahten" zur Laufzeit möglich Events ++: Adapter • Event soll einen bestimmten, nicht antizipierten Methodenaufruf im Listener verursachen e Instanz Komponente A addSWTListener(l); removeSWTListener(l); Adapter SWTListener Interface => Mehr Flexibilität handleSWTEvent(e); machWasBesonderes(); Instanz Komponente B machWasBesonderes(); JAVABEANS: Properties • Properties = (veränderbare) Eigenschaften einer Komponente • Methodensignatur: void setHintergrundfarbe (Farbe wert); Farbe getHintergrundfarbe(); • Drei Arten von Properties: – "silent" – bound: Änderungen erzeugen Events – constraint: Änderungen erzeugen Events und können verhindert werden JAVABEANS: Reflection • Dynamisches Nachladen einer Klasse: Klasse = ClassLoader.loadClass("Unbekannt", true); • Analyse der Methoden der Klasse Methoden[ ] = Klasse.getMethods(); ... if (Methoden[i].getName.startsWith("add")) { }; • Dynamisches Aufrufen von Methoden Methoden[i].invoke(Instanz_von_Klasse,Parameter[ ]); JAVABEANS: Benutzungsmodell • Entwickler erhält Bean mit allen Klassen & Ressourcen (z.B. bitmaps) als JAR Datei • Entwicklungswerkzeug analysiert Bean => Event (Ein- und Ausgänge), Methoden, Properties • Komposition: Bean wird instanziiert, Properties werden gesetzt, Instanz wird mit anderen Bean Instanzen "verdrahtet" • "Netz" von Beans wird persistent gemacht Design Modus -------> Runtime Modus Komposition • "Beschreibung eines Systems von Softwarekomponenten" • Unterschiedliche Ansätze • Gemeinsame Elemente: – Komponenteninstanzen – Komponenteneigenschaften – Komponentenverbindungen Komponenten A B C D A D B C A laufendes System Kompositionswerkzeuge Komponentenmodell • • • • IBM Visual Age MS Visual Basic Unix Shell Skripte Regis (DARWIN) JAVABEANS COM Pipes & Filters "Applikationen" => Vielzahl von unterschiedlichen Komponentenmodellen => Vielzahl von Kompositionsmethoden IBM Visual Age for Java • Visuelle Komposition • Erzeugt reinen Java Code • Komposition wird compiliert • => System = "normales" Java Programm IBM Visual Age: erzeugter Code public class SWTFrame extends java.awt.Frame private java.awt.Button ivjButton1 = null; public SWTFrame() { initialize(); } private void initialize() { getButton1().addActionListener(this); } private java.awt.Button getButton1() { if (ivjButton1 == null) { ivjButton1 = new java.awt.Button(); ivjButton1.setName("Button1"); ivjButton1.setBounds(53, 29, 134, 37); ivjButton1.setLabel("Und tschüß"); }; return ivjButton1; MS Visual Basic • Visuelle Komposition + Scripting • Skript wird in speziellen P-Code übersetzt • Komponenten selber in C++ (compiliert) => System = P-Code + Komponenten + VB Runtime Unix Shell Skript #!/bin/sh # Test auf unbekannte Schluesselwoerter awk '! /^#/' keywords | tr -c '[A-Z][a-z]' '[\012*]' | sort -u > /tmp/words Komponenteninstanzen Komponenteneigenschaften grep -h '^#Keys' $* | tr -c '[A-Z][a-z]' '[\012*]' | Komponentenverbindungen grep -v 'Keys' | sort -u | comm -23 - /tmp/words > /tmp/unknown echo "Unknown keywords:" cat /tmp/unknown © Nierstrasz & Schneider => System = Skript-file + Executables DARWIN: Eine Kompositionssprache für verteilte Systeme • Komponenten: lokale Applikationen / Prozesse • Verbindungen: Methodenaufrufe ("Services") System Instanz2 Instanz1 component System { required input daten; provided output daten; Output Input Port1 Port2 Port1 Port2 subcomponent Instanz1 ExeA@machine1(Parameter1 = 5); subcomponent Instanz2 ExeA@machine2; bind Instanz1.Port1 -- Input bind Instanz1.Port2 -- Instanz2.Port1; bind Instanz2.Port2 -- Output; } => System = Darwin file + Executables + Runtime Umgebung DARWIN Ablauf Executable.exe ... Andere.exe component System { required input daten; provided output daten; subcomponent Instanz1 ExeA@machine1(Parameter1 = 5); subcomponent Instanz2 ExeA@machine2; bind Instanz1.Port1 -- Input bind Instanz1.Port2 -Instanz2.Port1; bind Instanz2.Port2 -Output; Regis Runtime Umgebung } System Input Instanz1 von Executable Instanz2 von Executable Port1 Port1 Port2 machine1 Output Port2 machine1 Zusammenfassung • IBM Visual Age System = Java Programm (+ Virtual Machine) • MS Visual Basic System = P-Code + Komponenten + VB Runtime • Unix Shell Skripte System = Skript + Executables (+ Shell) • Regis (DARWIN) System = DARWIN file + Executables + Regis Runtime Zusammenfassung 2: Unterschiede • Wie wird komponiert? (Interface: textuell, visuell, gemischt) • Anzahl der Sprachen zur Beschreibung des ausgelieferten Systems? (nur Java, Kompositionssprache + Programmiersprache, Programmiersprache1 + Programmiersprache2) • Ist das resultierende System verteilt oder lokal? • Wann werden Änderungen in der Komposition wirksam? (nach dem Neustart, nach Compilieren+Neustart, sofort) Dynamische Anpaßbarkeit der Komposition einer Anwendung • Integration von Kompositionsumgebung + Laufzeitumgebung EVOLVE