springboot实现基于aop的切面日志

本文实例为大家分享了springboot实现基于aop的切面日志的具体代码,供大家参考,具体内容如下

通过aop的切面方式实现日志

通切面拦截所有指定包下的所有方法

@Aspect
@Component
@EnableAspectJAutoProxy
public class LogAspect1{
    Logger logger = LoggerFactory.getLogger(LogAspect.class);

    
/**
 * 拦截切点
 */

    @Pointcut("execution(*xx.xx.controller.*.*(..))")
    private void logPointCut() {
        logger.info("进入注解拦截");

    }

    //前置通知,在方法之前通知
    @Before(value = "logPointCut()")
    public void before(JoinPoint jp) {
        logger.info("方法调用前:" + "类名:" + jp.getTarget().getClass().getName() + "方法名 :" + jp.getSignature().getName());
    }

    //后置通知
    @After(value = "logPointCut()")
    public void doAfter(JoinPoint jp) {
        logger.info("方法调用结束:" + "类名:" + jp.getTarget().getClass().getName() + "方法名 :" + jp.getSignature().getName());
    }

    //环绕通知
    @Around("logPointCut()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        logger.info("方法开始调用》》》》》》");

        Object retVal = pjp.proceed();
        logger.info("方法调用结束》》》》》》");
        return retVal;
    }

    //返回通知
    @AfterReturning(pointcut = "logPointCut()")
    public void doAfterReturning(JoinPoint jp) {
        logger.info("写入日志");

    }

    //异常通知
    @AfterThrowing(pointcut = "logPointCut()", throwing = "ex")
    public void doAfterThrowing(JoinPoint jp, Throwable ex) {
        logger.info("方法异常,异常信息:" + ex.getMessage());
    }
}

拦截自定义注解

定义一个日志注解,在所有要需要记录的方法上加盖注解即可被后续的aop拦截处理

代码如下

@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {

    /**
     * 日志主题
     */
    public String title() default "";

    /**
     * 操作具体业务
     */
    public String business() default "";

    /**
     * 是否保留请求参数
     */
    public boolean isSaveRequestData() default false;
    /**
    * 日志的类别,主要用于日志的分开记录和查询
    **/
LogType logType() default LogType.LOGIN;
}

拦截切面的实现

@Aspect
@Component
@EnableAspectJAutoProxy
public class LogAspect {
    Logger logger = LoggerFactory.getLogger(LogAspect.class);
    @Autowired
    private ServiceDemo serviceDemo;

    /**
     * 拦截切点
     */

    @Pointcut("@annotation(moling.evolution.demo.aop.annotation.Log)")
    private void logPointCut() {
      

    }

    //前置通知,在方法之前通知
    @Before(value = "logPointCut()")
    public void before(JoinPoint jp) {
        logger.info("方法调用前:" + "类名:" + jp.getTarget().getClass().getName() + "方法名 :" + jp.getSignature().getName());
    }

    //后置通知
    @After(value = "logPointCut()")
    public void doAfter(JoinPoint jp) {
        logger.info("方法参数:{}", jp.getArgs());
        logger.info("  {} || {}", jp.getStaticPart().getId(), jp.getStaticPart().getSourceLocation());
        jp.getStaticPart().getId();

        logger.info("方法调用结束:" + "类名:" + jp.getTarget().getClass().getName() + "方法名 :" + jp.getSignature().getName());
    }

    //环绕通知
    @Around("logPointCut()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        logger.info("方法开始调用》》》》》》");

        Object retVal = pjp.proceed();
        logger.info("方法调用结束》》》》》》");
        return retVal;
    }

    //返回通知
    @AfterReturning(pointcut = "logPointCut()", returning = "object")
    public void doAfterReturning(JoinPoint jp, Object object) {
        System.out.println("返回通知");
        Log log = null;
        try {
            log = getAnnotationLog(jp);
        } catch (Exception e) {
            e.printStackTrace();

        }
        System.out.println(object);
        System.out.println(log);
        if (log != null) {
            logger.info(log.title());
            logger.info(log.business());
            logger.info(log.user());
            logger.info(log.isSaveRequestData() + "");
        } else {
            logger.error("获取注解信息失败");
        }
        serviceDemo.demo();

    }

    //异常通知
    @AfterThrowing(pointcut = "logPointCut()", throwing = "ex")
    public void doAfterThrowing(JoinPoint jp, Throwable ex) {
        logger.info("方法异常,异常信息:" + ex.getMessage());
        serviceDemo.error();
    }

    /**
     * 是否存在注解,如果存在就获取
     */

    private Log getAnnotationLog(JoinPoint joinPoint) throws Exception {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if (method != null) {
            return method.getAnnotation(Log.class);
        }
        return null;
    }
}

基于事件通知实现日志的记录

  • 拦截切面的实现
@Aspect
@Component
@EnableAspectJAutoProxy
public class LogAspectContext {

    Logger logger = LoggerFactory.getLogger(LogAspectContext.class);
    @Autowired
    private ApplicationContext applicationContext;

    /**
     * 拦截切点
     */
    @Pointcut("@annotation(moling.evolution.demo.aop.annotation.Log)")
    private void logPointCut() {
        logger.info("进入注解拦截");

    }

    //返回通知
    @AfterReturning(pointcut = "logPointCut()", returning = "object")
    public void doAfterReturning(JoinPoint jp, Object object) throws Exception {
        applicationContext.publishEvent(new LogSuccessEvent(jp, null));

    }

    //异常通知
    @AfterThrowing(pointcut = "logPointCut()", throwing = "ex")
    public void doAfterThrowing(JoinPoint jp, Throwable ex) {
        logger.info("方法异常,异常信息:" + ex.getMessage());
        applicationContext.publishEvent(new LogSuccessEvent(jp, ex));
    }

    /**
     * 是否存在注解,如果存在就获取
     */
    private Log getAnnotationLog(JoinPoint joinPoint) throws Exception {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if (method != null) {
            return method.getAnnotation(Log.class);
        }
        return null;
    }
}
@Slf4j
@Service
public class ApplicationListener implements org.springframework.context.ApplicationListener<LogSuccessEvent> {

    @Autowired
    private ServiceDemo demo;

    @Override
    public void onApplicationEvent(LogSuccessEvent event) {
        JoinPoint joinPoint = event.getJp();
        Throwable ex = event.getThrowable();
        if (ex == null) {
            demo.demo();
        } else {
            demo.error();
        }
    }

}
@Slf4j
public class LogSuccessEvent extends ApplicationEvent {
    /**
     * Create a new ApplicationEvent.
     *
     * @param source the component that published the event (never {@code null})
     */
    private JoinPoint jp;

    private Throwable throwable;

    public LogSuccessEvent(Object source, Throwable throwable) {
        super(source);
        this.throwable = throwable;
        this.jp = (JoinPoint) source;
//        Log logger = (Log) source;
//        log.info(logger.title());
//        log.info(logger.business());
//        log.info(logger.user());
//       log.info(logger.isSaveRequestData() + "");

    }

    public JoinPoint getJp() {
        return jp;
    }

    public Throwable getThrowable() {
        return throwable;
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 使用SpringBoot+AOP实现可插拔式日志的示例代码

    一.AOP AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型. 二.实现 引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot

  • Springboot使用@Valid 和AOP做参数校验及日志输出问题

    项目背景 最近在项目上对接前端的的时候遇到了几个问题 1.经常要问前端要请求参数 2.要根据请求参数写大量if...else,代码散步在 Controller 中,影响代码质量 3.为了解决问题1,到处记日志,导致到处改代码 解决方案 为了解决这类问题,我使用了@Valid 做参数校验,并使用AOP记录前端请求日志 1.Bean实体类增加注解 对要校验的实体类增加注解,如果实体类中有List结构,就在List上加@Valid @Valid注解 注解 备注 @Null 只能为null @NotNu

  • Springboot接口项目如何使用AOP记录日志

    一. 背景 一直想给项目构建一个统一的日志收集系统,先迈出第一步,构建一个日志收集类,用AOP实现无侵入日志收集 二. 环境 1.此随笔内容基于spring boot项目 2.数据库为mysql 5.7.9版本 3.jdk 版本为1.8 三. 说明 此版采用数据库存储,之后考虑使用elasticsearch等工具存储 四. 内容 1.构建日志采集实体类:BaseLogMessage public class BaseLogMessage { private String serverIP; pr

  • 详解基于SpringBoot使用AOP技术实现操作日志管理

    操作日志对于程序员或管理员而言,可以快速定位到系统中相关的操作,而对于操作日志的管理的实现不能对正常业务实现进行影响,否则即不满足单一原则,也会导致后续代码维护困难,因此我们考虑使用AOP切面技术来实现对日志管理的实现. 文章大致内容: 1.基本概念 2.基本应用 3.日志管理实战 对这几部分理解了,会对AOP的应用应该很轻松. 一.基本概念 项目 描述 Aspect(切面) 跨越多个类的关注点的模块化,切面是通知和切点的结合.通知和切点共同定义了切面的全部内容--它是什么,在何时和何处完成其功

  • SpringBoot AOP处理请求日志打印功能代码实例

    设计原则和思路: 元注解方式结合AOP,灵活记录操作日志 能够记录详细错误日志为运营以及审计提供支持 日志记录尽可能减少性能影响 操作描述参数支持动态获取,其他参数自动记录. 代码实例如下 @Slf4j @Aspect @Configuration public class RequestAopConfig { @Autowired private HttpServletRequest request; private static final ThreadLocal<Long> START_

  • 解析springboot集成AOP实现日志输出的方法

    开发接口系统中主要的一环就是日志输出,如果系统出现问题,日志能帮我们去定位问题,最常见的日志是调用方 所调用的IP 接口地址 对应方法 参数值 以及接口方接收到请求 所返回的参数.如果这需要在每一个controller层去写的话代码过于重复,于是就使用AOP定义切面 对其接口调用前后进行拦截日志输出. 1.加入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spr

  • springboot配置aop切面日志打印过程解析

    这篇文章主要介绍了springboot配置aop切面日志打印过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.SpringBoot Aop说明 1. Aop AOP(Aspect-Oriented Programming,面向切面编程),它利用一种"横切"的技术,将那些多个类的共同行为封装到一个可重用的模块.便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性. 2. AOP相关概念: Aspect

  • SpringBoot中使用AOP打印接口日志的方法

    前言 AOP 是 Aspect Oriented Program (面向切面)的编程的缩写.他是和面向对象编程相对的一个概念.在面向对象的编程中,我们倾向于采用封装.继承.多态等概念,将一个个的功能在对象中来实现.但是,我们在实际情况中也发现,会有另外一种需求就是一类功能在很多对象的很多方法中都有需要.例如有一些对数据库访问的方法有事务管理的需求,有很多方法中要求打印日志.按照面向对象的方式,那么这些相同的功能要在很多地方来实现或者在很多地方来调用.这就非常繁琐并且和这些和业务不相关的需求耦合太

  • Springboot2 配置AOP日志的方法步骤

    Spring boot2 配置AOP前置增强,后置增强,异常增强,环绕增强,最终增强 关于AOP切面相关具体概念不做过多阐述(概念弄懂有利于理解思想),这是配置AOP的各种增强日志,解决日志嵌套在业务代码的麻烦和不科学 先来个Git demo项目压压惊: https://github.com/zhang-xiao-xiang/boot-aop  (有的更新了一些) 1pom依赖(这里使用log4j2作为日志框架,因为比log4j或者其他日志框架,它效率更高,功能更加强大) <!-- 引入log4

  • 在springboot中使用AOP进行全局日志记录

    目录 前言 1. spring AOP 是什么? 2.spring AOP 能做什么? 3.spring AOP 我能用 AOP 解决什么问题? 一.引入依赖,增加自定义注解 1.引入 maven 依赖 2.增加自定义注解 OperationLog 二.为自定义注解编写切面实现 三.使用自定义日志注解 前言 此前项目上需要对用户的操作进行日志记录,以便后续追踪问题,所以就学习了使用 spring AOP 来进行日志记录. 1. spring AOP 是什么? spring 的两大核心就是 IOC

随机推荐