Tip: there is the source code address below, please take it yourself


preface

Do you still get the log object directly in the class and call the method to print the log? How to implement a logging feature elegantly using AOP+ custom annotations


Tip: The following is the main content of this article, the case is for reference only

I. Technical introduction

What is AOP?

In the software industry, AOP for the abbreviation of Aspect Oriented Programming, meaning: section-oriented Programming, through pre-compilation and runtime dynamic proxy to achieve unified maintenance of program functions of a technology. AOP is a continuation of OOP, a hot topic in software development, and an important content in Spring framework. It is a derivative paradigm of functional programming. Using AOP, each part of the business logic can be isolated, thus reducing the degree of coupling between each part of the business logic, improving the reusability of the program, and improving the efficiency of development. — from Baidu Baike

Two, start to use

1. Code directory structure

2. Start coding

POM.xml

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

Let’s use SpringBoot to write an on demand annotation, write an on demand annotation

package com.hyh.log.annotation;

import com.hyh.log.config.HyhLogAutoConfiguration;
import org.springframework.context.annotation.Import;

import java.lang.annotation.*;

/** * Enable log annotation **@Author: heyuhua
 * @Date: 2021/1/28 who neglects * /
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import({HyhLogAutoConfiguration.class})
public @interface EnableHyhLog {
}

Copy the code

Auto-configuration class

package com.hyh.log.config;

import com.hyh.log.aspect.LogAspect;
import com.hyh.log.service.LogService;
import com.hyh.log.service.impl.LogServiceImpl;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Log AutoConfiguration
 *
 * @Author: heyuhua
 * @Date: 2021/1/28 16:02 * /
@ConditionalOnWebApplication
@Configuration(proxyBeanMethods = false)
public class HyhLogAutoConfiguration {

    @Bean
    public LogAspect logAspect(a) {
        return new LogAspect();
    }

    @Bean
    public LogService logService(a) {
        return newLogServiceImpl(); }}Copy the code

Custom log annotations

package com.hyh.log.annotation;

import java.lang.annotation.*;

/** ** *@Author: heyuhua
 * @Date: 2021/1/28 16:02 * /
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface HyhLog {

    /** * description **@return* /
    String value(a) default "";
}

Copy the code

Log section code

package com.hyh.log.aspect;

import com.hyh.log.annotation.HyhLog;
import com.hyh.log.service.LogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

import javax.annotation.Resource;

/**
 * Log Aspect
 *
 * @Author: heyuhua
 * @Date: 2021/1/28 16:02 * /
@Aspect
public class LogAspect {


    /** * Log service */
    @Resource
    private LogService logService;

    /** * surround operation **@param point
     * @param hyhLog
     * @return
     * @throws Throwable
     */
    @Around("@annotation(hyhLog)")
    public Object around(ProceedingJoinPoint point, HyhLog hyhLog) throws Throwable {
        String className = point.getTarget().getClass().getName();
        String methodName = point.getSignature().getName();
        logService.info([class] :{}, [method] :{}", className, methodName);
        Object obj = point.proceed();
        // do something
        return obj;
    }

    /** ** ** *@param point
     * @param hyhLog
     * @return
     * @throws Throwable
     */
    @Before("@annotation(hyhLog)")
    public void before(JoinPoint point, HyhLog hyhLog) throws Throwable {
        logService.info("Perform the front operation..." + hyhLog.value());
        // do something
    }

    /** ** after operation **@param point
     * @param hyhLog
     * @return
     * @throws Throwable
     */
    @After("@annotation(hyhLog)")
    public void after(JoinPoint point, HyhLog hyhLog) throws Throwable {
        logService.info("Perform post-operation..." + hyhLog.value());
        // do something}}Copy the code

Log Service Interface

package com.hyh.log.service;

/** * Log interface **@Author: heyuhua
 * @Date: 2021/1/28 and * /
public interface LogService {

    /**
     * info
     *
     * @param msg
     */
    void info(String msg);

    /**
     * info
     *
     * @param msg
     * @param o
     */
    void info(String msg, Object o);

    /**
     * info
     *
     * @param msg
     * @param throwable
     */
    void info(String msg, Throwable throwable);

    /**
     * info
     *
     * @param msg
     * @param o
     */
    void info(String msg, Object... o);

    /**
     * info
     *
     * @param msg
     * @param o
     * @param throwable
     */
    void info(String msg, Object o, Throwable throwable);

    /**
     * error
     *
     * @param msg
     */
    void error(String msg);

    /**
     * error
     *
     * @param msg
     * @param o
     */
    void error(String msg, Object o);

    /**
     * error
     *
     * @param msg
     * @param throwable
     */
    void error(String msg, Throwable throwable);

    /**
     * error
     *
     * @param msg
     * @param o
     * @param throwable
     */
    void error(String msg, Object o, Throwable throwable);


}

Copy the code

Log service interface implementation

package com.hyh.log.service.impl;

import com.hyh.log.service.LogService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

/** * log service interface implementation **@Author: heyuhua
 * @Date: 2021/1/28 17:04 * /
@Service
public class LogServiceImpl implements LogService {


    /** * log */
    private static final Logger LOGGER = LoggerFactory.getLogger(LogServiceImpl.class);

    @Override
    public void info(String msg) {
        LOGGER.info(msg);
    }

    @Override
    public void info(String msg, Object o) {
        LOGGER.info(msg, o);
    }

    @Override
    public void info(String msg, Throwable throwable) {
        LOGGER.info(msg, throwable);
    }

    @Override
    public void info(String msg, Object... o) {
        LOGGER.info(msg, o);
    }

    @Override
    public void info(String msg, Object o, Throwable throwable) {
        LOGGER.info(msg, o, throwable);
    }

    @Override
    public void error(String msg) {
        LOGGER.error(msg);
    }

    @Override
    public void error(String msg, Object o) {
        LOGGER.error(msg, o);
    }

    @Override
    public void error(String msg, Throwable throwable) {
        LOGGER.error(msg, throwable);
    }

    @Override
    public void error(String msg, Object o, Throwable throwable) { LOGGER.error(msg, o, throwable); }}Copy the code

Unit testing

OK, no nonsense, let’s go to the unit test and start using our annotations in the SpringBoot projectIf you look in the red box, we write an on-demand import annotation, and then the Controller layer writes an interface that uses HyhLog annotations

	@HyhLog(value = "hello world test")
    @RequestMapping(value = "hello", method = RequestMethod.GET)
    public String hello(a) {
        return "hello";
    }

Copy the code

Visit the Hello interface to see the result

conclusion

AOP can implement many functions based on dynamic proxy, such as permission control, logging, transaction commit and rollback, etc. a series of operations, through non-invasive way to achieve business decoupling, function enhancement, let us use the most elegant code to achieve the most complex functions.

The author remarks

I see a long way to go, I’m willing to work with you. Thank you very much for your likes, favorites and comments. See you next time.

Source code: click here to view the source code.