Диссертация (1148251), страница 17
Текст из файла (страница 17)
РЕЗУЛЬТИРУЮЩИЙ WEB.CONFIG90Для решения указанной проблемы в диссертации предложено в целевомпроекте иметь два конфигурационных файла (напр. TargetWeb.config иweb.config). В первом из них будут настройки целевого приложения, а во втором— результат объединения их с аспектными настройками. Пользователь будетредактировать и хранить настройки целевого проекта в TargetWeb.config, а, припостроении сборки в Microsoft Visual Studio, специальное консольное приложениеXMLMergerConsole (вызванное в событиях Pre-Build Events аспектного проекта)будет сливать аспектный web.config с TargetWeb.config в общий web.configцелевого проекта. После завершения компиляции и развертывания в облакеаспекты и бизнес-логика будут иметь доступ к своим настройкам, содержащимсяв общем web.config. Необходимость слияния конфигурационных файлов на этапепредкомпиляции (Pre-Build Events) вытекает из того, что компилятор используетнекоторые настройки, заданные в web.config и, следовательно, слияние должнопроизойти перед стадией компиляции.Приведём требуемый алгоритм слияния аспектного web.config и целевогоTargetWeb.config в результирующий web.config.
Он должен удовлетворятьследующим правилам:1) вначале содержимое TargetWeb.config копируется в результирующийweb.config;2) если в TargetWeb.config отсутствует узел, который есть в аспектномweb.config, то этот узел добавляется в результирующий web.config;3) если и в TargetWeb.config и в аспектном web.config есть узел с одинаковыматрибутом name, то весь этот узел берется из аспектного web.config.Рекурсивный алгоритм слияния приведен в листинге 31:91void Merge(XmlNode aspectNode, XmlNode targetWebNode, out XmlNode resultNode) {resultNode = targetWebNode.Clone();// перебор по дочерним узлам входного узла "a", меняется только приёмник "b"for (int i = aspectNode.ChildNodes.Count - 1; i >= 0; --i) {XmlNode node = aspectNode.ChildNodes[i];}}// поиск такого же узла с таким же путёмXmlNode findedNode = Find(resultNode.ChildNodes, node);// такой узел есть в целевом файлеif (findedNode != null) {// продолжаем сравнивать детей этих двух одинаковых найденных// узловMerge(node, findedNode);}else{// если нет такого узла в приёмнике, то вставим его со// всеми детьми из источникаresultNode.AppendChild(resultNode.OwnerDocument.ImportNode(node, true));}ЛИСТИНГ 31.
АЛГОРИТМ СЛИЯНИЯ ФАЙЛОВ WEB.CONFIGАктуальность слияния и замещения целевой конфигурации аспектной такжеподтверждается популярностью в облачном веб-программировании паттерна“Модель провайдера” (Provider model) [46], когда некоторые компонентыреализуютодинаковыйинтерфейс,асозданиеконкретногоэкземплярапроизводится “фабричным методом” на основе настроек в Web.config. Такимобразом, чтобы заменить реализацию, достаточно изменить конфигурацию иданное изменение вполне можно вынести в аспект. Возможным сценариемявляется ситуация, когда облачное приложение тестируется на локальныхкомпонентах,апередпубликациейвоблаконеобходимопоменятьсоответствующие настройки провайдеров на облачную инфраструктуру. Еслиопределить облачные настройки в Web.config аспекта, тогда публикация егопроекта в Microsoft Visual Studio приведет к развертыванию в облаке с облачныминастройками, а запуск целевого проекта — к запуску веб-приложения слокальными настройками.923.5 Выводы по главеНесмотря на широкие возможности Aspect.NET (версии 2.1) по созданиюАОП-программ, его применение для бесшовного применения аспектов к вебприложениям было затруднено.
Во-первых, отсутствовала интеграция с MicrosoftVisual Studio – основной средой разработки облачных приложений в MicrosoftAzure. Во-вторых, не было возможности отлаживать результирующие сборки свнедренными аспектами. В-третьих, веб-приложения Microsoft Azure реализуютсякаркасом ASP.NET и Aspect.NET не позволял перехватывать каким-либоспособом вызываемые ASP.NET обработчики событий.В данной главе описаны предложенные в диссертационном исследованииспособы адаптации системы Aspect.NET для бесшовного АОП-программированиявеб-приложенийнабазеMicrosoftAzure,которыерешаютвсевышеперечисленные проблемы. При этом:1. Интеграция с Microsoft VS производится за счет вызова компоновщикааспектов Aspect.NET в событиях пост-компиляции аспектного проекта.2. Механизм отладки реализуется с помощью добавления отладочнойинформации к новым MSIL-инструкциям средствами Microsoft Phoenixи Mono.Cecil.3.
Разработан и реализован способ переопределять целевой классаспектным наследником, что позволяет бесшовно расширять егофункциональность и перехватывать целевые методы, недоступные для%before, %after, %instead действий Aspect.NET.4. Дополнительно предложен метод отдельного хранения настроек в XMLфайлах целевого и аспектного проектах. Такое разделение помогаетзапускать и тестировать целевой проект как с внедренными аспектами,так и без них. В первом случае конфигурационный файл содержитнастройки целевого и аспектного проекта, во втором – только целевого.Кроме того, некоторые аспекты (например, авторизация на базе форм)93могут быть реализованы исключительно в конфигурационном файлеаспекта.Данные методики реализованы в Aspect.NET версии 3.0 на базе которойразработана описанная в диссертации библиотека аспектов для облачных вебприложенийAzureLibrary,сформулированыпринципыАОП-рефакторингаоблачных веб-приложений и продемонстрирована возможность бесшовнорасширятьповедениецелевоговеб-приложениябиблиотеки Microsoft Enterprise Library.спомощьюсторонней94Глава4.Реализациябиблиотекиаспектов дляоблачных веб-приложений4.1 Перенаправление диагностической информации в Azure DiagnosticsStorageКак правило, для протоколирования на платформе .NET используютсястатическиеметодыклассаSystem.Diagnostics.Trace[48].Определениеконкретного приемника трассировочной информации осуществляется по паттерну“Наблюдатель”, то есть через добавление в коллекцию “слушателей”://Создать ConsoleTraceListener и добавить его в слушатели класса TraceConsoleTraceListener myWriter = new ConsoleTraceListener();Trace.Listeners.Add(myWriter);ЛИСТИНГ 32.
ДОБАВЛЕНИЕ В КОЛЛЕКЦИЮ СЛУШАТЕЛЕЙЕсли теперь вызвать метод, например, Trace.TraceInformation(string), то егоаргумент будет выведен на консоль. Предположим, что какое-то существующееприложение написано с учетом этих особенностей и его необходимо перенести воблако.
Тогда эту задачу можно возложить на аспект и бесшовно расширить имцелевое приложение.В облачной инфраструктуре Microsoft Azure отладочная информациядолжна храниться в специальном хранилище Azure Diagnostics Storage (WAD). АотвечаетзасборотладочнойинформацииобъектклассаMicrosoft.WindowsAzure.Diagnostics.DiagnosticMonitor [26], который необходимозапустить при старте роли.
Далее нужно зарегистрировать объект классаMicrosoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener как слушателятрассировки от класса Trace. После всех этих операций всю отладочнуюинформацию можно будет просматривать в облачной WAD-таблице с помощьюпанели Server Explorer в Microsoft Visual Studio.Приведемв листинге 33:кодаспекта,выполняющийперечисленныеоперации95public class AzureTrace : Aspect {//Строка для установки соединения с хранилищем Azureconst string DiagnosticsConnectionString = "…";//Настраиваем и запускаем диагностику Azure внутри метода WebRole.OnStart()[AspectAction("%before %call *RoleEntryPoint.OnStart()")]static public void RegisterAzureDiagnostics() {try {DiagnosticMonitorConfiguration diagnosticConfig =DiagnosticMonitor.GetDefaultInitialConfiguration();//Проводим настройку диагностического монитораdiagnosticConfig.Directories.ScheduledTransferPeriod =TimeSpan.FromMinutes(1d);diagnosticConfig.Directories.BufferQuotaInMB = 100;diagnosticConfig.Logs.ScheduledTransferPeriodTimeSpan.FromMinutes(1d);diagnosticConfig.Logs.ScheduledTransferLogLevelFilterLogLevel.Verbose;==//Указываем данные для доступа к облачному хранилищуCloudStorageAccount storage =CloudStorageAccount.Parse(DiagnosticsConnectionString);DiagnosticMonitor.Start(storage, diagnosticConfig);}}catch (Exception e){//Получаем из контекста точку внедрения и указываем её в сообщенииTrace.WriteLine("Exception during " + WithinType.ToString() + "." +WithinMethod.Name.ToString() + ": " + e.ToString());}//Перед каждым вызовом TraceInformation() убеждаемся, что соотв.
WAD-подписчик//зарегистрирован в коллекции System.Diagnostics.TraceListener[AspectAction("%before %call *System.Diagnostics.Trace.TraceInformation")]public static void AspectTrace() {foreach(System.Diagnostics.TraceListener listener inSystem.Diagnostics.Trace.Listeners) {if (listener isMicrosoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener)return;}}}//Если его ещё нет в списке подписчиков, то добавляем в этот списокSystem.Diagnostics.Trace.Listeners.Add(new Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener());System.Diagnostics.Trace.AutoFlush = true;ЛИСТИНГ 33.
АСПЕКТ ДЛЯ РАБОТЫ С ОТЛАДОЧНОЙ ИНФОРМАЦИЕЙКак можно видеть, действие аспекта RegisterAzureDiagnostics требуетсявыполнить при старте веб-роли WebRole.OnStart(). Данный метод вызываетсяMicrosoft Azure напрямую, и компоновщик аспектов не имеет возможности егоперехватить без создания замещающего аспектного наследника, что повысило бызависимость аспекта от конкретной веб-роли. Поэтому, в целях универсальности,96можно воспользоваться тем фактом, что внутри WebRole.OnStart() обычносодержится вызов base.OnStart() и вставить вызов действия аспекта перед ним.Далее, действие AspectTrace демонстрирует регистрацию слушателя дляWAD-таблицы перед вызовом метода трассировки. Стоит отметить, что еслилогика выбора слушателя достаточно проста, то подобную регистрацию можноперенести в конфигурационный файл аспекта:<system.diagnostics><trace><listeners><addtype="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener,Microsoft.WindowsAzure.Diagnostics,Version=1.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35" name="AzureDiagnostics"></add></listeners></trace></system.diagnostics>ЛИСТИНГ 34.