文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

使用java注解和aspectj AOP怎么实现打印日志

2023-06-06 10:35

关注

本篇文章给大家分享的是有关使用java注解和aspectj AOP怎么实现打印日志,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

首先需要自定义注解:

systemName:表示该系统的名称。

bizCode:表示具体的方法描述

logtype:表示日志的格式类型

package myspring;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD})public @interface LogAnnotation { String systemName(); String bizCode(); LogType logtype() default LogType.TIME;}

2.定义日志格式枚举:

package myspring;public enum LogType { TIME("TIME", "方法调用时间"), PARAM("PARAM", "参数打印"); private String type; private String desc; LogType(String type, String desc) {  this.type = type;  this.desc = desc; } public String getType() {  return type; } public void setType(String type) {  this.type = type; } public String getDesc() {  return desc; } public void setDesc(String desc) {  this.desc = desc; }}

3.切面代码:

其中execution(* *(..))

第一个* :表示所有返回值

第二个* :表示所有包匹配规则和所有类匹配规则以及所有方法匹配规则

两个点.. :表示任何参数匹配

例如:

execution(* *..*Service.*(..))

表示任何返回值 任何包以Service结尾的类或者实现类的任何方法任何参数

*.. :表示所有包

* :Service表示所有以Service结尾的类或者实现类

execution(* cn.lijie.MyService.*(..))

表示任何返回值 cn.lijie包下面 MyService类或者实现类的所有方法 所有参数

代码如下:

package myspring;import com.alibaba.fastjson.JSON;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.reflect.MethodSignature;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;import org.springframework.util.StopWatch;import org.springframework.util.StringUtils;@Component@Aspectpublic class LogAspect { private static Logger thisLog = LoggerFactory.getLogger(LogAspect.class); private static Logger timeLog = LoggerFactory.getLogger(TimeTypeLog.class); private static Logger paramLog = LoggerFactory.getLogger(ParamTypeLog.class); @Around("execution(* *(..)) && @annotation(logAnnotation)") public Object log(ProceedingJoinPoint point, LogAnnotation logAnnotation) {  StopWatch stop = new StopWatch();  stop.start();  boolean flag = false;  Object retValue = null;  try {   retValue = point.proceed();   flag = true;  } catch (Throwable throwable) {   throwable.printStackTrace();  } finally {   stop.stop();   if (logAnnotation.logtype().equals(LogType.TIME)) {    timeLog(this.getMethod(point), point, stop.getTotalTimeMillis(), logAnnotation, flag);   } else {    paramLog(this.getMethod(point), point, retValue);   }  }  return retValue; } private void timeLog(String method, ProceedingJoinPoint point, long totalTimeMillis, LogAnnotation logAnnotation, boolean flag) {  timeLog.info("系统为:{},调用的方法名字:{},调用是否成功:{},运行时间为:{}ms", logAnnotation.systemName(), method, flag, totalTimeMillis); } private void paramLog(String method, ProceedingJoinPoint point, Object retValue) {  try {   String result = JSON.toJSONString(retValue);   //获取入参   Object[] args = point.getArgs();   StringBuffer sb = new StringBuffer();   for (Object obj : args) {    String str = JSON.toJSONString(obj);    sb.append(subStr(str, 200)).append(" ");   }   paramLog.info("调用方法为:{},入参为:{},出参为:{}", method, sb, subStr(result, 200));  } catch (Exception e) {   thisLog.warn("切面日志 参数日志打印异常,异常信息:{}", e.getMessage());  } } private String getMethod(ProceedingJoinPoint pjp) {  MethodSignature methodSignature = (MethodSignature) pjp.getSignature();  return methodSignature.getDeclaringTypeName() + "#" + methodSignature.getMethod().getName(); } private String subStr(String string, int length) {  if (!StringUtils.isEmpty(string)) {   if (string.length() > length) {    string = string.substring(0, 200);    return string;   }  }  return string; }}

4.定义一个操作对象:

package myspring;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;@Component("logTest")public class LogTest { private static Logger logger = LoggerFactory.getLogger(LogTest.class); @LogAnnotation(systemName = "计算器系统", bizCode = "+", logtype = LogType.TIME) public int testLog01(int a, int b) {  logger.info("进入+运算");  return a + b; } @LogAnnotation(systemName = "计算器系统", bizCode = "-", logtype = LogType.PARAM) public int testLog02(int a, int b) {  logger.info("进入-运算");  return a - b; }}

5.定义两个空类,用于区分不同类型的日志:

package myspring;public class TimeTypeLog {
package myspring;public class ParamTypeLog {}

6.spring xml配置文件:

<context:component-scan base-package="myspring"/><aop:aspectj-autoproxy/>

7.启动spring的测试类:

package myspring;import org.springframework.context.support.AbstractApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Main { public static void main(String[] args) {  AbstractApplicationContext context = new ClassPathXmlApplicationContext("application.xml");  LogTest logTest = (LogTest) context.getBean("logTest");  logTest.testLog01(1, 2);  logTest.testLog02(3, 4);  context.registerShutdownHook(); }}

8.pom

<properties>  <spring_version>4.3.8.RELEASE</spring_version> </properties> <dependencies>  <dependency>   <groupId>org.springframework</groupId>   <artifactId>spring-context</artifactId>   <version>${spring_version}</version>  </dependency>  <dependency>   <groupId>org.springframework</groupId>   <artifactId>spring-core</artifactId>   <version>${spring_version}</version>  </dependency>  <dependency>   <groupId>org.springframework</groupId>   <artifactId>spring-beans</artifactId>   <version>${spring_version}</version>  </dependency>  <dependency>   <groupId>org.springframework</groupId>   <artifactId>spring-aop</artifactId>   <version>${spring_version}</version>  </dependency>  <dependency>   <groupId>org.springframework</groupId>   <artifactId>spring-test</artifactId>   <version>${spring_version}</version>  </dependency>  <dependency>   <groupId>org.springframework</groupId>   <artifactId>spring-aop</artifactId>   <version>${spring_version}</version>  </dependency>  <dependency>   <groupId>org.aspectj</groupId>   <artifactId>aspectjrt</artifactId>   <version>1.8.11</version>  </dependency>  <dependency>   <groupId>org.aspectj</groupId>   <artifactId>aspectjweaver</artifactId>   <version>1.8.11</version>  </dependency>  <dependency>   <groupId>org.slf4j</groupId>   <artifactId>slf4j-api</artifactId>   <version>1.7.21</version>  </dependency>  <dependency>   <groupId>ch.qos.logback</groupId>   <artifactId>logback-classic</artifactId>   <version>1.1.7</version>  </dependency>  <dependency>   <groupId>ch.qos.logback</groupId>   <artifactId>logback-core</artifactId>   <version>1.1.7</version>  </dependency>  <dependency>   <groupId>com.alibaba</groupId>   <artifactId>fastjson</artifactId>   <version>1.2.4</version>  </dependency> </dependencies>

最后执行测试的类,日志打印如下:

使用java注解和aspectj AOP怎么实现打印日志

补充:spring boot 自定义注解实现自动打印方法日志(入参和返回值)

pom文件

<?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> <parent>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-parent</artifactId>  <version>2.1.4.RELEASE</version>  <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.aline</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <properties>  <java.version>1.8</java.version> </properties> <dependencies>  <dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-web</artifactId>  </dependency>  <dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-aop</artifactId>  </dependency>  <dependency>   <groupId>com.alibaba</groupId>   <artifactId>fastjson</artifactId>   <version>1.2.7</version>  </dependency>  <dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-test</artifactId>   <scope>test</scope>  </dependency> </dependencies> <build>  <plugins>   <plugin>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-maven-plugin</artifactId>   </plugin>  </plugins> </build></project>

定义一个日志注解

SysLog.java

package com.aline.demo.annotation;import java.lang.annotation.*;@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface SysLog {}

定义一个日志实例缓存

LoggerCache.classpackage com.aline.demo.util;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.util.HashMap;public class LoggerCache {  private static HashMap<String, Logger> LOGERS = new HashMap<String, Logger>();  public static Logger getLoggerByClassName(String className) {  // 从静态map中获取日志实例  Logger logger = LOGERS.get(className);  // 如果没取到  if (logger == null) {   // 创建一个日志实例   logger = LoggerFactory.getLogger(className);   // 加入到静态map中   LOGERS.put(className, logger);  }  // 返回  return logger; }}

定义一个切面实现日志记录

SysLogAspect.java

package com.aline.demo.aspect;import com.alibaba.fastjson.JSON;import com.aline.demo.util.LoggerCache;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.springframework.stereotype.Component;import java.lang.reflect.Method;@Aspect@Componentpublic class SysLogAspect { @Pointcut("@annotation(com.aline.demo.annotation.SysLog)") public void log() { }  @Around(value = "log()") public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {  // 获取执行方法的类的名称(包名加类名)  String className = joinPoint.getTarget().getClass().getName();  // 获取实例和方法  MethodSignature signature = (MethodSignature) joinPoint.getSignature();  Method method = signature.getMethod();  // 从缓存中获取日志实例  Logger log = LoggerCache.getLoggerByClassName(className);  // 记录日志  log.info(className + "." + method.getName() + "() 执行");  Object[] args = joinPoint.getArgs();  log.info("Params\t===》\t" + JSON.toJSONString(args));  // 执行方法获取返回值  Object proceed = joinPoint.proceed();  // 记录日志  log.info("Returns\t===》\t" + JSON.toJSONString(proceed));  // 返回  return proceed; } }

写个controller测试

TestController.java

package com.aline.demo.controller;import com.aline.demo.annotation.SysLog;import com.aline.demo.util.LoggerCache;import org.slf4j.Logger;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("/test")public class TestController { static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); @GetMapping("/now") public String now(){  // 从缓存中获取日志  Logger LOG = LoggerCache.getLoggerByClassName(this.getClass().getName());  LOG.info("自定义日志 ==》 日志内容。。。");  return sdf.format(new Date()); } @GetMapping("/hello") @SysLog() public String hello(String name){  return "Hello, " + name; }}

访问 http://localhost:8080/test/hello?name=aline

打印日志:

2019-05-09 16:58:20.410 INFO 40004 --- [nio-8080-exec-1] c.aline.demo.controller.TestController : com.aline.demo.controller.TestController.hello() 执行,参数 ==》2019-05-09 16:58:20.584 INFO 40004 --- [nio-8080-exec-1] c.aline.demo.controller.TestController : Params ===》 ["aline"]2019-05-09 16:58:20.598 INFO 40004 --- [nio-8080-exec-1] c.aline.demo.controller.TestController : Returns ===》 "Hello, aline"

访问 http://localhost:8080/now

打印日志:

2019-05-09 16:58:29.208 INFO 40004 --- [nio-8080-exec-3] c.aline.demo.controller.TestController : 自定义日志 ==》 日志内容。。。

以上就是使用java注解和aspectj AOP怎么实现打印日志,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯