Înțelegeți conceptele OSGi. Încercați să urmați abordarea puzzle-ului

Publicat: 2013-04-20

OSGi a devenit foarte popular astăzi, datorită abordării modularității și capacității sale de a impune granițele logice între module. Când îl descoperim prima dată, întrebarea este de unde să începem să înțelegem cum funcționează?

Pentru a înțelege conceptele OSGi vom încerca să urmăm abordarea puzzle, ideea este să începem cu partea banală a acestei tehnologii și să căutăm alte părți legate de cele găsite. Și pentru a asambla puzzle-ul vom fi asistați de JArchitect, care va fi de ajutor pentru a detecta designul intern OSGi.

Pentru a fi mai concret analizăm cu JArchitect o aplicație care folosește tehnologia OSGi, este vorba de celebrul IDE eclipse care folosește echinocțiul containerului OSGi.

Să începem cu definiția tipică OSGi:

OSGi reduce complexitatea oferind o arhitectură modulară pentru sistemele distribuite la scară mare de astăzi, precum și pentru aplicațiile mici, încorporate. Construirea sistemelor din module interne și de pe raft reduce semnificativ complexitatea și, prin urmare, cheltuielile de dezvoltare și întreținere. Modelul de programare OSGi realizează promisiunea sistemelor bazate pe componente.

Partea trivială a OSGi este modularitatea, haideți să descoperim care sunt modulele OSGi?

Modulele OSGI se numesc pachete și, prin urmare, fiecare aplicație constă din cel puțin un pachet.
Aceste pachete sunt executate în interiorul unui container și, pe măsură ce fiecare abordare modulară în care un container gestionează modulele, întrebarea este ce contract trebuie să implementeze fiecare modul pentru a fi integrat în container?

Să luăm ca exemplu pachetul org.eclipse.equinox.jsp.jasper și să căutăm toate interfețele sale implementate, pentru asta putem executa următoarea cerere CQLinq:

eclipsa4

Este implementată interfața BundleActivator din pachetul OSGi, această interfață conține două metode de start și oprire utile pentru a personaliza pornirea și oprirea pachetului.

O altă specificitate a unui pachet este fișierul său manifest, iată o parte din fișierul manifest org.eclipse.equinox.jsp.jasper:

După cum putem observa, acest manifest conține câteva meta informații necesare containerului, cum ar fi specificarea clasei de activare a pachetului care implementează interfața BundleActivator.

Pachetul reprezintă prima noastră piesă a puzzle-ului și iată o reprezentare simplificată a unui pachet:

eclipsa7

Și doar pentru a avea o idee despre toate pachetele utilizate de eclipse, să căutăm toate clasele care implementează interfața BundleActivator.

eclipsa 2

Cine gestionează pachetul și invocă metodele BundleActivator?

Pentru a descoperi asta, să căutăm metode care invocă direct sau indirect BundleActivator.start

eclipsa6

Pachetul este activat de cadrul OSGi atunci când este lansat. Clasa cadru este începută de containerul echinocțiului. Și pentru a înțelege mai bine ce se întâmplă atunci când containerul pornește, iată câteva acțiuni executate atunci când containerul este lansat:

eclipsa31

Când containerul este lansat, inițializează cadrul OSGi, cadrul primește toate pachetele instalate, iar pentru fiecare creează o instanță a clasei BundleHost și stochează într-un depozit pachetul găsit.

Clasa BundleHost implementează interfața Bundle, care conține metode precum pornire, oprire, dezinstalare și actualizare, aceste metode sunt necesare pentru a gestiona ciclul de viață al pachetului.

Deci, a doua noastră piesă de puzzle este containerul OSGi, este lansată de Equinoxlauncher, care inițializează cadrul. Clasa cadru este responsabilă de încărcarea pachetelor și le activează.

După ce am descoperit câteva concepte de bază despre pachet și container, haideți să intrăm adânc în pachete și să descoperim cum funcționează acestea în interior.

Să luăm ca exemplu pachetul org.eclipse.equinox.http.servlet și să căutăm metode invocate de metoda de pornire a clasei sale Activator.

eclipsa 1

Acest pachet creează un serviciu și îl înregistrează în container. Un serviciu în OSGi este definit de o clasă sau o interfață Java standard. De obicei, o interfață Java este utilizată pentru a defini interfața de serviciu. Serviciul este metoda preferată pe care ar trebui să o folosească pachetele pentru a comunica între ele.

Iată câteva scenarii utile de utilizare a serviciilor:

  • Exportați funcționalitatea dintr-un pachet în alte pachete.
  • Importați funcționalități din alte pachete.
  • Înregistrați ascultătorii pentru evenimente din alte pachete.

O altă remarcă din graficul de dependență anterior este că o fabrică de servicii este utilizată pentru a crea instanța de serviciu.

A treia piesă a puzzle-ului este stratul de servicii OSGi, fiecare pachet poate utiliza sau declara unele servicii, ceea ce impune abordarea de proiectare a componentelor, iată noua reprezentare a pachetului OSGi.

eclipsa8

Dacă pachetul folosește servicii pentru a comunica cu alte pachete, cum comunică cu alte borcane?

Dacă dezvoltăm un bundle și încercăm să folosim o clasă dintr-un alt jar, putem fi surprinși că nu va funcționa așa cum era de așteptat, motivul este că ClassLoader-ul este agățat de containerul OSGi, pentru a verifica că haideți să căutăm ce metodă invocă java. lang.Thread.setContextClassLoader.

eclipsa9

Multe metode îl invocă, inclusiv EquinoxLauncher. deci de fiecare dată când pachetul încearcă să creeze o instanță de clasă, containerul OSGi va verifica dacă codul este permis să facă această acțiune sau nu și aici vine rolul pachetului importat și exportat în fișierul manifest.

Pachetul declară în mod explicit pachetul exportat și importat și, pentru a verifica acest lucru, să căutăm pachetele utilizate de pachetul org.eclipse.equinox.http.servlet și să verificăm dacă folosește numai pachetul importat.

eclipsa10

După cum putem observa toate pachetele utilizate sunt specificate în fișierul manifest, în secțiunea de import pachet.
Pachetul exportat reprezintă totuși pachetul care poate fi utilizat din alte pachete. este reprezentat de interfața ExportedPackage și putem căuta clasele container folosind această interfață.

eclipsa12

Ceea ce este interesant cu această nouă capacitate, este că pachetul va avea o graniță bine definită și ce folosește și ce expune ca servicii este foarte bine specificat.

Putem impune verificarea utilizării pachetelor importate folosind alte instrumente, de exemplu cu CQLinq putem scrie niște reguli care avertizează de fiecare dată când un proiect folosește pachete altele decât cele specificate, dar este mai bine să avem această verificare în mediul de execuție, astfel încât dezvoltatorul nu pot încălca aceste reguli.

Această capacitate de a trata pachetele importate și exportate este gestionată de stratul de module OSGi și a fost a patra piesă a puzzle-ului.

Să revenim la containerul OSGi și să descoperim ce servicii oferă?

Servicii de containere

După cum am descoperit înainte ca containerul să fie lansat de către clasa EquinoxLauncher și clasa cadru inițializează și lansează pachetele, pentru a detecta ce servicii sunt furnizate, să căutăm toate clasele utilizate în metoda de inițializare a cadrului.

eclipsa11

Unele clase au fost deja descoperite înainte, cum ar fi BundleRepository, BundleHost, PackageAdminImpl și ServiceRegistry.

Ce zici de celelalte clase:

  • StartLevelManager:
    Fiecare pachet OSGi este asociat cu un nivel de pornire care permite serverului să controleze ordinea relativă de pornire și oprire a pachetelor. Trebuie să fie active numai pachetele care au un nivel de pornire mai mic sau egal cu nivelul de pornire activ al cadrului server. De obicei, un pachet cu un nivel de pornire mai mic tinde să fie început mai devreme.
  • Administrator de securitate:
    Nivelul de securitate gestionează aspectele de securitate limitând funcționalitatea pachetului la capabilități predefinite.
  • Manager de evenimente:
    Serviciul Event Admin oferă un model de publicare-abonare pentru gestionarea evenimentelor. Este realizat conform specificațiilor serviciului OSGi Event Admin. Serviciul Event Admin trimite evenimente între editorii de evenimente și abonații de evenimente (gestionarii evenimentelor) prin interpunerea unui canal de evenimente. Editorii postează evenimente pe canal, iar canalul de evenimente definește ce gestionari trebuie notificați. Astfel, editorii și managerii nu au cunoștințe directe unul de celălalt, ceea ce simplifică gestionarea evenimentelor.

Imaginea de ansamblu a OSGi

Să asamblam toate piesele de puzzle descrise anterior și vom avea următoarea imagine OSGi:
stratificare-osgi

Această arhitectură are următoarele beneficii interesante:

  • Simplu.
  • Complexitate redusă.
  • Implementare ușoară.
  • Sigur.

Ceea ce îl face foarte atractiv și merită ocol și nu îți vei pierde timpul dacă îl studiezi în profunzime.