Добавить AspectJ в Webservice
У меня есть Java EE Webservice (REST) и теперь хотел бы использовать AspectJ, чтобы создать правило, которое будет распечатывать каждый входящий вызов службы и их параметры.
Я просто прочитал этот учебник и реализовал следующий код:
pom.xml
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.10</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
<showWeaveInfo>true</showWeaveInfo>
<verbose>true</verbose>
<Xlint>ignore</Xlint>
<encoding>UTF-8 </encoding>
</configuration>
<executions>
<execution>
<goals>
<!-- use this goal to weave all your main classes -->
<goal>compile</goal>
<!-- use this goal to weave all your test classes -->
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
... и создал файл Test.aj с помощью Pointcut, который должен распечатать тестовую строку после вызова getSignOfLife():
import de.jack.businesspartner.service.BusinessPartnerServiceImpl;
public aspect TestAspectJ {
pointcut getSignOfLife() :
call(void BusinessPartnerServiceImpl.getSignOfLife());
before() : getSignOfLife() {
System.err.println("ADKL TEST ASPECT");
}
}
- > Но ничего не происходит, если я вызываю метод getSignOfLife(). Можете ли вы мне помочь?
Ответы
Ответ 1
@Тони объяснил это довольно хорошо.
Что касается учебника, вы указали, я протестировал его, слегка изменив аспект учетной записи:
public aspect AccountAspect {
final int MIN_BALANCE = 10;
pointcut callWithDraw(int amount, Account acc) :
call(boolean Account.withdraw(int)) && args(amount) && target(acc);
before(int amount, Account acc) : callWithDraw(amount, acc) {
}
boolean around(int amount, Account acc) :
callWithDraw(amount, acc) {
acc.balance -= 5;
if (acc.balance < amount) {
return false;
}
return proceed(amount, acc);
}
after(int amount, Account balance) : callWithDraw(amount, balance) {
System.out.println("After withdraw " + amount);
}
}
Затем в простой сервлет:
@WebServlet("/Hello")
public class Hello extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 482093033327453159L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
Account acc = new Account();
resp.setContentType("text/html");
PrintWriter out = resp.getWriter();
out.println("Account before withdraw: " + acc.balance + "<br/>");
acc.withdraw(10);
out.println("Account after withdraw: " + acc.balance + "");
out.close();
}
}
Я использовал:
- Java 8
- Wildfly 10.1.0.Final
Он работает так, как ожидалось (при вызове отзыва учетная запись будет снята еще на 5, как вы можете видеть из around
в моем файле aspectj, а отпечатки записываются на консоль)
Ответ 2
Ваше выражение вырезания точки может быть неправильным:
pointcut getSignOfLife() :
call(void BusinessPartnerServiceImpl.getSignOfLife());
Выражение в call
должно соответствовать сигнатуре вашего реального метода.
CheckList
- Тип возвращаемого значения:
getSignOfLife
Кажется, имеет возвращаемое значение, которое вы пишете тип выражения void
в выражении, который не даст совпадения;
- тип параметра: вы можете использовать
f(..)
для представления метода f
с любым параметром, но если вы оставили его пустым, это означает отсутствие параметра. Если ваш фактический метод имеет параметр, он не сможет выполнить совпадение;
- обратите внимание, что
int
и Integer
отличаются в выражении, потому что примитивы и тип бокса различны;
-
вам нужен оригинальный плагин компилятора maven в вашей pom;
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
Подробнее
- Вы можете обратиться к здесь, если хотите погрузиться в AspectJ
- В наиболее распространенных случаях Spring AOP достаточно для обработки таких заданий, как ведение журнала, auth и т.д., которые могут использоваться с аннотацией, и я думаю, что это более удобно.
- Runnable code.