34
Знакомство с аспектно- ориентированным программированием Михаил Крестьянинов, Новотелеком

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

Embed Size (px)

Citation preview

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

Знакомство с аспектно-ориентированнымпрограммированием

Михаил Крестьянинов,Новотелеком

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

Эволюция парадигм

2

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

Сферический быдлокод в вакууме

public class WebService {

public BookDTO getBook(Integer bookId) {

BookDTO book = bookDAO.readBook(bookId);

return book; }

}

3

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

Сферический быдлокод:Логирование

public BookDTO getBook(Integer bookId) {

LOG.debug("Call method getBook with id " + bookId);

BookDTO book = bookDAO.readBook(bookId);

LOG.debug("Book info is: " + book.toString()); return book;}

4

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

Сферический быдлокод:Обработка исключенийpublic BookDTO getBook(Integer bookId) throws ServiceException {

LOG.debug("Call method getBook with id " + bookId); BookDTO book = null; try { BookDTO book = bookDAO.readBook(bookId); } catch(SQLException e) { throw new ServiceException(e); }

LOG.debug("Book info is: " + book.toString()); return book;}

5

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

Сферический быдлокод:Авторизацияpublic BookDTO getBook(Integer bookId)

throws ServiceException, AuthException {

if (!SecurityContext.getUser().hasRight("GetBook")) throw new AuthException("Permission Denied");

LOG.debug("Call method getBook with id " + bookId); BookDTO book = null; try { BookDTO book = bookDAO.readBook(bookId); } catch(SQLException e) { throw new ServiceException(e); }

LOG.debug("Book info is: " + book.toString()); return book;}

6

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

Сферический быдлокод:Кеширование

public BookDTO getBook(Integer bookId) throws ServiceException, AuthException {

if (!SecurityContext.getUser().hasRight("GetBook")) throw new AuthException("Permission Denied");

LOG.debug("Call method getBook with id " + bookId); BookDTO book = null; String cacheKey = "getBook:" + bookId; try {

if (cache.contains(cacheKey)) { book = (BookDTO) cache.get(cacheKey); } else { BookDTO book = bookDAO.readBook(bookId);

cache.put(cacheKey, book); } } catch(SQLException e) { throw new ServiceException(e); }

LOG.debug("Book info is: " + book.toString()); return book;}

7

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

Сферический быдлокод:Идеальный вариант

8

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

Сквозная функциональность

• логирование;

• профилирование;

• обработка транзакций;

• обработка ошибок;

• авторизация и проверка прав;

• кеширование;

• контрактное программирование.

9

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

Что такое АОП

Основной задачей аспектно-ориентированного программирования (АОП) является модуляризация сквозной функциональности, выделение её в аспекты.

10

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

AspectJ: Пример аспекта@Aspectpublic class WebServiceLogger { private final static Logger LOG = Logger.getLogger(WebServiceLogger.class);

@Pointcut("execution(* example.WebService.*(..)) && @annotation(example.Loggable)") public void loggableMethod() { }

@Around(“loggableMethod()") public Object logWebServiceCall(ProceedingJoinPoint thisJoinPoint) { 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); return result; }}

11

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

Термины АОП

• аспект (aspect);

• совет (advice);

• точка соединения (join point);

• срез (pointcut);

• внедрение (introduction).

12

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

AspectJ: точки соединения

Создание объекта

• initialization(MyClass || MyOtherClass);

• staticinitialization(MyClass+ && !MyClass);

Вызов метода, обращение к свойству

• execution(static * com.xyz..*.*(..));

• call(void MyInterface.*(..));

• handler(ArrayOutOfBoundsException);

• get/set(static int MyClass.x);

13

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

AspectJ: точки соединения

Вспомагательные

• this/target(MyClass)

• args(Integer)

• within/withincode(MyClass)

• cflow/cflowbelow(call(void MyClass.test()))

• @annotation(MyAnnotation)

14

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

AspectJ: советы

• before – запуск совета до выполнения точки соединения;

• after returning — запуск совета после нормального выполнения точки соединения;

• after throwing — запуск совета после выброса исключения в процессе выполнения точки соединения;

• after — запуск совета после любого варианта выполнения точки соединения;

• around – запуск совета вместо выполнения точки соединения (выполнение точки соединения может быть вызвано внутри совета).

15

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

AspectJ: вторая попытка

@Aspectpublic class WebServiceLogger { private final static Logger LOG = Logger.getLogger(WebServiceLogger.class);

@Pointcut("execution(* example.WebService.*(..)) && @annotation(example.Loggable)") public void loggableMethod() { }

@Around(“loggableMethod()") public Object logWebServiceCall(ProceedingJoinPoint thisJoinPoint) { 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); return result; }}

16

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

PostSharpАспект обработки исключений:

public class ExceptionDialogAttribute : OnExceptionAspect{ public override void OnException(MethodExecutionEventArgs e) { string message = e.Exception.Message; Window window = Window.GetWindow((DependencyObject)eventArgs.Instance);

MessageBox.Show(window, message, "Exception");

eventArgs.FlowBehavior = FlowBehavior.Continue; }}

17

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

PostSharp

Применение аспекта через настройки сборки:

[assembly: ExceptionDialog ( AttributeTargetTypes="Example.WorkflowService.*", AttributeTargetMemberAttributes = AttributeTargetElements.Public )]

Применение аспекта с помощью атрибута:

[ExceptionDialog]public BookDTO GetBook(Integer bookId)

18

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

PostSharp

Aспекты:

• OnMethodBoundary/OnMethodInvocation – обращение к методу (начало, конец, выход, выход с исключением);

• OnFieldAccess – обращение к свойству;

• OnException – обработка исключения;

• Composition – внедрение кода.

19

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

Как это работает?

20

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

Как это работает?

• Изменение байт-кода:

21

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

Как это работает?

• Автоматическое создание proxy-объектов:

22

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

От теории к практике

23

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

От теории к практике

24

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

От теории к практике

• Отталкивает необходимость использования дополнительных компиляторов;

• Смущает отсутствие широкой известности и большого сообщества.

26

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

Spring AOP

• написан на чистом Java/C#;

• не использует сторонних компиляторов;

• урезанная поддержка АОП;

• интеграция с AspectJ;

• поддержка аннотаций @AspectJ;

• часть Spring Framework.

26

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

Spring AOP: Примеры

Ограничение прав доступа:

<sec:protect-pointcut expression="execution(* ru.novotelecom.xxx.Subscription.*(..))" access="ROLE_SUBSCRIPTION_MANAGER" />

Или

@Aspectpublic class SecurityManager {

@Before("execution(* ru.novotelecom.xxx.Subscription.*(..))") public void doAccessCheck() {… }}

27

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

Spring AOP: ПримерыОбработка исключений:

@Aspectpublic class WebServiceException {

@Pointcut("execution(* example.WebService.*(..)) && @annotation(example.Loggable)") public void loggableMethod() { }

@Around(“loggableMethod()") public Object logWebServiceCall(ProceedingJoinPoint thisJoinPoint) throws ServiceException { Object result = null;

try { result = thisJoinPoint.proceed(); } catch (Exception e) { throw new ServiceException(e); }

return result; }}

28

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

Альтернативы

Шаблоны проектирования:

• Proxy

• Decorator

• Chain of responsibility

Конструкции языка:

• Аннотации / Атрибуты

29

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

АОП в других языках

• python (Aspyct)

• perl (Aspect CPAN)

• ruby (AspectR)

• c++ (AspectC++)

• php (Seasar, GAP)

• javascript (Ajaxpect)

30

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

Резюме

• Основная цель АОП — выноса «общей» (сквозной) функциональности «за скобки» (модуляризация сквозной функциональности);

• Для Java AOP доступен через проект AspectJ, для .NET – через PostSharp;

• Наиболее простая и проверенная реализация AOP – Spring AOP.

31

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

От теории к практике

32

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

Ссылки

• http://habrahabr.ru/blogs/programming/114649/

• http://www.eclipse.org/aspectj/

• http://www.sharpcrafters.com/postsharp

• https://www.ibm.com/developerworks/ru/library/j-aopwork15/

• http://en.wikipedia.org/wiki/Aspect-oriented_programming

33

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

Вопросы?

Михаил Крестьянинов,Новотелеком

[email protected]