我已经使用spring boot和spring initileizr制作了一个简单的Web应用程序,并尝试用 @ASPECT 使用 @AROUND 建议。
当我添加自定义注释 @retryonfailure 到控制器的端点方法 - 它可以使用,但是当我将此注释添加到控制器端点执行的控制器方法时 - 工作。我花了很多时间来理解这种行为的原因,但没有任何结果。所以请帮助。
项目:https://github.com/zalizko/spring-aop-playground
@Aspect
@Component
public final class MethodRepeater {
@Around("execution(* *(..)) && @annotation(RetryOnFailure)")
public Object wrap(final ProceedingJoinPoint joinPoint) throws Throwable {
// code is here
}
}
所以,我的目标是:
@RequestMapping
public String index() {
inTry();
return "OK";
}
@RetryOnFailure(attempts = 3, delay = 2, unit = TimeUnit.SECONDS)
public void inTry() {
throw new RuntimeException("Exception in try " + ++counter);
}
您犯了一个典型的春季AOP初学者的错误:您忘记了基于代理的AOP仅在从外部调用代理方法而不是通过this
调用(避免代理)时起作用。但是内部呼叫inTry()
与this.inTry()
相同。因此,该方面永远不会触发inTry
,您必须像这样重新排列您的代码:
package spring.aop;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
@RestController("/")
public class HomeController {
static int counter = 0;
@RequestMapping
@RetryOnFailure(attempts = 3, delay = 2, unit = TimeUnit.SECONDS)
public String index() {
throw new RuntimeException("Exception in try " + ++counter);
}
}
我也更改了一些方面,以便
- 避免反射并将注释直接通过
@annotation()
,
绑定到建议参数 - 在触发建议和 时记录JoinPoint
- 在尝试#3上返回"确定"(只是为了娱乐,不是必需的)。
package spring.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public final class MethodRepeater {
@Around("execution(* spring.aop..*(..)) && @annotation(retryOnFailure)")
public Object wrap(final ProceedingJoinPoint joinPoint, RetryOnFailure retryOnFailure) throws Throwable {
System.out.println(joinPoint);
return proceed(joinPoint, retryOnFailure);
}
private Object proceed(ProceedingJoinPoint joinPoint, RetryOnFailure retryOnFailure) throws Throwable {
int attempt = 1;
while (true) {
try {
return joinPoint.proceed();
} catch (final Throwable ex) {
System.out.println("Try #" + attempt + " failed: " + ex);
if (++attempt >= retryOnFailure.attempts())
return "OK";
if (retryOnFailure.delay() > 0L)
retryOnFailure.unit().sleep(retryOnFailure.delay());
}
}
}
}
现在可以正常工作,并且控制台日志说:
execution(String spring.aop.HomeController.index())
Try #1 failed: java.lang.RuntimeException: Exception in try 1
Try #2 failed: java.lang.RuntimeException: Exception in try 2
我遇到了类似的问题,我设法使用facteactj:
来解决它。https://github.com/mdanetzky/tour-of-heroes-java
另外 - 我花了一些时间来找出我的想法没有正确地重建方面,因此在尝试一些更严厉的措施之前,可能值得尝试清洁/重建项目。
5/2023 for AspectJ
myApplication.java
@SpringBootApplication
public class AopjApplication {
public static void main(String[] args) {
ConfigurableApplicationContext cntx = SpringApplication.run(AopjApplication.class, args);
A a=cntx.getBean(A.class);
a.chirp();
}
}
将FactactJ添加到 build.gradle
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.aspectj:aspectjweaver:1.9.19' //currently last version
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
A.Java:
public class A {
public void chirp() {
System.out.print(11111);
}
}
myconfig.java
@Configuration
@EnableAspectJAutoProxy
public class MyConfig {
@Bean
public A a() {
return new A();
}
@Bean
public B b() {
return new B();
}
. . .
@Bean
public MyAspect myAspect() {
return new MyAspect();
}
}
myaspect.java
@Aspect
public class MyAspect {
@Before("execution(* mypackage.A.chirp())")
public void aa() {
System.out.print(2222);
}
}
我可以运行它,现在控制台显示:
2023-05-21T22:47:34.035+05:00 INFO 9332 --- [ main] mypackage.AopjApplication : Starting AopjApplication using Java 17.0.6 with PID 9332 (C:Usersericseclipse-workspaceaopjbinmain started by erics in C:Usersericseclipse-workspaceaopj)
2023-05-21T22:47:34.045+05:00 INFO 9332 --- [ main] mypackage.AopjApplication : No active profile set, falling back to 1 default profile: "default"
2023-05-21T22:47:35.566+05:00 INFO 9332 --- [ main] mypackage.AopjApplication : Started AopjApplication in 2.33 seconds (process running for 3.303)
2222
11111