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.*; ** @author: heyuhua * @date: 2021/1/28 15:32 */ @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() { return new LogAspect(); } @Bean public LogService logService() { return new LogServiceImpl(); }}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() default ""; } Duplicate codeCopy 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 {/** * 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; } /** * Pre-operation ** @param point * @param hyhLog * @return * @throws Throwable */ @before ("@annotation(hyhLog)") public Void before(JoinPoint Point, HyhLog HyhLog) throws Throwable {logService.info(" Perform the preceding operation..." + hyhLog.value()); // do something} /** * Post-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 codeCopy the code

Log Service Interface

package com.hyh.log.service; /** * @author: heyuhua * @date: 2021/1/28 15:37 */ 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); } Duplicate codeCopy 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; ** @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 codeCopy the code

Unit testing

OK, no nonsense, let’s go to the unit test and start using our annotations in the SpringBoot project

If 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() {
        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.

Source: www.tuicool.com/articles/FF…