I heard wechat search “Java fish boy” will change strong oh!

This article is in the JavaStarter, which has my complete Java series, study or interview can see oh

(I) Preface

Recently, by the end of the year, the system has been stable for three months. However, the project manager recently felt the system slowed down and wanted to know the execution time of all the methods on both the front end and the back end of the system. Yes you heard me right, every way. As soon as this requirement is presented, it is masked, and execution time is calculated for each method, which puts pressure on the system.

(2) Ideas

Now that I mention it, let me give you some ideas. In fact, it is very simple, each method before the execution of a timestamp, record a timestamp at the end of the execution, subtraction is the execution time. But it’s not practical to change every method, there’s so much code, it’s too much work to hack, and what if one day the project manager doesn’t want it anymore?

When you hear this requirement, you should think of AOP. I have used Spring for so long, IOC and AOP by heart. Now is the time to apply it.

(3) Use AOP to record time

The concept of AOP is not mentioned here, but aspect oriented, non-invasive development fits this requirement perfectly. And 20 lines of code will solve the problem.

3.1 Importing Dependencies

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
Copy the code

3.2 Configuring Sections

To start by configuring a pointcut, I want the aspect to take effect on all methods in the TestController class

@Slf4j
@Component
@Aspect
@Order(10)
public class LogAspect {

	// Configure the pointcut, that is, the location of execution
    @Pointcut("execution(* com.javayz.codinguser.controller.TestController.*(..) )"
    public void pointCut(a){}// Use surround notification to record a time subtraction before and after the execution of the method
    @Around("pointCut()")
    public Object doLog(ProceedingJoinPoint proceedingJoinPoint){
        long startTime = System.currentTimeMillis();
        Object object=null;
        try {
            object=proceedingJoinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }finally {
            long endTime = System.currentTimeMillis();
            log.info(proceedingJoinPoint.getSignature().toShortString()+"The method is executed:"+(endTime-startTime)+"ms");
        }
        returnobject; }}Copy the code

The TestController method looks like this:

@RestController
@RequestMapping("/testApi")
public class TestController {

    @GetMapping("/test1")
    public String testAop(a){
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "testAop"; }}Copy the code

3.3 Test

Call /testApi/test1 directly, and you get the effect

3.4 Customizing an annotation

This is sufficient to meet the project manager’s needs, and if the new code is not in the scope of the pointcut, it will not take effect, so define an annotation and write one when you want to record it

@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
@Documented
public @interface LogAnnotation {
}
Copy the code

Add annotations when configuring pointcuts

@Pointcut("execution(* com.javayz.codinguser.controller.TestController.*(..) ) || @annotation(com.javayz.codinguser.annotation.LogAnnotation)")
public void pointCut(a){}Copy the code

OK, add this annotation when you need to execute.

(4) Problems concerning the recording of data

The project manager also wants to be able to check the execution time of a method at any given time, so this data must be saved.

Now, there are 40,000 people using this system. If I put it into the database, I define three fields in the table: time, caller, call time, call method. A piece of data is about 40 bytes in size. That’s at least 40 million pieces of data a day, or about 1.5 gigabytes, for 40, 000 people. The amount of data doesn’t matter, but the pressure to write to the database is even greater.

The same is true if it is in a log, which can become very large and inconvenient to check.

(v) Results

Finally, after some reasoning with the project manager, he changed his mind and only recorded the methods that took more than 200ms to execute, and the data was recorded in the log. This requirement was solved through communication and a small amount of code. Well, see you next time!