- PVSM.RU - https://www.pvsm.ru -
Решил внедрить АОП логирование на проект и не внедрил. Как и почему, собственно и хочу поделиться.
Я не буду описывать суть и принципы АОП, а опишу только те проблемы, с которыми я столкнулся, и решения которых заняло много времени.
У меня было в распоряжении Spring, WebLogic, google.com и проект, куда я хотел внедрить АОП логирование. Скажу сразу, до этого я никогда не работал с АОП.
Spring AOP – использует proxy-based подход.
Если у нас есть класс (СlassA) с методами (methodA, methodB), при этом methodB() вызывает methodA() и аспект (допустим after) который должен выполняться при вызове methodA():
public class ClassA {
public void methodA() {
System.out.println("methodA");
}
public void methodB() {
System.out.println("methodB");
methodA();
}
}
public class AspectClass {
public void aspectMethodA() {
System.out.println("Aspect on method A");
}
}
И некий класс который в рамках какой-то логики делает вызов этих методов:
public void execute() {
// .....
classA.methodA();
classA.methodB();
// .....
}
Результат такого вызова (используя стандартный Spring AOP) будет:
methodA
Aspect on method A
methodB
methodA
И все, второй раз аспект не сработает. В документации [1] хорошо описан принцип работы Spring-AOP, прочитав его, все встает на свои места. Это отправная точка.
Методы должны быть public. Тут без комментариев.
Так вот, почитав документацию и другую познавательную литературу я нашел следующее решение:
Поскольку я нашел хорошую документацию по LTW [2], я решил использовать именно его. Цена вопроса:
@Before( "execution(* com.solutions. web.test.WebTestClass.testA())")
public void testALog() {}
@Aspect
.-javaagent:${PATH_TO_LIB }/aspectjweaver.jar
Если посмотреть на пример приведенный в документации [2] (aop.context):
<weaver>
<include within="foo.*"/>
</weaver>
<aspects>
<aspect name="foo.ProfilingAspect"/>
</aspects>
Да все работает, но одно НО — мы редко будем хранить наш выполняющий код и непосредственно код аспектов в одном классе/пакете. Эту маленькую деталь они упустили в описании. Так вот, если у нас есть класс (ClassA) и аспект (AspectA) которые находятся в разных пакетах, то валидной конфигурацией будет следующий aop.xml:
<weaver>
<include within="com.example.ClassA"/> <!-- путь к конкретному классу -->
<include within="com.log.* "/> <!—путь к пакету с аспектами>
</weaver>
<aspects>
<aspect name="com.log.AspectA"/>
</aspects>
В теге <weaver>
следует указать все классы к которым будут применены аспекты + пакет со всеми аспектами.
LTW нельзя применить на EAR/APP уровне.
«As Costin said, there is unfortunately nothing we can do about this. Load-time weaving only works for specific deployment units such as WARs, and even there it is considered an advanced feature that won't work in all runtime environments.”
Конкретно этот комментарий [3] я искал очень долго.
Решением этой проблемы как вы догадались, и является использование CTW. Цена вопроса:
CTW+LTW не совместимые технологии.
Может мне просто не повезло, но по не известным мне причинам LTW сканировало весь classpath и при вызове классов скомпилированных при помощи СTW падало с ошибкой:
java.lang.Exception: java.lang.NoSuchMethodError: com.aop.example.log.AspectA.aspectOf()Lcom/aop/example/log/AspectA;
Проблема сразу же пропадает после отключения LTW.
Что я для себя вынес и хотел бы добавить:
<weaver>
файла app.context нужно указывать как сами “weav” классы так и aspect-ы.
В конечном итоге для приложения, имеющего WEB и APP уровни, получаем проект с Spring AOP + CTW технологиями.
От красивой конфигурации в одном .xml файле не осталось и следа. Из-за специфики проекта, объяснять все это заказчику я не решился и оставил эту затею для следующего проекта.
Скачать проект-пример можно из github-a [4]. Проект на maven-e.
Класс Executor является spring-bean-ом, получив его экземпляр, выполните метод execute().
Если вы все правильно завели, то в результате должны получить следующие сообщения:
--methodA-- method
Aspect Before for methodCTW
--methodCTW-- method
Aspect After for method A
--webMethodA-- method
Web Aspect Before for MethodCTW
--webMethodForCTW-- method
Web Aspect After web method A
Список литературы:
Cсылки на статьи из Хабра:
Автор: Liroyd
Источник [9]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/maven/38953
Ссылки в тексте:
[1] документации: http://static.springsource.org/spring/docs/2.5.5/reference/aop.html
[2] LTW: http://static.springsource.org/spring/docs/3.0.0.RC2/reference/html/ch07s08.html
[3] комментарий: https://jira.springsource.org/browse/SPR-6176
[4] github-a: https://github.com/Liroyd/aop.git
[5] AspectJ: http://eclipse.org/aspectj/
[6] Spring3-AOP-AspectJ-XML-Example: http://www.mkyong.com/spring3/spring-aop-aspectj-in-xml-configuration-example/
[7] AspectJ, Spring, Maven: http://habrahabr.ru/post/112466/
[8] Знакомство с АОП: http://habrahabr.ru/post/114649/
[9] Источник: http://habrahabr.ru/post/186940/
Нажмите здесь для печати.