在 Web 服务中添加 AspectJ
Add AspectJ in Webservice
我有一个 Java EE Webservice (REST),现在想使用 AspectJ 创建一个规则,打印出每个传入的服务调用及其参数。
我刚读完这篇文章 tutorial 并实现了以下代码:
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 文件,带有一个切入点,它应该在调用 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() 方法,则不会发生任何事情。你能帮帮我吗?
你的切点表达可能有误:
pointcut getSignOfLife() :
call(void BusinessPartnerServiceImpl.getSignOfLife());
call
中的表达式应与您的真实方法的签名匹配。
清单
- return type:
getSignOfLife
似乎有一个 return 值,你在表达式中写一个 void
return 类型,这将使匹配失败;
- 参数类型:可以用
f(..)
表示一个方法f
有任何参数,但如果留空则表示没有参数。如果您的实际方法有参数,它将匹配失败;
- 注意
int
和Integer
的表达方式不同,因为基元和拳法不同;
你的pom中需要maven的原始编译器插件;
<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,你可以参考 here
- 在大多数情况下,Spring AOP足以处理日志记录,身份验证等工作,可以与注释一起使用,我认为更方便。
- Runnable code.
@Tony 解释得很好
关于您指出的tutorial,我通过稍微修改帐户方面进行了测试:
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);
}
}
然后在一个简单的 servlet 中:
@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
- 野蝇 10.1.0.Final
它按预期工作(当调用 withdraw 时,帐户又被提取了 5 个,正如您从我的 aspectj 文件中的 around
中看到的那样,打印在控制台上)
我有一个 Java EE Webservice (REST),现在想使用 AspectJ 创建一个规则,打印出每个传入的服务调用及其参数。
我刚读完这篇文章 tutorial 并实现了以下代码:
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 文件,带有一个切入点,它应该在调用 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() 方法,则不会发生任何事情。你能帮帮我吗?
你的切点表达可能有误:
pointcut getSignOfLife() :
call(void BusinessPartnerServiceImpl.getSignOfLife());
call
中的表达式应与您的真实方法的签名匹配。
清单
- return type:
getSignOfLife
似乎有一个 return 值,你在表达式中写一个void
return 类型,这将使匹配失败; - 参数类型:可以用
f(..)
表示一个方法f
有任何参数,但如果留空则表示没有参数。如果您的实际方法有参数,它将匹配失败; - 注意
int
和Integer
的表达方式不同,因为基元和拳法不同; 你的pom中需要maven的原始编译器插件;
<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,你可以参考 here
- 在大多数情况下,Spring AOP足以处理日志记录,身份验证等工作,可以与注释一起使用,我认为更方便。
- Runnable code.
@Tony 解释得很好
关于您指出的tutorial,我通过稍微修改帐户方面进行了测试:
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);
}
}
然后在一个简单的 servlet 中:
@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
- 野蝇 10.1.0.Final
它按预期工作(当调用 withdraw 时,帐户又被提取了 5 个,正如您从我的 aspectj 文件中的 around
中看到的那样,打印在控制台上)