Za Wikipedią - Programowanie aspektowe:
Programowanie aspektowe (aspect-oriented programming, AOP) to paradygmat tworzenia programów komputerowych wspomagający separację zagadnień i rozdzielenie programu na części w jak największym stopniu niezwiązane funkcjonalnie.
Jak można było usłyszeć na ostatniej prezentacji Bartka Szkudlarka podczas XV spotkania Warszawa JUG jest wiele pojęć związanych z AOP i próba ich wytłumaczenia tu i teraz i w dodatku przeze mnie mogłaby nie oddać pełnego kolorytu AOP (niech tracą Ci, którym nie udało się przybyć na spotkanie).
Programowanie aspektowe opiera się na wyodrębnieniu zagadnień, które można określić pobocznymi w stosunku do podstawowych, biznesowych wymagań aplikacji. Takimi zagadnieniami są m.in. mechanizm bezpieczeństwa, śledzenie wykonywania programu, badanie wydajności, itp. Są to zagadnienia istotne dla pełnego działania aplikacji, jednakże ich znaczenie biznesowe jest niewielkie w stosunku do problemu, dla którego powstaje nasza aplikacja.
EJB3 dostarcza rozwiązanie o nazwie interceptor (alternatywnie metoda przechwytująca), który jest uruchamiany podczas wykonania metody biznesowej ziarna EJB - interceptor metod biznesowych (dalej zwany interceptorem biznesowym) - lub zdarzenia związanego z cyklem rozwojowym ziarna - interceptor zdarzenia rozwojowego (dalej zwany interceptorem rozwojowym).
Interceptor może być zdefiniowany w dedykowanej klasie interceptora bądź może być niebiznesową metodą ziarna EJB (dla przypomnienia: metody biznesowe są zdefiniowane przez interfejs lokalny, zdalny, endpoint oraz w przypadku ziarna sterowanego komunikatami metodzie onMessage bądź adekwatnej dla stosowanego systemu komunikatów).
I tu pojawia się kwestia związana z typem ziarna, dla których można zadeklarować interceptor biznesowy. Interceptory biznesowe są jedynie deklarowane dla ziaren sesyjnych oraz sterowanych komunikatami (kolejne miejsce w specyfikacji EJB3, gdzie można zauważyć inne traktowanie ziaren encyjnych, które w następnej specyfikacji Java EE 6 mają być ustandaryzowane przez dedykowaną specyfikację i wyjść z objęć EJB3).
Klasa interceptora musi definiować bezargumentowy konstruktor.
Metoda interceptora biznesowego posiada następującą składnię:
Wykonanie interceptora wiąże się z przekazaniem egzemplarza javax.interceptor.InvocationContext, który dostarcza informacji o środowisku uruchomieniowym metody interceptora, tj. metodzie, parametrów wejściowych i nazwie klasy ziarna, z którym jest związany. Najczęściej wykorzystywaną metodą InvocationContext jest proceed(), której uruchomienie spowoduje wykonanie kolejnego interceptora w łańcuchu interceptorów związanych z daną metodą biznesową lub samą metodę biznesową.
Object <dowolna-nazwa-metody>(InvocationContext) throws Exception
Skoro wspominałem o łańcuchu interceptorów sugeruje to możliwość deklaracji wielu interceptorów dla pojedyńczej metody biznesowej oraz prowokuje do zadania pytania o ich kolejność wykonania. Istnieje możliwość deklaracji wielu interceptorów biznesowych dla pojedyńczej metody czy klasy. Ich kolejność zostanie omówiona w kolejnej odsłonie na ich temat.
I w końcu informacja, której brakuje do popróbowania się z interceptorami biznesowymi - sposób ich deklaracji oraz miejsce ich uruchomienia. EJB3 dostarcza adnotację @AroundInvoke oraz znacznik <around-invoke>, które definiują metodę interceptora, natomiast adnotacja @Interceptors związuje metody biznesowe z klasami interceptorów. Miejsce wystąpienia adnotacji @Interceptors lub wartości znacznika <around-invoke> określają metody biznesowe związane z interceptorami, których wywołanie spowoduje wywołanie interceptora.
Dla zobrazowania materiału przedstawię przykład interceptora TracingInterceptor, którego zadaniem będzie odnotowywanie wykonania metod biznesowych.
Klasa interceptora TracingInterceptor
package pl.jaceklaskowski.ejbws.interceptors;
import java.util.logging.Logger;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
public class TracingInterceptor {
Logger logger = Logger.getLogger(TracingInterceptor.class.toString());
@AroundInvoke
public Object trace(InvocationContext ctx) throws Exception {
logger.info("Wykonuje metode biznesowa " +
ctx.getTarget().getClass().getSimpleName() +
"." + ctx.getMethod().getName());
return ctx.proceed();
}
}
oraz ziarno MojPierwszyWsEJBBean z poprzedniego wpisu, z zadeklarowanym interceptorem:
package pl.jaceklaskowski.ejbws;
import java.util.logging.Logger;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
import pl.jaceklaskowski.ejbws.interceptors.TracingInterceptor;
@Stateless
@Interceptors(TracingInterceptor.class)
public class MojPierwszyWsEJBBean implements MojPierwszyWsEJBLocal {
Logger logger = Logger.getLogger(MojPierwszyWsEJBBean.class.toString());
public void metodaBiznesowa() {
logger.info("Metoda biznesowa metodaBiznesowa wywolana poprawnie");
}
}
Uruchomienie metody metodaBiznesowa zakończy się następującym wpisem w dzienniku zdarzeń serwera aplikacyjnego Korporacyjnej Javy 5 (Java EE 5):
Wykonuje metode biznesowa MojPierwszyWsEJBBean.metodaBiznesowa
Metoda biznesowa metodaBiznesowa wywolana poprawnie
Zgadzam się z Tobą całkowicie. Ze sposobu w jaki rozumiem programowania aspektowe to technologia EJB3 (a nawet starsza EJB2, czy Hibernate) są aspektowe. Powiem więcej, używanie zwykłych adnotacji jest dla mnie także programowaniem aspektowym.
OdpowiedzUsuńProgramowania aspektowego jest dla programowania obiektowego tym, czym grafika 3D dla grafiki 2D. To nowy wymiar programowania!
Coż za trafne spostrzeżenie! Postaram się podtrzymać temat w tym tonie. Dzięki Antoni!
OdpowiedzUsuń