1. 概述
在本教程中,我們將探討 Spring Framework 為性能監控提供的幾個基本選項。
2.
一個簡單的解決方案,用於獲取我們方法執行時間的基本監控功能,我們可以利用 Spring AOP(面向切面編程)中的 類。
Spring AOP 允許在應用程序中定義橫切關注點,這意味着可以攔截一個或多個方法的執行,以便添加額外的功能。
類是一個攔截器,可以與任何自定義方法關聯,以便在方法執行的同時執行。該類使用一個 實例來確定方法的開始時間和結束時間。
讓我們創建一個簡單的 類和一個 類,其中包含兩個我們將進行監控的方法:
public class Person {
private String lastName;
private String firstName;
private LocalDate dateOfBirth;
// standard constructors, getters, setters
}public class PersonService {
public String getFullName(Person person){
return person.getLastName()+" "+person.getFirstName();
}
public int getAge(Person person){
Period p = Period.between(person.getDateOfBirth(), LocalDate.now());
return p.getYears();
}
}為了充分利用 Spring 監控攔截器,我們需要定義一個切入點和顧問:
@Configuration
@EnableAspectJAutoProxy
@Aspect
public class AopConfiguration {
@Pointcut(
"execution(public String com.baeldung.performancemonitor.PersonService.getFullName(..))"
)
public void monitor() { }
@Bean
public PerformanceMonitorInterceptor performanceMonitorInterceptor() {
return new PerformanceMonitorInterceptor(true);
}
@Bean
public Advisor performanceMonitorAdvisor() {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("com.baeldung.performancemonitor.AopConfiguration.monitor()");
return new DefaultPointcutAdvisor(pointcut, performanceMonitorInterceptor());
}
@Bean
public Person person(){
return new Person("John","Smith", LocalDate.of(1980, Month.JANUARY, 12));
}
@Bean
public PersonService personService(){
return new PersonService();
}
}切面包含一個表達式,用於識別我們希望攔截的方法——在本例中是 PersonService 類中 getFullName() 方法。
配置 performanceMonitorInterceptor() Bean 後,我們需要將攔截器與切面關聯起來。這通過 Advisor 實現,如上例所示。
最後,@EnableAspectJAutoProxy 註解啓用了 AspectJ 支持,以便我們對 Bean 進行支持。簡單來説,AspectJ 是一個庫,旨在通過方便的註解(如 @Pointcut)使 Spring AOP 更容易使用。
配置完成後,我們需要將攔截器類的日誌級別設置為 TRACE,因為這是它記錄消息的級別。
例如,使用 Jog4j,我們可以通過 log4j.properties 文件來實現這一點:
log4j.logger.org.springframework.aop.interceptor.PerformanceMonitorInterceptor=TRACE, stdout對於 getAge() 方法的每次執行,您將在控制枱日誌中看到 TRACE 消息:
2017-01-08 19:19:25 TRACE
PersonService:66 - StopWatch
'com.baeldung.performancemonitor.PersonService.getFullName':
running time (millis) = 103. 自定義性能監控攔截器
為了獲得對性能監控的更多控制,我們可以實現自定義攔截器。為此,我們應該擴展 AbstractMonitoringInterceptor 類並覆蓋 invokeUnderTrace() 方法,以記錄方法的開始、結束和持續時間,以及如果方法執行時間超過 10 毫秒的警告。
public class MyPerformanceMonitorInterceptor extends AbstractMonitoringInterceptor {
public MyPerformanceMonitorInterceptor() {
}
public MyPerformanceMonitorInterceptor(boolean useDynamicLogger) {
setUseDynamicLogger(useDynamicLogger);
}
@Override
protected Object invokeUnderTrace(MethodInvocation invocation, Log log)
throws Throwable {
String name = createInvocationTraceName(invocation);
long start = System.currentTimeMillis();
log.info("Method " + name + " execution started at:" + new Date());
try {
return invocation.proceed();
}
finally {
long end = System.currentTimeMillis();
long time = end - start;
log.info("Method "+name+" execution lasted:"+time+" ms");
log.info("Method "+name+" execution ended at:"+new Date());
if (time > 10){
log.warn("Method execution longer than 10 ms!");
}
}
}
}遵循前一節中將自定義攔截器與一個或多個方法關聯的相同步驟。
讓我們為getAge()方法定義一個切入點,該方法位於PersonService中,並將該切入點與我們創建的攔截器關聯起來:
@Pointcut("execution(public int com.baeldung.performancemonitor.PersonService.getAge(..))")
public void myMonitor() { }
@Bean
public MyPerformanceMonitorInterceptor myPerformanceMonitorInterceptor() {
return new MyPerformanceMonitorInterceptor(true);
}
@Bean
public Advisor myPerformanceMonitorAdvisor() {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("com.baeldung.performancemonitor.AopConfiguration.myMonitor()");
return new DefaultPointcutAdvisor(pointcut, myPerformanceMonitorInterceptor());
}讓我們將日誌級別設置為 INFO 以供自定義攔截器使用:
log4j.logger.com.baeldung.performancemonitor.MyPerformanceMonitorInterceptor=INFO, stdout執行 g<em>etAge()</em> 方法 產生以下輸出:
2017-01-08 19:19:25 INFO PersonService:26 -
Method com.baeldung.performancemonitor.PersonService.getAge
execution started at:Sun Jan 08 19:19:25 EET 2017
2017-01-08 19:19:25 INFO PersonService:33 -
Method com.baeldung.performancemonitor.PersonService.getAge execution lasted:50 ms
2017-01-08 19:19:25 INFO PersonService:34 -
Method com.baeldung.performancemonitor.PersonService.getAge
execution ended at:Sun Jan 08 19:19:25 EET 2017
2017-01-08 19:19:25 WARN PersonService:37 -
Method execution longer than 10 ms!4. 結論
在本快速教程中,我們介紹了在 Spring 中進行簡單性能監控的方法。