我想用切入点来测量方法的执行时间,我用 CompletableFuture.supplyAsync 调用它。 目前,我只能触发一个方法,其中包含 CompletableFuture.supplyAsync,但不能触发方法,该方法将从 CompletableFuture.supplyAsync 执行。
这里我想测量 startProcess 方法:
@Async
public CompletableFuture<Void> myHandler(MyList request) {
CompletableFuture<Void> result = null;
for (MyEntity entity : request.getEntities()) {
result = CompletableFuture.supplyAsync(() -> selectRequiredProcess(entity), Runnable::run)
.thenAccept(case ->
log.info("success ")
.exceptionally(err -> {
return null;
});
}
return result;
}
public CompletableFuture<String> selectRequiredProcess(MyEntity entity) {
startNewProcess(entity);
return CompletableFuture.completedFuture(entity.getCaseId());
}
public void startNewProcess(InExkassodaten inExkassodaten) {
//do stuff...
}
我的切入点看起来像这样:
@Around("execution(* my.bbb.StartProcessService.*(my.bb.MyEntity))")
public Object executionTime(ProceedingJoinPoint point) throws Throwable {
long startTime = System.currentTimeMillis();
Object object = point.proceed();
long endtime = System.currentTimeMillis();
log.info("Class Name: {} . Method Name: {} . Time taken for Execution is : {} ms",
point.getSignature().getDeclaringTypeName(), point.getSignature().getName(),
(endtime - startTime));
return object;
}
但不会触发我从 CompletableFuture.supplyAsync 调用的方法。 我只能触发“myHandler”方法。
这实际上是许多类似问题的重复。例如,我正在here解释问题和可能的解决方案。简而言之:基于代理的 Spring AOP 在方法自调用的情况下不起作用,只有本机 AspectJ 可以。一种解决方法是将调用的方法分解到辅助组件中。
package de.scrum_master.spring.q78768043;
public class MyEntity {
String caseId;
public MyEntity(String caseId) {
this.caseId = caseId;
}
public String getCaseId() {
return caseId;
}
}
package de.scrum_master.spring.q78768043;
public class MyList {
public MyEntity[] getEntities() {
return new MyEntity[] { new MyEntity("one"), new MyEntity("two") };
}
}
package de.scrum_master.spring.q78768043;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;
@Service
public class StartProcessService {
@Autowired
HelperComponent helperComponent;
@Async
public CompletableFuture<Void> myHandler(MyList request) {
CompletableFuture<Void> result = null;
for (MyEntity entity : request.getEntities()) {
result = CompletableFuture.supplyAsync(() -> helperComponent.selectRequiredProcess(entity), Runnable::run)
.thenAccept(System.out::println);
}
return result;
}
@Component
public static class HelperComponent {
public CompletableFuture<String> selectRequiredProcess(MyEntity entity) {
startNewProcess(entity);
return CompletableFuture.completedFuture(entity.getCaseId());
}
public void startNewProcess(MyEntity myEntity) {
//do stuff...
}
}
}
package de.scrum_master.spring.q78768043;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MyAspect {
@Around("execution(* StartProcessService.HelperComponent.*(MyEntity))")
public Object executionTime(ProceedingJoinPoint point) throws Throwable {
long startTime = System.currentTimeMillis();
Object object = point.proceed();
System.out.printf(
"Class Name: %s . Method Name: %s . Time taken for Execution is : %d ms%n",
point.getSignature().getDeclaringTypeName(), point.getSignature().getName(),
System.currentTimeMillis() - startTime
);
return object;
}
}
package de.scrum_master.spring.q78768043;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
try (ConfigurableApplicationContext appContext = SpringApplication.run(DemoApplication.class, args)) {
doStuff(appContext);
}
}
private static void doStuff(ConfigurableApplicationContext appContext) {
appContext.getBean(StartProcessService.class).myHandler(new MyList());
}
}
运行应用程序以查看以下控制台日志:
Class Name: de.scrum_master.spring.q78768043.StartProcessService$HelperComponent . Method Name: selectRequiredProcess . Time taken for Execution is : 13 ms
java.util.concurrent.CompletableFuture@24842b8e[Completed normally]
Class Name: de.scrum_master.spring.q78768043.StartProcessService$HelperComponent . Method Name: selectRequiredProcess . Time taken for Execution is : 0 ms
java.util.concurrent.CompletableFuture@146add7b[Completed normally]