Санкт-Петербургский государственный университет
Опубликован: 25.07.2014 | Доступ: свободный | Студентов: 1041 / 80 | Длительность: 17:26:00
Лекция 14:

Использование аспектно-ориентированного программирования (АОП) в среде Visual Studio 2013

< Лекция 13 || Лекция 14: 1234 || Лекция 15 >

17.5. Исследования по бесшовной интеграции аспектов в облачные приложения для новой версии Azure с помощью системы Aspect.NET

Нашей группой под моим научным руководством ведутся исследования по бесшовной интеграции аспектов в облачные приложения для новой версии Microsoft Azure с помощью системы Aspect.NET.

Наша основная публикация по этой теме [37]: Григорьев Д.А., Григорьева А.В., Сафонов В.О. Бесшовная интеграция аспектов в облачные приложения на примере библиотеки Enterprise Library Integration Pack for Windows Azure и системы Aspect.NET. - Компьютерные инструменты в образовании, 2012, № 4, 3-15. Имеются еще несколько публикаций по этой теме (см. [37]). Материал из данной публикации использован в настоящей главе. Выражаю глубокую благодарность соавторам публикации за сотрудничество.

Идея предлагаемых и реализованных нами методов применения АОП для Windows Azure в следующем.

Система Aspect.NET осуществляет внедрение аспектов в целевую сборку на уровне бинарного кода MSIL, без модификации исходного кода целевого приложения.

Библиотека Enterprise Library Integration Pack for Windows Azure [36] - решение компании Microsoft для выделения "сквозной функциональности" при разработке облачных приложений (однако оно требует для этого модификации их исходного кода).

Библиотека Microsoft Enterprise Library представляет собой набор наиболее удачных образцов решения стандартных проблем и также предназначена для реализации "сквозной функциональности". В нее входят следующие функциональные блоки:

  • Caching Application Block для поддержки кэширования;
  • Cryptography Application Block для поддержки шифрования;
  • Data Access Application Block для поддержки работы с базами данных;
  • Exception Handling Application Block для реализации стратегий обработки исключений;
  • Logging Application Block для поддержки протоколирования;
  • Security Application Block для поддержки авторизации и безопасности приложений;
  • Validation Application Block для поддержки механизмов валидации данных бизнес-объектов;

В 2011 году компания Microsoft выпустила расширение Enterprise Library Integration Pack for Windows Azure, которое содержит функциональные блоки для управления производительностью (Autoscaling Application Block) и ограничения функциональности под нагрузкой (Transient Fault Handling Block). Программист может реализовать ту или иную "сквозную функциональность", если в исходном коде своего проекта вызовет методы из набора классов соответствующего функционального блока. С точки зрения АОП очевидно, что местоположение этих вызовов в исходном коде целевого приложения является совокупностью точек внедрения для действий соответствующего аспекта.

Чтобы облегчить внедрение (weaving) функциональных блоков в целевое приложение, компания Microsoft представила Unity Application Block - IOC-контейнер с ограниченной поддержкой АОП. Его механизмы позволяют во время исполнения целевой программы перехватывать вызовы заданных методов и передавать управление цепочке методов - "перехватчиков" (interceptors). Цепочка "перехватчиков" может вызываться как перед вызовом целевого метода, так и после него, имея возможность обратится к результату выполнения данного целевого метода.

Кроме того, Unity позволяет разрывать зависимости между конкретным классом и его интерфейсом. Иными словами, за создание конкретного класса отвечает специальная фабрика Unity, что дает возможность задавать правила сопоставления интерфейса и класса не в исходном коде, а в конфигурационном файле. К сожалению, говорить в этом случае о бесшовной интеграции также не приходится, так как процесс применения Unity включает в себя создание Unity-контейнера, а затем обращение к нему за конкретным классом в том месте исходного кода, где требуется получить реализацию для интерфейса.

Проект Aspect.NET, разрабатываемый коллективом авторов с 2004 г. в СПбГУ, также представляет собой аспектно-ориентированную среду разработки программ для платформы Microsoft.NET. Аспекты определяются на метаязыке Aspect.NET ML [35], либо с помощью пользовательских атрибутов в отдельных проектах MS Visual Studio, а их слияние с целевым кодом происходит на уровне сборок статически, т.е. после этапа компиляции. Вначале компилируется сборка с аспектами из которой компоновщик аспектов (weaver) извлекает правила внедрения каждого действия аспекта, содержащиеся в его пользовательском атрибуте AspectAction(). Затем компоновщик анализирует MSIL-код откомпилированной сборки целевого проекта, находит соответствующие места внедрения (сканирование) и вставляет туда действия из аспектной сборки. Операции сканирования и внедрения действий аспектов разделены, что позволяет пользователю просматривать и фильтровать точки внедрения. Весь анализ и модификация .NET - сборок производится с помощью сервисов рефлексии (reflection) и библиотеки Microsoft Phoenix, которая декомпилирует сборку и представляет ее в виде набора высокоуровневых инструкций.

Любое действие можно вставлять перед (ключевое слово %before), после (%after) или вместо (%instead) вызова заданного целевого метода. Название целевого метода задается с помощью регулярных выражений относительно его сигнатуры. Местонахождение точки внедрения внутри конкретного метода или класса можно фильтровать по ключевому слову %within.

Внутри действий можно использовать свойства базового класса Aspect, предоставляющие доступ к контексту точки внедрения, например, "this" и "target" объектам целевого метода, его метаданным (типа MethodInfo), отладочной информации, результату выполнения и пр. Причем компоновщик вставляет в итоговую сборку MSIL-код для передачи контекста только в том случае, если действие аспекта использует его. Аргументы целевого метода передаются через аргументы действия. Таким образом, аспект - это класс, производный от служебного базового класса Aspect, а его действиями будут открытые статические методы, помеченные атрибутом AspectAction(). В случае, когда определение аспекта задается на Aspect.NET ML, специальный конвертер переводит его в определение с пользовательскими атрибутами.

В свою очередь, MS Enterprise Library имеет множество готовых функциональных блоков и не требует никаких сторонних инструментов для своей работы, но возможности Unity по их аспектно-ориентированному применению серьезно ограничены. Перед авторами была поставлена задача заменить Unity и реализовать бесшовную интеграцию этих функциональных блоков с помощью Aspect.NET. Это позволило бы объединить сильные стороны двух инструментов, а именно: большой набор готовых аспектов, приемлемая скорость результирующего кода и независимость целевого проекта от АОП-инструмента. Объектом исследования были выбраны Autoscaling Application Block и Transient Fault Handling Block, как наиболее полезные для разработки облачных приложений на платформе Microsoft Azure. По мнению авторов, фокусирование на решении проблем сквозной функциональности в области разработки облачных приложений более перспективно, так как здесь возможности применения аспектно-ориентированного программирования еще не до конца изучены.

17.6. Принципы применения АОП и Aspect.NET для новой версии Azure на примере: Web-роль, на странице которой тестируется Logging Application Block

Для практического ознакомления с EL Integration Pack for Windows Azure компания Microsoft предлагает серию лабораторных работ (Hands-on Labs). Программисту предоставляется исходный проект и методические указания по его пошаговому изменению. Полученный результат можно сравнить с эталонным конечным проектом, в котором теперь задействуется тот или иной функциональный блок EL Integration Pack for Windows Azure. Если на основе этих методических указаний составить аспект и применить его с помощью Aspect.NET к начальному проекту, то результирующая сборка будет обладать функциональностью соответствующего эталонного проекта, но без модификации кода исходного проекта. Однако стоит учитывать, что изменения в конфигурационные файлы исходного проекта необходимо все же вносить вручную, поскольку АОП позволяет удалять сквозную функциональность лишь из программного кода.

Рассмотрим упражнение "Hands-on Lab 1: Using the Logging Application Block with Windows Azure Storage", где путем добавления ссылок на сборки EL производится подключение функционального блока логгирования к исходному проекту, а затем вызов его метода для передачи сообщения в облачное хранилище диагностической информации WAD (листинг 17.1). Это дает возможность настраивать параметры сбора и хранения отладочных сообщений через графический интерфейс Logging Application Block, либо через его конфигурационные файлы.

//Веб-роль, на странице которой тестируется Logging Application Block
public partial class Default : System.Web.UI.Page {
//Сообщение отсылается в обработчике щелчка мыши по кнопке страницы
protected void LogButton_Click(object sender, EventArgs e) {
Microsoft.Practices.EnterpriseLibrary.Logging.
     Logger.Write("Message from the Logging Application Block");
     }
}
    
Листинг 17.1.

Итак, наша задача заключается в том, чтобы перенести все зависимости от EL и вызовы методов протоколирования в отдельный проект с аспектом. Применив затем с помощью Aspect.NET данный аспект к исходному проекту, мы получим его бесшовную интеграцию с Logging Application Block.

Традиционно, в Aspect.NET подобные задачи решаются размещением кода протоколирования в действии аспекта и вставкой его перед, после, или вместо вызова целевого метода в исходном проекте. В нашем случае, целевой метод - это обработчик события щелчка мыши LogButton_Click() класса веб-страницы Default, причем созданием объекта этого класса и отправкой ему событий занимается среда ASP.NET и сервер IIS. Это означает, что код вызова нашего целевого метода располагается вне сборки исходного проекта и недоступен Aspect.NET.

По мнению авторов, перехват вызовов методов, которые реагируют на внешние события, может быть осуществлен через наследование классов. Если в аспектном проекте создать класс, который наследует от целевого класса, а затем подменить им свой базовый класс в сборке исходного проекта, то требуемый перехват можно осуществить в переопределенном виртуальном методе (см. листинг 17.2). Специальный пользовательский атрибут [ReplaceBaseClass] предписывает компоновщику Aspect.NET заменить целевой класс своим аспектным наследником:

  1. Заменить в исходной сборке все вызовы методов базового целевого класса (в том числе и конструкторы) на вызовы методов его наследника в аспектной сборке.
  2. Принудительно объявить виртуальными те методы целевого класса, которые переопределены в замещающем его наследнике. Если они закрыты (private), то сделать их защищенными (protected).
  3. Если вызов этих методов в исходной сборке производится с помощью MSIL-инструкции call или ldftn, заменить их на callvirt и ldvirtftn соответственно.
  4. Объединить с помощью инструмента ILRepack (из проекта Mono.Cecil) сборки с аспектом и исходную.
  5. Присвоить какое-нибудь служебное имя базовому целевому классу, а его первоначальное имя - замещающему наследнику из аспекта.

Преимуществами такого алгоритма является простота подмены классов для пользователя, а также использование только штатного синтаксиса языка .NET. Теперь с помощью аспекта можно: уточнять поведение любого метода целевого класса, реализовывать в нем дополнительные интерфейсы, накладывать различные пользовательские атрибуты и т.п.

//Проект с замещающим аспектным наследником
[AspectDotNet.ReplaceBaseClass]
public class AspectClass : Default {
protected void LogButton_Click(object sender, EventArgs e) {           
Microsoft.Practices.EnterpriseLibrary.Logging.
     Logger.Write("Message from the Logging Application Block");
            base.LogButton_Click(sender, e);
      }
}
 
//Исходный проект, после отделения зависимости от Logging Application Block
public partial class Default : System.Web.UI.Page {
protected void LogButton_Click(object sender, EventArgs e) {}
}
    
Листинг 17.2.
< Лекция 13 || Лекция 14: 1234 || Лекция 15 >
Александр Калинин
Александр Калинин

Осенью прошёл курс и получил ключ. Но т.к. уже имел действующую подписку, то ключом не воспользовался. Сейчас захожу сюда, а про DreamSpark вообще ни слова. Где же мой ключ?