Знакомство с аспектно-ориентированнымпрограммированиемМихаил Крестьянинов,Новотелеком
Эволюцияпарадигм2
Сферический быдлокод в вакуумеpublic class WebService {    publicBookDTOgetBook(IntegerbookId) {BookDTObook = bookDAO.readBook(bookId);        returnbook;    }}3
Сферический быдлокод:ЛогированиеpublicBookDTOgetBook(IntegerbookId) {LOG.debug("Call method getBook with id "        + bookId);BookDTObook = bookDAO.readBook(bookId);LOG.debug("Book info is: "        + book.toString());     returnbook;}4
Сферический быдлокод:ОбработкаисключенийpublicBookDTOgetBook(IntegerbookId)    throws ServiceException {LOG.debug("Call method getBook with id " + bookId);BookDTObook = null;    try {BookDTObook = bookDAO.readBook(bookId);    } catch(SQLException e) {        throw new ServiceException(e);    }LOG.debug("Book info is: " + book.toString());    returnbook;}5
Сферический быдлокод:АвторизацияpublicBookDTOgetBook(IntegerbookId)    throws ServiceException, AuthException {    if (!SecurityContext.getUser().hasRight("GetBook"))        throw new AuthException("Permission Denied");LOG.debug("Call method getBook with id " + bookId);BookDTObook = null;    try{BookDTObook = bookDAO.readBook(bookId);    } catch(SQLException e) {        throw newServiceException(e);    }LOG.debug("Book info is: " + book.toString());    returnbook;}6
Сферический быдлокод:КешированиеpublicBookDTOgetBook(IntegerbookId)    throws ServiceException, AuthException {    if(!SecurityContext.getUser().hasRight("GetBook"))        throw newAuthException("Permission Denied");LOG.debug("Call method getBook with id " + bookId);BookDTObook = null;    String cacheKey = "getBook:" + bookId;    try{    if (cache.contains(cacheKey)) {        book = (BookDTO) cache.get(cacheKey);    } else {BookDTObook = bookDAO.readBook(bookId);cache.put(cacheKey, book);    }    } catch(SQLException e) {        throw newServiceException(e);    }LOG.debug("Book info is: " + book.toString());    returnbook;}7
Сферический быдлокод:Идеальныйвариант8
Сквознаяфункциональностьлогирование;
профилирование;
обработкатранзакций;
обработкаошибок;
авторизация и проверкаправ;
кеширование;
контрактноепрограммирование.9
Чтотакое АОПОсновнойзадачейаспектно-ориентированногопрограммирования (АОП) является модуляризация сквознойфункциональности, выделениееё в аспекты.10
AspectJ: Примераспекта@Aspectpublic classWebServiceLogger {    privatefinal static Logger LOG =Logger.getLogger(WebServiceLogger.class);    @Pointcut("execution(* example.WebService.*(..))         && @annotation(example.Loggable)")    public voidloggableMethod() { }    @Around(“loggableMethod()")    public ObjectlogWebServiceCall(ProceedingJoinPointthisJoinPoint) {        String methodName = thisJoinPoint.getSignature().getName();        Object[] methodArgs = thisJoinPoint.getArgs();LOG.debug("Call method " + methodName + " with args " + methodArgs);        Object result = thisJoinPoint.proceed();LOG.debug("Method " + methodName + " returns " + result);        returnresult;    }}11
Термины АОПаспект (aspect);
совет (advice);
точкасоединения (join point);
срез (pointcut);
внедрение (introduction).12
AspectJ: точкисоединенияСозданиеобъектаinitialization(MyClass || MyOtherClass);
staticinitialization(MyClass+ && !MyClass);Вызовметода, обращение к свойствуexecution(static * com.xyz..*.*(..));
call(void MyInterface.*(..));
handler(ArrayOutOfBoundsException);
get/set(static intMyClass.x);13
AspectJ: точкисоединенияВспомагательныеthis/target(MyClass)
args(Integer)
within/withincode(MyClass)
cflow/cflowbelow(call(void MyClass.test()))
@annotation(MyAnnotation)14
AspectJ: советыbefore – запусксоветадовыполненияточкисоединения;
after returning — запусксоветапосленормальноговыполненияточкисоединения;

CodeFest 2011. Крестьянинов М. — Обзор аспектно-ориентированного программирования