Zusammenfassung In diesem Artikel wird mit Ihnen besprochen, wie Sie die Kraft von Annotationen und Aspekten kombinieren können, um Unternehmen mit EJB 3.0 kompatible Weise deklarative Dienste bereitzustellen und gleichzeitig die Unabhängigkeit von Containern zu bieten.
1. Einführung
In unserem gemeinsamen Streben nach Möglichkeiten zur weiteren Verbesserung der Produktionsleistung der Softwareentwicklung wenden wir uns als Mitglieder der Java -Community J2EE an J2EE, um anspruchsvollere technische Probleme in der Unternehmensentwicklung wie verteiltes Transaktionsmanagement, Gleichzeitigkeit und Distributionslösungen für Objekte zu liefern. Die Leitideologie dahinter - diese komplexen Unternehmensdienste können von Anwendungsserveranbietern implementiert und von kommerziellen Entwicklern ausgewogen - ist in der Tat eine gute Idee. J2EE, insbesondere EJB, hat erfolgreich eine Plattform zur Verfügung gestellt, auf der Unternehmen Java -Anwendungen erstellt werden.
Ein Teil dieses Erfolgs ist auf die Fähigkeit zurückzuführen, deklarative Programme durchzuführen - eine Möglichkeit, ein Programm zu entwickeln -, in dem Sie Infrastrukturdienste deklarieren können, anstatt explizit mit Geschäftslogik zu kodieren, damit der Code überall verbreitet wird. EJB hat den Wert dieses Programmieransatzes nachgewiesen - indem es mit einem Veröffentlichungsdeskriptor deklariert und von einem Container behandelt werden kann.
In den letzten Jahren haben immer mehr Entwickler erkannt, dass EJB sich viele neue Herausforderungen in der Produktivität eines Teams mit sich bringt. Jeder EJB muss von mehreren Schnittstellen begleitet werden, mit einer Beschreibung des Veröffentlichungsdeskriptors, auf die über JNDI usw. zugegriffen wird. Unit-Tests auf EJB außerhalb des Containers haben auch zusätzliche Schwierigkeiten.
Bitte beachten Sie, dass Sie die folgenden Tools haben müssen, um diesen Artikel zu lesen:
· Java 2 SDK 1.5
· Maven 2.0 Beta 2
Das Ziel von EJB 3.0 ist es, die Unternehmensentwicklung in den folgenden Aspekten zu erleichtern:
· Implementieren Sie deklarative Anfragen für Unternehmensdienste durch Einführung von Metadatenanmerkungen
· Implementieren Sie die Abhängigkeits-/Ressourceninjektion über Annotation
· Implementieren Sie die Entkopplung von Unternehmensbohnen und EJB -spezifischen Schnittstellen
· Vereinfachung des kontinuierlichen Speichers durch leichte Objektrelationskartierung
Dies ist wie eine Frühlingsbrise für EJB -Entwickler - sie haben hart daran gearbeitet, EJB zu entwickeln, zu testen und aufrechtzuerhalten. Es ist jetzt einfach, eine Unternehmensbean mit EJB 3.0 zu schreiben, genau wie das Erstellen eines Pojo (traditionelles Java -Objekt) mit spezifischen Annotationen, um es als EJB zu markieren und Enterprise -Dienste anzufordern. Hier ist ein Beispiel von EJB in EJB 3.0 Public Draft:
@Stateful
Kartellklassen im öffentlichen Klassen implementiert ShoppingCart
{
privater Schwimmer total;
private Vektorproduktcodes;
public int someshoppingMethod () {...};
...
}
In der EJB 3.0-Erklärung heißt es im Wesentlichen, dass das, was Entwickler brauchen, kein Schwergewicht ist, "eine Release erfüllt alles", sondern eine leichte und einfach zu verwendende Lösung-und bietet Entwicklern eine bestimmte Reihe von Unternehmensdiensten. Zu diesem Zweck besteht eine der wichtigsten Methoden von EJB 3.0 darin, Enterprise -Bohnen und EJB -APIs zu entkoppeln. Und diese Lösung bringt auch interessante Derivate - EJB kann jetzt nicht nur in verschiedenen EJB -Containern, sondern auch innerhalb eines Anwendungsrahmens ausgeführt werden. Diese Frameworks müssen in der Lage sein, EJB 3.0 (JSR 220) und normale Annotation zur Deklaration von Unternehmensdiensten (JSR 250) zu erkennen. .
Dieser Artikel enthält keine eingehende Untersuchung der deklarativen Programmierung, EJBs, Aspekte oder Anmerkungen. Analysieren Sie stattdessen einfach die Wechselbeziehungen zwischen diesen Technologien und diskutieren Sie, wie Sie sie auf eine neue Weise kombinieren können, um die Anwendungsentwicklung zu vereinfachen.
In diesem Artikel lernen Sie, wie Sie eine EJB 3.0 -kompatible Bean schreiben und mehrere einfache Aspekte erstellen, um das Deklarative Transaktionsmanagement, die Sicherheit und die Ressourceninjektion zu gestalten. Ich hoffe, Sie können von dieser Übung profitieren:
· Drei praktische Anwendungen beim Lernen (Abhängigkeitsinjektion, Sicherheit und Transaktion).
· Mit EJB 3.0 und den Ideen dahinter vertraut.
Erkennen Sie, wie die Entkopplung von EJB aus bestimmten APIs implementiert wird, damit EJB 3.0 -kompatible Dienste nur von EJB im Umfang im Leichter implementiert werden können.
2. Beispiel für Anwendungsflug-Flucht
Während der gesamten Diskussion erfahren Sie eine Implementierung eines Flugbestellsystems, das Aspekte und Anmerkungen verwendet, um Abhängigkeitsinjektion, Sicherheit und Transaktionsmanagement zu implementieren. Die App führt nur zwei Funktionen aus: Sie ermöglicht es Benutzern, nach Flügen zu suchen (Abbildung 1) und dann eine Reise bestellen (Abbildung 2). Beide Vorgänge werden sicher verarbeitet, damit nur identifizierte Benutzer sie ausführen können. Da der Betrieb "Order Travel" zwei Flüge (Out- und Rückkehrflüge) bestellt, muss der Betrieb als Transaktionsanlage erstellt werden - beispielsweise werden beide Bestellungen als Arbeitseinheit erfolgreich sein oder fehlschlagen.
Abbildung 1. Flugabfrage: Erstens suchen Benutzer nach Flügen, die ihren angegebenen Kriterien erfüllen.
Abbildung 2. Flugbestellung: Als nächstes bestellt der Benutzer einen ausgehenden Flug und einen Rückflug. Beide Bestellungen sind entweder erfolgreich oder scheitern.
Diese einfache Webanwendung enthält mehrere Servlets, ein Service -Erscheinungsbild und eine DAO -Ebene (siehe Abbildung 3).
Übergreifende Bedenken wie Ressourcenkonfiguration, Sicherheits- und Transaktionsmanagement werden durch Aspekte (implementiert mit Aspekt 1 1,5 m3) zur Umsetzung des in Java 5-Anmerkungen deklarierten Injektionsverhaltens bereitgestellt.
Abbildung 3.. Flugbestellsystemarchitektur: Dieses Flugbestellsystem besteht aus drei Hauptkomponenten - sie verbinden sich zusammen, um Benutzeranforderungen zu erfüllen. 3.. Ressourceninjektion
Mit dem Entwurf der EJB 3.0 -Entwürfe können die Ressourcen über die @Resource -Annotation deklariert werden (diese Entscheidung ist im Entwurf der ordentlichen Annotationserklärung definiert) und in Ihrem EJB vom Container injiziert. Die Abhängigkeitsinjektion ist eine Technik - Mit dieser Technik kann eine Entität außerhalb eines Objekts und nicht eine Entität, die explizit für dieses Objekt erstellt wurde, die Abhängigkeit eines Objekts liefern (injizieren). Es wird manchmal als Hollywood -Prinzip beschrieben - das scherzt wie "Rufen Sie uns nicht an, wir rufen Sie an."
Nehmen Sie die TravelagencyServiceImpl -Klasse als Beispiel - Um einige Daten kontinuierlich zu speichern, muss diese Klasse eine Implementierung der IFILLDDAO -Schnittstelle finden. Traditionell wird dies über eine Fabrik, einen Singleton, einen Service -Locator oder eine andere individuelle Lösung erreicht. Unter ihnen sieht eine mögliche Lösung so aus:
öffentliche Klasse TravelagencyServiceImpl implementiert ittravelAGencyService
{
öffentlich Iflightdao Flightdao;
öffentliche ReisebereicheServiceImpl ()
{flightDao = flugdaofactory.getInstance (). GetflightDao ();
Public Void BookTrip (lange Outboundflightid, Long Return -FlightId, int Sitze)
Wirft InvalidSeatsexception aus
{
Reserveneats (OutboundFlightId, Sitze);
Reserveneats (returnFlightId, Sitze);
}
}
Sie haben gesehen, dass diese Implementierung das Erstellen einer bestimmten Werksklasse beinhaltet - sie wird wahrscheinlich Konfigurationsinformationen gelesen, die irgendwo gespeichert sind, um zu verstehen, wie die Implementierung zum Erstellen von IFILLDDAO erstellt werden soll. Wenn der Dienst nicht explizit seine vom Container eingerichteten Abhängigkeiten erstellt, werden Konfigurationsdetails und Objekterstellung in den Container verfolgt. Auf diese Weise können Komponenten in einer Anwendung leicht miteinander verbunden sein - mit unterschiedlichen Konfigurationen und beseitigt viele altmodische Singleton- und Fabrikcode.
Eine Implementierung der Klasse - die auf einer Implementierung von IFILLDDAO mit JSR 250 -Ressourcenannotation beruht, kann wie folgt aussehen:
öffentliche Klasse TravelagencyServiceImpl implementiert ittravelAGencyService
{
@resource (name = "flightdao")
öffentlich Iflightdao Flightdao;
Public Void BookTrip (lange Outboundflightid, Long Return -FlightId, int Sitze)
Wirft InvalidSeatsexception aus
{
Reserveneats (OutboundFlightId, Sitze);
Reserveneats (returnFlightId, Sitze);
}
}
In diesem Fall bietet der Container die korrekte Implementierung einer Ressource mit dem Namen "FlightDao" in die Serviceklasse. Aber was ist, wenn Sie die Ressourceninjektion jetzt nutzen möchten, anstatt auf die EJB 3.0 -Version zu warten? OK, Sie können einen leichten Behälter nehmen - es kann Abhängigkeitsinjektionen wie Frühlings- oder Pico -Behälter bereitstellen. Ich verstehe jedoch nicht, dass es einen leichten Container gibt - es ist in der Lage, JSR 250 -Ressourcenanmerkungen zu verwenden, um die Einspritzanforderungen anzugeben (obwohl ich mich sehr auf einige in dieser Hinsicht freue).
Eine Lösung besteht darin, Aspekte zur Implementierung der Abhängigkeitsinjektion zu verwenden. Wenn Sie die @Resource -Annotation dafür verwenden, stimmt Ihre Implementierung mit dem Way EJB 3.0 überein und ist mit der EJB 3.0 -Implementierung kompatibel - und das ist nicht sehr schwierig zu implementieren. Die folgende Liste zeigt einen Aspekt, der mit Aspektj erstellt wurde - sie injiziert Felder, die mit @Resource Annotation kommentiert sind:
@Aspekt
öffentliche Klasseneinspritzung
{
private DependentyManager Manager = new DependentyManager ();
@before ("Get (@resource * *. *)")
öffentliche void vorfield Accesses (joinpoint thisjoinpoint)
wirft IllegalArgumentException, IllegalAccessException aus
{
fieldSInnature signature = (fieldSInnature) ThisjoInpoint.getSignature ();
RessourceninjectAntation = Signature.getField (). getAnnotation (Ressource.Class);
Object Dependecy = Manager.Resolve Dependent (Signature.getFieldType (), InjectAnnotation.Name ());
Signature.getField (). set (thisjoinpoint.GetThis (), Abhängigkeit);
}
}
All dieser einfache Aspekt ist die Abfrage der Implementierungsklasse aus einer Eigenschaftsdatei (diese Logik wird im Abhängigkeitsmanager -Objekt eingekapselt) und in die mit @Resource -Annotation kommentierten Felder injizieren, bevor Sie auf das Feld zugreifen. Offensichtlich ist diese Implementierung nicht vollständig, zeigt jedoch, wie Sie eine Ressourceninjektion auf eine JSR 250-kompatible Weise ohne EJB bereitstellen können.
4. Sicherheit
Zusätzlich zur Ressourceninjektion bieten JSR 250 und EJB 3.0 auch eine Metadatenvertretung über Annotation. Das Javax.annotation.Security -Paket definiert fünf Annotationen - Runas, Rollen, Genehmigungen, Denyall und RollesReference -, die alle auf Methoden zur Definition der Sicherheitsanforderungen angewendet werden können. Wenn Sie beispielsweise erklären möchten, dass die oben aufgeführte Buchflight -Methode nur von Anrufern mit der Rolle "Benutzer" ausgeführt werden kann, können Sie diese Methode mit den folgenden Sicherheitsbeschränkungen kommentieren:
öffentliche Klasse TravelagencyServiceImpl implementiert ittravelAGencyService
{
@resource (name = "flightdao")
öffentlich Iflightdao Flightdao;
@roleslowed ("Benutzer")
Public Void BookTrip (lange Outboundflightid, Long Return -FlightId, int Sitze)
Wirft InvalidSeatsexception aus
{
Reserveneats (OutboundFlightId, Sitze);
Reserveneats (returnFlightId, Sitze);
}
}
In dieser Annotation wird angegeben, dass der Container dafür verantwortlich ist, dass nur der Anrufer der angegebenen Rolle diese Methode ausführen kann. Jetzt werde ich einen weiteren einfachen Aspekt zeigen - es wird die Sicherheitsbeschränkungen für die Anwendung weiter stärken:
@Aspekt
Öffentliche Klasse Securityaspect
{
@around ("Ausführung (@javax.annotation.security.roleslowed * *. *(..))")
öffentliches Objekt rund umgesehene Methoden (ProseingJoInpoint ThisjoInpoint)
Wirft Throwable
{
boolean callerAuthorized = false;
ROLLELAUMED ROLLELALED = ROLLOLADEDFORJOINPOPPE (thisjoinpoint);
für (String -Rolle: ROLLELALED.VALUE ())
{
if (callerinrol (Rolle))
{callerAuthorized = true;
}
if (callerauthorisiert)
{return thisjoinpoint.ProceTe ();
anders
{
Neue RunTimeException werfen ("Anrufer, der nicht zur Ausführung der festgelegten Funktion autorisiert ist");
}
}
Private Rolllowed Rollesallowed ForjoInpoint (Proceedingjoinpoint ThisjoInpoint)
{
Methodensignature methodesignature = (methodeInt) thoinpoint.getSignature ();
Methode targetMethod = methodicInTature.getMethod ();
return targetMethod.getAnnotation (rolesallowed.class);
}
private booleschen Anruferinrole (String -Rolle)
{...}
}
Dieser Aspekt beinhaltet die Ausführung aller Methoden - durch Überprüfung, ob der Anrufer eine der in der Annotation angegebenen Rollen ist, kommentieren Sie die @roleslowed Annotation und stellen Sie sicher, dass der Anrufer autorisiert ist, die Methode aufzurufen. Natürlich können Sie auch jeden Algorithmus verwenden, den Sie den Benutzer autorisieren und seine Rolle wie JAAS oder eine maßgeschneiderte Lösung abrufen möchten. In diesem Beispielprogramm habe ich aus Gründen der Einschätzung den Stellvertreter in den Servlet -Container gewählt.
V. Angelegenheiten
Transaktionen werden zu einem wichtigen Bestandteil der Unternehmensentwicklung - da sie die Datenintegration in einer gleichzeitigen Umgebung erleichtern. Transaktionen können aus hoher Ebene durch mehrere oder vollständige oder unvollständige Operationen sicherstellen.
Im Gegensatz zu den Anmerkungen zur Ressourceninjektion und -sicherheit sind die Anmerkungen für Transaktionen spezifisch für EJB 3.0 und sind in den normalen Annotationen der JSR 250 nicht definiert. EJB 3.0 definiert zwei mit Transaktionen verbundene Anmerkungen: Transaktionsmanagement und Transaktionattribute. Die Transaktionsmanager -Annotation gibt an, ob die Transaktion vom Container oder von der Bohne verwaltet wird. In EJB 3 wird die vom Container verwaltete Transaktion verwendet, wenn diese Annotation nicht angegeben ist. Die Transaktions -Attribut -Annotation wird verwendet, um die Transaktionsausbreitungsstufe der Methode anzugeben. Gültige Werte - einschließlich obligatorischer, erforderlich, erforderlich, erforderlich, unterstützt, nicht unterstützt und nie unterstützt - werden verwendet, um festzustellen, ob eine vorhandene Transaktion erforderlich ist oder eine neue Transaktion eingeleitet wird, usw.
Da der Buchflugbetrieb aus zwei Schritten besteht, die einen ausgehenden Flug und einen Rückflug bestellen, indem Sie ihn in eine Transaktion verpacken, können Sie die Konsistenz des Betriebs sicherstellen. Durch die Verwendung von EJB 3.0 -Transaktionsanmerkungen sieht dies so aus:
öffentliche Klasse TravelagencyServiceImpl implementiert ittravelAGencyService
{
@resource (name = "flightdao")
öffentlich Iflightdao Flightdao;
@roleslowed ("Benutzer")
@TransactionAttribute (TransactionAttribUTetype.Required)
Public Void BookTrip (lange Outboundflightid, Long Return -FlightId, int Sitze)
Wirft InvalidSeatsexception aus
{
Reserveneats (OutboundFlightId, Sitze);
Reserveneats (returnFlightId, Sitze);
}
}
Und Sie können einen einfachen Aspekt anwenden, um die Transaktionsgrenzen automatisch zu definieren:
@Aspekt
öffentliche Klassentransaktion
{
@pointcut ("Ausführung (@javax.ejb.transactionAttribute * *. *(..))")
public void transactionalmethods () {}
@before ("TransactionalMethods ()")
öffentliche Leere Beforectionalmethoden ()
{HibernateUtil.BeginTransaction ();
@AfterReturning ("TransactionalMethods ()")
öffentliche void AfterReturningTransactionalMethods ()
{HibernateUtil.Committransaction ();
@Afterthring ("TransactionalMethods ()")
öffentliche Leere nach ThrowingTransactionalMethods ()
{hibernateUtil.rollbacktransaction ();
}
Diese Implementierung basiert auf der Annahme, dass Hibernate und allgegenwärtiges Thread-lokales Muster zur Verwaltung von Winterschlafsitzungen und Transaktionsobjekten verwendet werden.
6. Zusammenfassung
Durch die Verwendung der Annotationssätze von EJB 3.0 und JSR 250 hat dieser Artikel gezeigt, wie sich die Bedenken hinsichtlich der Überschneidung wie Ressourcenmanagement, Sicherheit und Transaktionen als Aspekte implementieren. Natürlich gibt es viele andere Inhalte, die wir weiter lernen müssen. Das erste, was zu lernen ist, ist die Blaupause, die durch die modularen Überschneidungsbedenken bereitgestellt werden, indem diese Beispielaspekte mit Aspektje implementiert werden. Zweitens haben wir einige neue Ideen und Konzepte hinter der jetzt entstehenden EJB 3.0 -Aussage gesehen. Schließlich sehen wir auch auf dramatische Weise die Freiheit, die unsere Geschäftsobjekte von der EJB -API entkoppeln muss. Zu diesem Zeitpunkt möchten Sie TravelagencyServiceImpl eine staatenlose Sitzung durchführen, ist eine letzte Notiz hinzuzufügen:
@Stateful
öffentliche Klasse TravelagencyServiceImpl implementiert ittravelAGencyService
{...}
Schließlich hoffe ich wirklich, dass dieser kostenlose Ansatz zur Bereitstellung von Unternehmensdiensten Wettbewerb und Innovation in der Rahmen-/Containerbranche mit sich bringt.