SpringBoot Integrates AOP Recording Interface Access Logs

Posted by qbox on Fri, 13 Mar 2020 03:40:43 +0100

Reference resources:

SpringBoot Integration AOP


AOP is the abbreviation of Aspect Oriented Programming, which means: facet-oriented programming, a technology for unified maintenance of program functions through precompilation and run-time dynamic agents.With AOP, individual parts of business logic can be isolated, which reduces the coupling between parts of business logic, improves the reusability of programs, and improves the efficiency of development.

Terminology related to AOP


The notification describes the work to be done by the facet and when it will be executed.For example, if our log slice needs to record the length of each interface call, we need to record the current time before and after the interface call, and then take the difference.

  • Before: Call the notification function before the target method is called;
  • Post Notification: The notification function is invoked After the target method is invoked, regardless of the method's return result;
  • AfterReturning: Invoke notification function after successful execution of target method;
  • AfterThrowing: Invokes the notification function after the target method throws an exception;
  • Around notification: The notification wraps the target method and executes custom behavior before and after the target method call.


When notifications are applied, such as when an interface method is called, is the connection point to the log slice


The tangent points define the scope within which the notification function is applied.For example, log facets can be applied to all interfaces, which are the interface methods of all controller s.


Aspects are a combination of notifications and tangent points that define when and where notifications should be applied


Add a new method or property to an existing class without modifying it.


The process of applying facets to the target object and creating a new proxy object.

Creating facets using annotations in Spring

Relevant Notes

  • @Aspect: Used to define facets
  • @Before: The notification method executes before the target method call
  • @After: The notification method executes after the target method returns or throws an exception
  • @AfterReturning: The notification method will execute after the target method returns
  • @AfterThrowing: The notification method executes after the target method throws an exception
  • @Around: The notification method encapsulates the target method
  • @Pointcut: Define the tangent expression

Tangent expression

Specifies the scope in which the notification will be applied, and the expression format:

Execution (package to which a method modifier returns a type method. class name. method name (method parameter)
//The public methods of all classes in the com.macro.mall.tiny.controller package apply the notifications in the facets
execution(public * com.macro.mall.tiny.controller.*.*(..))
//Notifications in facets apply to all methods in all classes under the com.macro.mall.tiny.service package and its subpackages
execution(* com.macro.mall.tiny.service..*.*(..))
//Notifications in facets apply to all methods in the com.macro.mall.tiny.service.PmsBrandService class
execution(* com.macro.mall.tiny.service.PmsBrandService.*(..))


Add Log Information Encapsulation Class WebLog

Used to encapsulate log information that needs to be logged, including descriptions of operations, time consumed, url s, request parameters, and return results.

package com.macro.mall.tiny.dto;

 * Controller Layer's Log Encapsulation Class
 * Created by macro on 2018/4/26.
public class WebLog {
     * Pedagogical operation
    private String description;

     * Operating Users
    private String username;

     * Operation time
    private Long startTime;

     * Time consumed
    private Integer spendTime;

     * Root Path
    private String basePath;

     * URI
    private String uri;

     * URL
    private String url;

     * Request Type
    private String method;

     * IP address
    private String ip;

     * Request parameters
    private Object parameter;

     * Return of Request
    private Object result;

    //getter,setter method omitted

Add Face Class WebLogAspect

A log facet is defined to get the information needed for the log in a surround notification and apply to all public methods in the controller layer.

  * Unified Log Processing Face
  * @author yisheng.mikelv@foxmail.com 2020/3/12 17:22
public class WebLogAspect {

    private static final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);

    @Pointcut("execution(public * org.developer.es.api.controller.*.*(..))")
    public void webLog(){


    public void doBefore(JoinPoint joinPoint) throws Throwable{


    @AfterReturning(value = "webLog()", returning = "ret")
    public void doAfterReturning(Object ret) throws Throwable{


    //Wrap Notification=Pre+Target Method Execution+Post Notification
    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
        WebLog webLog = new WebLog();
        //The proceed method is used to initiate the target method execution
        Object result = joinPoint.proceed();
        //Get Called Signature
        Signature signature = joinPoint.getSignature();
        //Convert to method signature
        MethodSignature methodSignature = (MethodSignature) signature;
        //Methods to get controller s
        Method method = methodSignature.getMethod();
        //If there is an ApiOperation annotation, get the value of the description
            ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
        long endTime = System.currentTimeMillis();
        String urlStr = request.getRequestURL().toString();
        webLog.setBasePath(StrUtil.removeSuffix(urlStr, URLUtil.url(urlStr).getPath()));
        webLog.setParameter(getParameter(method, joinPoint.getArgs()));
        webLog.setSpendTime((int) (endTime - startTime));
        logger.info("{} \n", JSONUtil.parse(webLog));
        return result;


     * Get request parameters based on method and parameters passed in
    private Object getParameter(Method method, Object[] args) {
        List<Object> argList = new ArrayList<>();
        //Get the parameters of the method
        Parameter[] parameters = method.getParameters();
        for (int i = 0; i < parameters.length; i++) {
            //Use RequestBody comment-modified parameters as request parameters
            RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);
            if(requestBody != null){
            //RequestParam annotated parameters as request parameters
            RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);
            if (requestParam != null) {
                Map<String, Object> map = new HashMap<>();
                String key = parameters[i].getName();
                if (!StringUtils.isEmpty(requestParam.value())) {
                    key = requestParam.value();
                map.put(key, args[i]);

        if (argList.size() == 0) {
            return null;
        } else if (argList.size() == 1) {
            return argList.get(0);
        } else {
            return argList;

Run result:


SpringBoot officially recommends logback-spring.xml

logback.xml: When an application is started, it is recognized directly by the log framework logback and used without going through SpringBoot

logback-spring.xml:The logback logging framework is not directly recognized, and the log configuration file is parsed by Spring Boot

SpringBoot loads logback-spring.xml

Reference resources:

logback profile loading process in Spring Boot

// org.springframework.boot.logging.logback.LogbackLoggingSystem
protected String[] getStandardConfigLocations() {
    return new String[] { "logback-test.groovy", "logback-test.xml", "logback.groovy",
                         "logback.xml" };

Here you can see that the logback configuration file format supported in spring boot is to add'-spring'after the file name based on the logback-test.xml (logback-test.xml, logback.xml, etc.), such as logback-test-spring, logback-spring, etc.

 * Return the spring config locations for this system. By default this method returns
 * a set of locations based on {@link #getStandardConfigLocations()}.
 * @return the spring config locations
 * @see #getSpringInitializationConfig()
protected String[] getSpringConfigLocations() {
    String[] locations = getStandardConfigLocations();
    for (int i = 0; i < locations.length; i++) {
        String extension = StringUtils.getFilenameExtension(locations[i]);
        locations[i] = locations[i].substring(0,
                                              locations[i].length() - extension.length() - 1) + "-spring."
            + extension;
    return locations;

Focus on the org.springframework.boot.logging.logback.LogbackLoggingSystem

Two original articles have been published. Approved 0. Visits 17
Private letter follow

Topics: Spring xml SpringBoot Programming