AOP is one of the two most important concepts in the Spring architecture (the other is IoC), and this article will take you through the field. AOP techniques were used in the Programming cat SpringBoot project to add a facet to the Controller layer to achieve uniform logging of interface access.

First, about AOP

AOP, also known as aspect-oriented Programming, is a design idea in computer science that aims to add extra Advice to business entities through Aspect technology. This allows uniform management and decoration of code blocks declared as “pointcuts.”

This philosophy applies well to adding functionality that is not closely related to the core business, such as logging functionality, which is today’s topic.

AOP is a supplement to object-oriented Programming (COMMONLY known as OOP). OOP’s core unit is class, while AOP’s core unit is Aspect. Using AOP, the various parts of the business logic can be isolated, thus reducing the degree of coupling, improving the reusability of the program, and improving the development efficiency.

We can think of AOP simply as the operations that run through a method, before, during, after, after a return value, and after an exception.

Terms related to AOP

Consider the following diagram, which is an AOP model diagram in which common operations are performed before and after some method execution without affecting the execution of the program itself.

Let’s take a look at the five key terms involved with AOP:

1) Crosscutting concerns, the same class of non-core business extracted from each method

2) Aspect, a class that encapsulates crosscutting concerns, and each concern is represented as a notification method; The @aspect annotation is usually used to define aspects.

Advice. For example, if our log aspect needs to record the time before and after the interface is called, we need to record the time before and after the interface is called, and then take the difference. There are five ways of notification:

  • @before: The notification method is executed Before the target method is called
  • After: The notification method is executed After the target method is called
  • AfterReturning: Notification methods are executed after the target method returns
  • AfterThrowing: The notification method is executed after the target method throws an exception
  • Around: Wraps the entire target method and executes the notification method before and after the call

4) JoinPoint (JoinPoint), notify the application of the time, such as interface method is called when the log section is joined point.

5) Pointcut, which indicates the scope of application of the function. For example, the application scope of the log section is the interface of all controllers. The @pointcut annotation is usually used to define Pointcut expressions.

The syntax format specification for pointcut expressions is as follows:

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?
				name-pattern(param-pattern)
                throws-pattern?)
Copy the code
  • modifiers-pattern?Is the access permission modifier
  • ret-type-patternIs the return type, usually used*To represent any return type
  • declaring-type-pattern?As the package name
  • name-patternIs the method name and can be used*To represent all, orset*To represent all class names that begin with set
  • param-pattern)Is a parameter type. Multiple parameters can be used.Separate, each participant can also be used*To represent all types of parameters, you can also use(..)Represents zero or any parameters
  • throws-pattern?Is the exception type
  • ?Indicates that the preceding parameter is optional

Here’s an example:

@Pointcut("execution(public * com.codingmore.controller.*.*(..) )"
Copy the code

Said com. Codingmore. Controller under the package of all public methods to apply section of notice.

Three, practical operation AOP record interface access log

The first step is to add the Spring-boot-starter-AOP dependency to the POm. XML file of the Spring Boot project.

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

The second step is to add a WebLog, which is used to record the operation, the operator, the start time, the time spent, the path of the operation, the method name of the operation, the IP address of the operation host, the request parameters, and the return result.

/** * Created by macro on 2018/4/26. */
public class WebLog {
    private String description;
    private String username;
    private Long startTime;
    private Integer spendTime;
    private String basePath;
    private String uri;
    private String url;
    private String method;
    private String ip;
    private Object parameter;
    private Object result;
    // omit getter,setter methods
}
Copy the code

Third, add the unified logging aspect WebLogAspect.

/** * Created by */
@Aspect
@Component
@Order(1)
public class WebLogAspect {
    private static final Logger LOGGER = LoggerFactory.getLogger(WebLogAspect.class);

    @Pointcut("execution(public * com.codingmore.controller.*.*(..) )"
    public void webLog(a) {}@Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {}@AfterReturning(value = "webLog()", returning = "ret")
    public void doAfterReturning(Object ret) throws Throwable {}@Around("webLog()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        // Get the current request object
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // Record request information (pass Elasticsearch via Logstash)
        WebLog webLog = new WebLog();
        Object result = joinPoint.proceed();
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if (method.isAnnotationPresent(ApiOperation.class)) {
            ApiOperation log = method.getAnnotation(ApiOperation.class);
            webLog.setDescription(log.value());
        }
        long endTime = System.currentTimeMillis();
        String urlStr = request.getRequestURL().toString();
        webLog.setBasePath(StrUtil.removeSuffix(urlStr, URLUtil.url(urlStr).getPath()));
        webLog.setIp(request.getRemoteUser());
        Map<String,Object> logMap = new HashMap<>();
        logMap.put("spendTime",webLog.getSpendTime());
        logMap.put("description",webLog.getDescription());
        LOGGER.info("{}", JSONUtil.parse(webLog));
        returnresult; }}Copy the code

Step 4, run the project and test one of the controllers under Controller.

Swagger knife4j access address: http://localhost:9022/doc.html

Perform the login user query operation:You can see the following log information on the console:

Source code address:

Github.com/itwanger/co…

Reference links:

The author cxuan:www.cnblogs.com/cxuanBlog/p… Ash little ape: bbs.huaweicloud.com/blogs/28904… High mountain I for peak: www.cnblogs.com/liaojie970/… Macrozheng:github.com/macrozheng/…


This article has been published on GitHub’s 1.6K + Star. It is said that every good Java programmer likes her. It is humorous and easy to understand. The content includes Java foundation, Java concurrent programming, Java virtual machine, Java enterprise development, Java interview and other core knowledge points. Learn Java, look for Java programmers to advance the road 😄.

Github.com/itwanger/to…

Star the repository and you have the potential to become a good Java engineer. Click the link below to jump to the Java Programmer’s Path to Progress website and start your fun learning journey.

tobebetterjavaer.com/

Nothing keeps me here but purpose, and though there are roses by the shore, and trees by the shore, and still harbours, I am not tied.