我正在使用AOP来围绕某些服务包装审计框架。我遇到过一个问题,即由于递归,我们会针对同一操作审核多个事件。快速解决方法将方法标记为@NonAuditable
并将其添加到我的切入点策略中。我发现该方法仍然被执行。
这是我现有的策略:
@Around(value="(" +
"execution( * my.class.services..*.*(..)) " +
") && "+
"@annotation(auditable)), argName="audit")
public Object audit(ProceedingJoinPoint call, Audit audit) {
...
...
}
如何更新我的执行以表示"只有在不包含@NonAuditable
注释的服务包中执行?
我尝试了以下操作,但没有效果:
@Around(value="(" +
"execution( * my.class.services..*.*(..)) " +
") && "+
"!@annotation(NonAuditable) && " +
"@annotation(auditable), argName="audit")
public Object audit(ProceedingJoinPoint call, Audit audit) {
...
...
}
更新:
以下是一些获得审核的方法的一些示例
package my.class.services.UserService
import ...
...
@Auditable(message="Request for user", Context="Search")
public User getUser(long id){
User u = userRepository.getUser(id);
... // do work
}
\
package my.class.services.CarService
import ...
...
@Auditable(message="Request for traffic violations", Context="Search")
public List<Ticket> getTickets(long id){
List<Ticket> tix = dmvRepository.getUserTicketsById(id);
... // do work
}
@NonAuditable(message="Request for traffic violations", Context="Search")
public List<Ticket> getSpeedingTickets(long id){
List<Ticket> tickets = this.getTickets(id);
Collection filter = Collection.filter(...);
// do some other logic to just get speeding tickets.
return filter;
}
我继承的一个问题是getTickets
被另一个方法(getSpeedingTickets)递归调用,我希望能够在该方法上应用Annotation
(@NonAuditable
)阻止getTickets
被审核。
答案 0 :(得分:0)
好的,我又想了想,我想我已经猜到了你的意思。我认为你的情况是这样的:
<强>注解强>
package de.scrum_master.app;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Auditable {}
package de.scrum_master.app;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface NonAuditable {}
驱动程序应用程序:
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
Application application = new Application();
application.auditableAction("main");
application.inBetweenAction("main");
application.otherAction();
application.nonAuditableAction();
}
@Auditable
public void auditableAction(String caller) {
System.out.println(" auditableAction called by " + caller);
}
@NonAuditable
public void nonAuditableAction() {
auditableAction("nonAuditableAction");
inBetweenAction("nonAuditableAction");
}
public void otherAction() {
auditableAction("otherAction");
inBetweenAction("otherAction");
}
public void inBetweenAction(String caller) {
auditableAction(caller + " via inBetweenAction");
}
}
现在我假设您希望避免在@Auditable
方法直接或间接调用时审核@NonAuditable
方法的执行。正确?如果是这样,解决方案是使用cflow()
或cflowbelow()
切入点。由于此类切入点无法静态评估,但仅在运行时动态评估,因此您可能需要在应用方面后监视应用程序的性能,但在许多情况下,这不是一个真正的问题。你自己看。解决方案如下:
<强>方面:强>
package de.scrum_master.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class AuditAspect {
@Around(
"within(de.scrum_master.app..*) && " +
"execution(* *(..)) && " +
"@annotation(de.scrum_master.app.Auditable) && " +
"!cflow(@annotation(de.scrum_master.app.NonAuditable))"
)
public Object audit(ProceedingJoinPoint thisJoinPoint) throws Throwable {
System.out.println(thisJoinPoint);
return thisJoinPoint.proceed();
}
}
控制台日志:
execution(void de.scrum_master.app.Application.auditableAction(String))
auditableAction called by main
execution(void de.scrum_master.app.Application.auditableAction(String))
auditableAction called by main via inBetweenAction
execution(void de.scrum_master.app.Application.auditableAction(String))
auditableAction called by otherAction
execution(void de.scrum_master.app.Application.auditableAction(String))
auditableAction called by otherAction via inBetweenAction
auditableAction called by nonAuditableAction
auditableAction called by nonAuditableAction via inBetweenAction
请注意,在最后两行之前没有记录任何内容。