美文网首页服务Spring boot框架建设收集
使用SpringBoot+AOP实现可插拔式日志

使用SpringBoot+AOP实现可插拔式日志

作者: Justin_Jun | 来源:发表于2019-04-10 22:01 被阅读429次

    一、AOP

    AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。 AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。

    二、实现

    引入依赖

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    

    新建SysLog类

    package com.example.aop.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface SysLog {
        String value() default " ";
    }
    

    新建SysLogAspect类

    package com.example.aop.annotation;
    
    import com.example.aop.service.LogService;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    
    @Aspect
    @Component
    public class SysLogAspect {
        @Autowired
        private LogService logService;
    
        @Pointcut("@annotation(com.example.aop.annotation.SysLog)")
        public void logPointCut() {}
    
        @Before("logPointCut()")
        public void before(JoinPoint joinPoint) {
            long beginTime = System.currentTimeMillis();
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            SysLog annotation = method.getAnnotation(SysLog.class);
            String value = annotation.value();
            Object[] args = joinPoint.getArgs();
            try {
                logService.log(beginTime, "before " + method.getName());
            } catch (Exception e) {
            }
        }
    
        @Around("logPointCut()")
        public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
            long beginTime = System.currentTimeMillis();
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            SysLog annotation = method.getAnnotation(SysLog.class);
            String value = annotation.value();
            Object[] args = joinPoint.getArgs();
            Object object = joinPoint.proceed(args);
            try {
                logService.log(beginTime, "around " + method.getName());
            } catch (Exception e) {
            }
            return object;
        }
    
        @After("logPointCut()")
        public void after(JoinPoint joinPoint) {
            long beginTime = System.currentTimeMillis();
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            SysLog annotation = method.getAnnotation(SysLog.class);
            String value = annotation.value();
            Object[] args = joinPoint.getArgs();
            try {
                logService.log(beginTime, "after " + method.getName());
            } catch (Exception e) {
            }
        }
    
        @AfterReturning("logPointCut()")
        public void afterReturning(JoinPoint joinPoint) {
            long beginTime = System.currentTimeMillis();
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            SysLog annotation = method.getAnnotation(SysLog.class);
            String value = annotation.value();
            Object[] args = joinPoint.getArgs();
            try {
                logService.log(beginTime, "after returning " + method.getName());
            } catch (Exception e) {
            }
        }
    
        @AfterThrowing("logPointCut()")
        public void afterThrowing(JoinPoint joinPoint) {
            long beginTime = System.currentTimeMillis();
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            SysLog annotation = method.getAnnotation(SysLog.class);
            String value = annotation.value();
            Object[] args = joinPoint.getArgs();
            try {
                logService.log(beginTime, "after throwing " + method.getName());
            } catch (Exception e) {
            }
        }
    }
    

    新建TestService类

    package com.example.aop.service;
    
    import com.example.aop.dto.TestDomain;
    import com.example.aop.annotation.SysLog;
    import org.springframework.stereotype.Service;
    
    @Service
    public class TestService {
        @SysLog("log-1")
        public void log1(String name, TestDomain testDomain) {
            System.out.println("print log 1" + name + " " + testDomain.toString());
        }
    
        @SysLog("log-2")
        public void log2(String name, TestDomain testDomain) {
            System.out.println("print log 2" + name + " " + testDomain.toString());
        }
    
    
        @SysLog("throw-exception")
        public void throwException() {
            System.out.println("throw exception");
            int i = 3/0;
        }
    }
    

    新建TestController

    package com.example.aop.controller;
    
    import com.example.aop.dto.TestDomain;
    import com.example.aop.service.TestService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class TestController {
        @Autowired
        private TestService testService;
    
        @GetMapping("test")
        public String test(@RequestParam("p1") String p1) {
            TestDomain testDomain = new TestDomain();
            testDomain.setId("1");
            testDomain.setTitle("t1");
            testService.log1(p1, testDomain);
            testService.log2(p1, testDomain);
            testService.throwException();
            return "hello aop";
        }
    }
    

    三、测试

    运行AopApplication, 然后访问http://localhost:8080/test?p1=123,可以看到控制台有以下输出:

    before log1 at: 1554903984403
    print log 1123 com.example.aop.dto.TestDomain@2a7a4cd5
    around log1 at: 1554903984402
    after log1 at: 1554903984409
    after returning log1 at: 1554903984409
    before log2 at: 1554903984409
    print log 2123 com.example.aop.dto.TestDomain@2a7a4cd5
    around log2 at: 1554903984409
    after log2 at: 1554903984410
    after returning log2 at: 1554903984410
    before throwException at: 1554903984410
    throw exception
    after throwException at: 1554903984410
    after throwing throwException at: 1554903984410
    

    github地址:https://github.com/lijun003/SpringBoot-AOP-log)https://github.com/lijun003/SpringBoot-AOP-log

    相关文章

      网友评论

        本文标题:使用SpringBoot+AOP实现可插拔式日志

        本文链接:https://www.haomeiwen.com/subject/lahaiqtx.html