290 likes | 543 Views
Programowanie aspektowe. Programowanie aspektowe. Metoda programowania mająca na celu modularyzację kodu i likwidację nakładających się problemów przekrojowych. AOP - przykłady zastosowania. logowanie, profilowanie, cacheowanie autoryzacja i uwierzytelnianie
E N D
Programowanie aspektowe • Metoda programowania mająca na celu modularyzację kodu i likwidację nakładających się problemów przekrojowych Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
AOP - przykłady zastosowania • logowanie, profilowanie, cacheowanie • autoryzacja i uwierzytelnianie • zarządzanie błędami, transakcje • sprawdzanie poprawności danych • rejestracja zmian Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
AOP – podstawowe pojęcia (I) • Aspekt - wydzielona funkcjonalnie cześć programu, realizująca konkretne zadanie i koncentrująca sie tylko na problemie, którego dotyczy (np. logowanie, monitorowanie aplikacji, zarządzanie transakcjami). • Podstawowe pojęcia AOP • aspekt (aspect): nazwany problem przekrojowy, inaczej to zbiory rad i punktów cięć/złączeń • rada (advice): dodatkowe zachowanie/czynność które zostaje zaninicjowane w punkcie złączenia, • punkt złączenia (join point): miejsce w strukturze wykonywania się aplikacji w którym powinna zostać zastosowana rada. Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
AOP – podstawowe pojęcia (II) Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
Spring AOP framework • Rodzaje rad: • around advice: wykonuje się przed i po punkcie styku, ma możliwość przerwania przepływu kontroli programu przez zwrócenie własnej wartości lub wyjątku, • before advice: wykonuje się przed punktem styku, nie może zablokować przepływu kontroli programu, • throws advice: wykonuje się w momencie zgłoszenia wyjątku, • after returning advice: wykonuje się po poprawnym wykonaniu. Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
Around Advice • Zgodność z AOP Alliance. • Przechwycenie wywołania metody. • Może zastąpić Before, After oraz Throws Advice. • Możliwość zatrzymania wywołania metody. • Możliwość zwrócenia innego obiektu niż przechwycona metoda. Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
Before Advice • Wplatany przed wywołaniem metody. • Zatrzymanie wykonania metody tylko poprzez wyrzucenie wyjątku. • Ograniczone możliwości modyfikacji parametrów wywołania metody. Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
After Advice • Wplatany przy udanym powrocie z metody. • Ograniczone możliwości zmiany wyniku zwróconego przez metodę. Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
Throws Advice • Wplatany w przypadku wyrzucenia wyjątku przez metodę. • Możliwość zaimplementowania różnych metod dla różnych wyjątków w jednej klasie. • Brak możliwości „zatrzymania” wyjątku. Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
Implementacja (I) public class TracingBeforeAdvice implements MethodBeforeAdvice { public void before(Method m, Object[] args, Object target) throwsThrowable { System.out.println("Before method : "+ m.getName() ); } } Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
Implementacja (II) public class TracingAfterAdvice implements AfterReturningAdvice { public void afterReturning(Object object, Method m, Object[] args, Object target) throwsThrowable { System.out.println("After method : "+ m.getName()); } } Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
Konfiguracja (I) <bean id=”proxybean" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target"> <ref local="beanTarget" /> </property> <property name="interceptorNames"> <list> <value>theTracingBeforeAdvisor</value> <value>theTracingAfterAdvisor</value> </list> </property> </bean> Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
Konfiguracja (II) <bean id="theTracingBeforeAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="advice"> <ref local="theTracingBeforeAdvice" /> </property> <property name="pattern"> <value>.*</value> </property> </bean> <bean id="theTracingBeforeAdvice" class="TracingBeforeAdvice" /> Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
Przykład public class TimeInterceptor implements MethodInterceptor { public Object invoke(MethodInvocation method) throwsThrowable { long start = System.currentTimeMillis(); try { Object result= method.proceed(); return result; } finally { long end= System.currentTimeMillis(); long timeMs= end-start; System.out.println("Method: " + method.toString() + " took: " + timeMs+"ms."); }}} Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
@Aspect @Aspect public class MyAspect { ..... } Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
@Pointcut @Pointcut("execution(* transfer(..))") private void my() {} • execution • target • args Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
execution • execution(public * *(..)) • execution(* set*(..)) • execution(* com.xyz.service.*.*(..)) • execution(* com.xyz.service..*.*(..)) • execution (public * dao.commons..*.update(..))) Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
Stosowane adnotacje • @Before() • @AfterReturning(Object) • @AfterThrowing(Exception) • @After() • @Around(ProceedingJoinPoint) Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
@Around @Around("execution(* dao..*.get(..))") public Object applySecurity(ProceedingJoinPoint joinpoint) throws Throwable { logger.debug("Applying Security"); Object obj = joinpoint.proceed(); ..... return obj; } } Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
Przykład @Aspect public class DataUpdateInterceptor { @After("(execution(public *dao.commons..*.update(..)) || " + "execution(public *dao.commons..*.save(..)) ) && " + " target(dao.GenericDAO)") public void updateDataAspect(JoinPoint jp) { logger.debug("nastapila zmiana w danych"); } } Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
Konfiguracja <aop:aspectj-autoproxy/> <bean class=”common.DataUpdateInterceptor "> </bean> Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
@Auditable @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Auditable { } Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
@NonAuditableField @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface NonAuditableField { } Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
Klasa domenowa @Auditable @Entity public class Uzytkownik { .... @NonAuditableField @Column(nullable = true, length = 64) private String haslo; .... Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
AudytInterceptor (I) @Transactional(propagation = Propagation.MANDATORY) public class AudytInterceptor extends EmptyInterceptor { private AuditLoggerService auditLoggerService; ... Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
AudytInterceptor (II) @Override public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { if (entity.getClass().isAnnotationPresent(Auditable.class)) { auditLoggerService.logSave(entity, id, state, propertyNames, types); } return super.onSave(entity, id, state, propertyNames, types); } Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
AudytInterceptor (III) @Override public void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { if (entity.getClass().isAnnotationPresent(Auditable.class)) { auditLoggerService.logDelete(entity, id); } super.onDelete(entity, id, state, propertyNames, types); } } Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego
Interceptor (III) <bean id="audytInterceptor" class="commons.interceptor.AudytInterceptor"> <property name="auditLoggerService" ref="auditLoggerService"></property> </bean> Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego