自定义注解实现方法入参与出参的日志打印


声明:本文转载自https://my.oschina.net/xiaomingnevermind/blog/1619274,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

talk is cheap,show me the code.

代码目录结构:

-src  -main    -java    -resource  -test    -pom

pom.xml

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">     <modelVersion>4.0.0</modelVersion>      <groupId>com.example</groupId>     <artifactId>demo</artifactId>     <version>0.0.1-SNAPSHOT</version>     <packaging>jar</packaging>      <name>demo</name>     <description>Demo project for Spring Boot</description>      <parent>         <groupId>org.springframework.boot</groupId>         <artifactId>spring-boot-starter-parent</artifactId>         <version>1.5.6.RELEASE</version>         <relativePath/> <!-- lookup parent from repository -->     </parent>      <properties>         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>         <java.version>1.8</java.version>     </properties>      <dependencies>          <!-- aop dependency -->         <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-aop</artifactId>         </dependency>          <!-- web starter dependency -->         <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-web</artifactId>         </dependency>          <!-- spring boot start denpendency -->         <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-test</artifactId>             <scope>test</scope>         </dependency>          <!-- slf4j log dependency -->         <dependency>             <groupId>org.slf4j</groupId>             <artifactId>slf4j-api</artifactId>         </dependency>          <!-- json dependency -->         <dependency>             <groupId>com.alibaba</groupId>             <artifactId>fastjson</artifactId>             <version>LATEST</version>         </dependency>          <!-- test dependency -->         <dependency>             <groupId>org.mockito</groupId>             <artifactId>mockito-all</artifactId>             <version>LATEST</version>             <scope>test</scope>         </dependency>          <dependency>             <groupId>org.powermock</groupId>             <artifactId>powermock-core</artifactId>             <version>LATEST</version>             <scope>test</scope>         </dependency>          <dependency>             <groupId>org.powermock</groupId>             <artifactId>powermock-api-mockito</artifactId>             <version>LATEST</version>             <scope>test</scope>         </dependency>         <dependency>             <groupId>org.powermock</groupId>             <artifactId>powermock-module-testng</artifactId>             <version>1.7.0</version>             <scope>test</scope>         </dependency>     </dependencies>      <build>         <plugins>             <plugin>                 <groupId>org.springframework.boot</groupId>                 <artifactId>spring-boot-maven-plugin</artifactId>             </plugin>         </plugins>     </build>      <repositories>         <repository>             <id>spring-snapshots</id>             <name>Spring Snapshots</name>             <url>https://repo.spring.io/snapshot</url>             <snapshots>                 <enabled>true</enabled>             </snapshots>         </repository>         <repository>             <id>spring-milestones</id>             <name>Spring Milestones</name>             <url>https://repo.spring.io/milestone</url>             <snapshots>                 <enabled>false</enabled>             </snapshots>         </repository>     </repositories>      <pluginRepositories>         <pluginRepository>             <id>spring-snapshots</id>             <name>Spring Snapshots</name>             <url>https://repo.spring.io/snapshot</url>             <snapshots>                 <enabled>true</enabled>             </snapshots>         </pluginRepository>         <pluginRepository>             <id>spring-milestones</id>             <name>Spring Milestones</name>             <url>https://repo.spring.io/milestone</url>             <snapshots>                 <enabled>false</enabled>             </snapshots>         </pluginRepository>     </pluginRepositories>   </project> 

application.properties 写了,controller 配置了webroot路径和服务器端口。

server.contextPath=/test server.port=8080

自定义注解类 Log.java:

package com.example.demo.annotation;  import org.springframework.stereotype.Component;  import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;  /**  *  TYPE ->  Class, interface (including annotation type), or enum declaration  *  METHOD ->  Method declaration  */ @Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Log {      String value() default "";      boolean ignore() default false; } 

切面类,注解实现->LogAspect.java 。

package com.example.demo.impl;  import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.serializer.SerializerFeature; import com.example.demo.annotation.Log; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component;  import java.lang.reflect.Method;  /**  * Log 注解类实现  */ @Aspect @Order(100) @Component public class LogAspect {      public static final Logger log =  LoggerFactory.getLogger(LogAspect.class);     public static final String dateformat = "yyyy:MM:dd HH:mm:ss";     public static final String STIRNG_START = "\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<";     public static final String STIRNG_END = "\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>";     //execution the scan of pakage 切点package     @Pointcut("execution( * com.example.demo..*(..))")     public void serviceLog(){      }      @Around("serviceLog()")     public Object around(ProceedingJoinPoint joinPoint) { // ProceedingJoinPoint 为JoinPoint 的子类,在父类基础上多了proceed()方法,用于增强切面         try {             // 获取方法签名             MethodSignature signature = (MethodSignature) joinPoint.getSignature();             //java reflect相关类,通过反射得到注解             Method method = signature.getMethod();             Class<?> targetClass = method.getDeclaringClass();              StringBuffer classAndMethod = new StringBuffer();              //获取类注解Log             Log classAnnotation = targetClass.getAnnotation(Log.class);             //获取方法注解Log             Log methodAnnotation = method.getAnnotation(Log.class);              //如果类上Log注解不为空,则执行proceed()             if (classAnnotation != null) {                 if (classAnnotation.ignore()) {                     //proceed() 方法执行切面方法,并返回方法返回值                     return joinPoint.proceed();                 }                 classAndMethod.append(classAnnotation.value()).append("-");             }              //如果方法上Log注解不为空,则执行proceed()             if (methodAnnotation != null) {                 if (methodAnnotation.ignore()) {                     return joinPoint.proceed();                 }                 classAndMethod.append(methodAnnotation.value());             }              //拼凑目标类名和参数名             String target = targetClass.getName() + "#" + method.getName();             String params = JSONObject.toJSONStringWithDateFormat(joinPoint.getArgs(), dateformat, SerializerFeature.WriteMapNullValue);              log.info(STIRNG_START + "{} 开始调用--> {} 参数:{}", classAndMethod.toString(), target, params);              long start = System.currentTimeMillis();             //如果类名上和方法上都没有Log注解,则直接执行 proceed()             Object result = joinPoint.proceed();             long timeConsuming = System.currentTimeMillis() - start;              log.info("\n{} 调用结束<-- {} 返回值:{} 耗时:{}ms" + STIRNG_END, classAndMethod.toString(), target, JSONObject.toJSONStringWithDateFormat(result, dateformat, SerializerFeature.WriteMapNullValue), timeConsuming);             return result;         } catch (Throwable throwable) {             log.error(throwable.getMessage(), throwable);         }         return null;     } } 

接口类,测试@Log注解

package com.example.demo.service;  import com.example.demo.AspectBean; import com.example.demo.annotation.Log;  //@Log(value = "aspect test",ignore = true) @Log(value = "aspect test",ignore = false) public interface AspectService {  //    @Log("this is a method for test aspect.")     public AspectBean testAspect(AspectBean aspectBean) throws InterruptedException;      public boolean init();  } 

接口实现:

package com.example.demo.service;  import com.example.demo.AspectBean; import org.springframework.stereotype.Service;  import java.text.SimpleDateFormat; import java.util.Date;  @Service("aspectService") public class AspectServiceImpl implements AspectService {      @Override     public AspectBean testAspect(AspectBean aspectBean) throws InterruptedException {         // sleep 1 second         Thread.sleep(1000);         aspectBean.setName("update name");         aspectBean.setAge(20);         aspectBean.setSex(0);         aspectBean.setBirthday(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date().getTime()));         return aspectBean;     }      @Override     public boolean init() {         return false;     } } 

定义一个bean

package com.example.demo;  public class AspectBean {      private String name;     private int age;     private String birthday;     private int sex;      public String getName() {         return name;     }      public void setName(String name) {         this.name = name;     }      public int getAge() {         return age;     }      public void setAge(int age) {         this.age = age;     }      public String getBirthday() {         return birthday;     }      public void setBirthday(String birthday) {         this.birthday = birthday;     }      public int getSex() {         return sex;     }      public void setSex(int sex) {         this.sex = sex;     }      @Override     public String toString() {         return "AspectBean{" +                 "name='" + name + '\'' +                 ", age=" + age +                 ", birthday=" + birthday +                 ", sex=" + sex +                 '}';     } } 

controller:

package com.example.demo.controller;  import com.alibaba.fastjson.JSON; import com.example.demo.AspectBean; import com.example.demo.service.AspectService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;  import java.text.SimpleDateFormat; import java.util.Date;   @RestController @RequestMapping(value = "/aspect") public class AspectController {      private static final Logger log = LoggerFactory.getLogger(AspectController.class);      @Autowired     private AspectService aspectService;      @GetMapping(value = "/testaspect")     public String testAspect() throws InterruptedException {          AspectBean aspectBean = new AspectBean();         aspectBean.setAge(18);         aspectBean.setBirthday(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date().getTime()));         aspectBean.setSex(1);         aspectBean.setName("aspect");         return JSON.toJSONString(aspectService.testAspect(aspectBean));     }      @GetMapping(value = "/init")     public boolean init() {         return aspectService.init();     } } 

用的spring boot ,启动类

package com.example.demo;  import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;  @SpringBootApplication public class DemoApplication {  	public static void main(String[] args) { 		SpringApplication.run(DemoApplication.class, args); 	} } 

在浏览器上测试:

http://127.0.0.1:8080/test/aspect/testaspect

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 开始调用--> com.example.demo.controller.AspectController#testAspect 参数:[] 2018-02-06 19:26:57.003  INFO 239676 --- [nio-8080-exec-2] com.example.demo.impl.LogAspect          :  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<aspect test- 开始调用--> com.example.demo.service.AspectService#testAspect 参数:[{"age":18,"birthday":"2018-02-06 19:26:56","name":"aspect","sex":1}] 2018-02-06 19:26:58.003  INFO 239676 --- [nio-8080-exec-2] com.example.demo.impl.LogAspect          :  aspect test- 调用结束<-- com.example.demo.service.AspectService#testAspect 返回值:{"age":20,"birthday":"2018-02-06 19:26:58","name":"update name","sex":0} 耗时:1000ms >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 2018-02-06 19:26:58.003  INFO 239676 --- [nio-8080-exec-2] com.example.demo.impl.LogAspect          :   调用结束<-- com.example.demo.controller.AspectController#testAspect 返回值:"{\"age\":20,\"birthday\":\"2018-02-06 19:26:58\",\"name\":\"update name\",\"sex\":0}" 耗时:1041ms >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

源码稍后上传git.

idea 版本上传github有冲突,暂时没能解决,附上码云地址,文件 等待上传:

https://gitee.com/xiaomingnevermind/logaspect

本文发表于2018年02月07日 16:31
(c)注:本文转载自https://my.oschina.net/xiaomingnevermind/blog/1619274,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 2767 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1