`

springboot aop

阅读更多

在springboot中使用aop

1、加入pom

<dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

 2、定义aop切面类

/**
 * ClassName:MetricsAop <br/>
 * @author   shijun@richinfo.cn
 * @version  
 * @see 	 
 */
@Component
@Aspect
public class MetricsAop {
    
    //匹配com.richinfo.sipop.web.account.controller包及其子包下的所有类的所有方法  ,以及含有注解的MetricAnnotation的方法
    @Pointcut("execution(* com.richinfo.sipop.web.account.controller..*.*(..)) ")  
    public void executeService(){  
      
    }  
    
    @Before(value="executeService()")  
    public void doBeforeAdvice(JoinPoint joinPoint){  
        System.out.println("我是前置通知!!!");  
        //获取目标方法的参数信息  
        Object[] obj = joinPoint.getArgs();  
        System.out.println(JSON.toJSONString(obj));
        //AOP代理类的信息  
        System.out.println(joinPoint.getThis().getClass().getSimpleName());  
        //代理的目标对象  
        System.out.println(joinPoint.getTarget().getClass().getSimpleName());  
        //用的最多 通知的签名  
        Signature signature = joinPoint.getSignature();  
        //代理的是哪一个方法  
        System.out.println(signature.getName());  
        //AOP代理类的名字  
        System.out.println(signature.getDeclaringTypeName());  
        //AOP代理类的类(class)信息  
        System.out.println("class::::"+signature.getDeclaringType());  
        //获取RequestAttributes  
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();  
        //从获取RequestAttributes中获取HttpServletRequest的信息  
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);  
        Enumeration<String> enumeration = request.getParameterNames();  
        Map<String,String> parameterMap = Maps.newHashMap();  
        while (enumeration.hasMoreElements()){  
            String parameter = enumeration.nextElement();  
            parameterMap.put(parameter,request.getParameter(parameter));  
        }  
        String str = JSON.toJSONString(parameterMap);  
        if(obj.length > 0) {  
            System.out.println("请求的参数信息为:"+str);  
        }  
    }  
    
    /** 
     * 后置返回通知 
     * 这里需要注意的是: 
     *      如果参数中的第一个参数为JoinPoint,则第二个参数为返回值的信息 
     *      如果参数中的第一个参数不为JoinPoint,则第一个参数为returning中对应的参数 
     * returning 限定了只有目标方法返回值与通知方法相应参数类型时才能执行后置返回通知,否则不执行,对于returning对应的通知方法参数为Object类型将匹配任何目标返回值 
     * @param joinPoint 
     * @param keys 
     */  
    @AfterReturning(value="executeService()",returning = "keys")  
    public void doAfterReturningAdvice1(JoinPoint joinPoint,Object keys){  
      
        System.out.println("第一个后置返回通知的返回值:"+keys);  
    }  
      
    @AfterReturning(value="executeService()",returning = "keys",argNames = "keys")  
    public void doAfterReturningAdvice2(String keys){  
      
        System.out.println("第二个后置返回通知的返回值:"+keys);  
    }  
    
    /** 
     * 后置异常通知 
     *  定义一个名字,该名字用于匹配通知实现方法的一个参数名,当目标方法抛出异常返回后,将把目标方法抛出的异常传给通知方法; 
     *  throwing 限定了只有目标方法抛出的异常与通知方法相应参数异常类型时才能执行后置异常通知,否则不执行, 
     *      对于throwing对应的通知方法参数为Throwable类型将匹配任何异常。 
     * @param joinPoint 
     * @param exception 
     */  
    @AfterThrowing(value = "executeService()",throwing = "exception")  
    public void doAfterThrowingAdvice(JoinPoint joinPoint,Throwable exception){  
        //目标方法名:  
        System.out.println(joinPoint.getSignature().getName());  
        if(exception instanceof NullPointerException){  
            System.out.println("发生了空指针异常!!!!!");  
        }  
    }  
    
    /** 
     * 后置最终通知(目标方法只要执行完了就会执行后置通知方法) 
     * @param joinPoint 
     */  
    @After(value="executeService()")  
    public void doAfterAdvice(JoinPoint joinPoint){  
      
        System.out.println("后置通知执行了!!!!");  
    } 
    
    /** 
     * 环绕通知: 
     *   环绕通知非常强大,可以决定目标方法是否执行,什么时候执行,执行时是否需要替换方法参数,执行完毕是否需要替换返回值。 
     *   环绕通知第一个参数必须是org.aspectj.lang.ProceedingJoinPoint类型 
     */  
    @Around(value="executeService()")  
    public Object doAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){  
        System.out.println("环绕通知的目标方法名:"+proceedingJoinPoint.getSignature().getName());  
        try {
            Object obj = proceedingJoinPoint.proceed();  
            return obj;  
        } catch (Throwable throwable) {  
            throwable.printStackTrace();  
        }  
        return null;  
    } 
}

 3、切入有注解如MetricAnnotation的方法,并获取注解,如下

//切入controller类中使用MetricAnnotation注解的方法
    @Before("@annotation(metricAnnotation)")
    public void doBeforeAdvice(JoinPoint joinPoint, MetricAnnotation metricAnnotation){
//获取request中的参数
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = (HttpServletRequest) requestAttributes
                .resolveReference(RequestAttributes.REFERENCE_REQUEST);

        // 从@PathVariables中获取
        Map<String, Object> pathVariables = (Map<String, Object>) request
                .getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);

        String id = String.valueOf(pathVariables.get(metricAnnotation.paramField()));
        if (StringUtils.isBlank(id)) {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("URI路径{},@PathVariables无参数{}的值", request.getRequestURI(), metricAnnotation.paramField());
            }
            // 从@RequestParam中获取
            id = request.getParameter(paramField);
        }

       //。。。
}

 

4、切入点表达式

  定义切入点需要一个包含名字和任意参数的签名,还有一个切入点表达式,就是* com.sjz.web.account.controller..*.*(..) 这一部分。 

  切入点表达式的格式:execution([可见性] 返回类型 [声明类型].方法名(参数) [异常])

  其中【】中的为可选,其他的还支持通配符的使用:

    *:匹配所有字符

      ..:一般用于匹配多个包,多个参数

      +:表示类及其子类

 

  运算符有:&&、||、!

 

切入点表达式关键词:   

    1)execution:用于匹配子表达式。

            //匹配com.sjz.model包及其子包中所有类中的所有方法,返回类型任意,方法参数任意

            @Pointcut("execution(* com.sjz.model..*.*(..))")

            public void before(){}

 

      2)within:用于匹配连接点所在的Java类或者包。

            //匹配Person类中的所有方法

            @Pointcut("within(com.sjz.model.Person)")

            public void before(){} 

 

            //匹配com.sjz包及其子包中所有类中的所有方法

            @Pointcut("within(com.sjz..*)")

            public void before(){} 

 

     3) this:用于向通知方法中传入代理对象的引用。

            @Before("before() && this(proxy)")

            public void beforeAdvide(JoinPoint point, Object proxy){

                  //处理逻辑

            } 

 

      4)target:用于向通知方法中传入目标对象的引用。

            @Before("before() && target(target)

            public void beforeAdvide(JoinPoint point, Object proxy){

                  //处理逻辑

            }

 

      5)args:用于将参数传入到通知方法中。

            @Before("before() && args(age,username)")

            public void beforeAdvide(JoinPoint point, int age, String username){

                  //处理逻辑

            }

 

      6)@within :用于匹配在类一级使用了参数确定的注解的类,其所有方法都将被匹配。 

 

            @Pointcut("@within(com.sjz.annotation.AdviceAnnotation)") - 所有被@AdviceAnnotation标注的类都将匹配

            public void before(){}  

 

      7)@target :和@within的功能类似,但必须要指定注解接口的保留策略为RUNTIME。

            @Pointcut("@target(com.sjz.annotation.AdviceAnnotation)")

            public void before(){} 

 

      8)@args :传入连接点的对象对应的Java类必须被@args指定的Annotation注解标注。

            @Before("@args(com.sjz.annotation.AdviceAnnotation)")

            public void beforeAdvide(JoinPoint point){

                  //处理逻辑

            }  

 

      9)@annotation :匹配连接点被它参数指定的Annotation注解的方法。也就是说,所有被指定注解标注的方法都将匹配。

            @Pointcut("@annotation(com.sjz.annotation.AdviceAnnotation)")

            public void before(){}

 

      10)bean:通过受管Bean的名字来限定连接点所在的Bean。该关键词是Spring2.5新增的。

            @Pointcut("bean(person)")

            public void before(){}

 

分享到:
评论

相关推荐

    SpringBoot AOP各种注解、自定义注解、鉴权使用案例(免费下载)

    SpringBoot AOP,即面向切面编程,是Spring框架中的一个重要特性,用于实现代码的横切关注点,如日志记录、事务管理、权限验证等。AOP通过使用代理模式,将这些关注点与核心业务逻辑分离,使得代码更加模块化,更...

    SpringBoot AOP切面类三种写法(源代码)

    SpringBoot AOP 写法一: @Before("execution(* com.bjpowernode.springboot07.javabean.Man.eat(..))") 一、AOP开发 1.1 概述 1.2使用方法 1.3创建项目并添加maven依赖 1.4 创建Javabean测试类 1.5 创建切面 1.6 ...

    springboot AOP使用实例源码

    在Springboot上使用AOP的简单实例源码,可以结合本人的文章一起学习理解 https://blog.csdn.net/vincent_yuan89/article/details/85128009

    SpringBoot中的AOP+自定义注解(源代码)

    SpringBoot 中的 Aop + 自定义注解 1. @AspectJ 1.1 `@AspectJ` 切面类 1.2 `@Pointcut` 创建切入点 1.3 通知 1.4 Spring AOP 和 AspectJ AOP 有什么区别? 2. 在 SpringBoot 中使用 Aop 功能 2.0 创建一个...

    详解SpringBoot AOP 拦截器(Aspect注解方式)

    SpringBoot AOP 拦截器(Aspect注解方式) 在 SpringBoot 项目中,AspectJ 是一种常用的 AOP 实现方式,通过使用 AspectJ 注解,可以轻松地实现方法拦截和增强。下面将详细介绍 SpringBoot AOP 拦截器的实现方式。 ...

    高级软件人才培训专家-day13-SpringBoot AOP

    ### 高级软件人才培训专家-day13-SpringBoot AOP #### 一、事务管理 ##### 事务回顾 在数据库操作中,**事务**是一个非常重要的概念,它确保了一系列的操作作为一个整体被执行,即所有操作要么全部成功,要么全部...

    springBoot+aop+自定义注解+本地线程实现统一接口日志及接口响应时长

    内容概要:springboot+拦截器+aop+自定义注解+本地线程实现统一接口日志记录,记录下接口所在模块、接口描述、接口请求参数、接口返回参数、接口请求时间以及接口耗时用于接口优化,接口记录参数以及操作人防止使用...

    springBoot+aop 简单demo

    而AOP(Aspect Oriented Programming,面向切面编程)则是Spring框架的一个重要特性,它允许程序员在不修改原有业务代码的情况下,对程序进行功能增强或日志记录等操作。现在我们来详细探讨Spring Boot集成AOP的基本...

    SpringBoot AOP方式实现多数据源切换的方法

    SpringBoot AOP方式实现多数据源切换的方法 在本篇文章中,我们将介绍如何使用 SpringBoot AOP 方式实现多数据源切换的方法。这是一种非常实用的解决方案,能够解决多数据源配置和动态切换的问题。 多数据源配置 ...

    spring-boot aop

    Spring Boot AOP(面向切面编程)是一种强大的设计模式,它允许我们在不修改现有代码的情况下,插入额外的功能或监控代码。在Spring框架中,AOP主要用于日志记录、事务管理、性能统计等场景。本示例是关于如何在...

    使用springboot aop来实现读写分离和事物配置

    使用SpringBoot AOP实现读写分离和事务配置 使用SpringBoot AOP来实现读写分离和事务配置是当前流行的技术方案之一。本文将详细介绍使用SpringBoot AOP来实现读写分离和事务配置的原理、实现步骤和配置方法。 一、...

    SpringBoot+AOP日志

    在本项目中,"SpringBoot+AOP日志"是一个基于Spring Boot框架的日志管理系统,它利用了Spring Boot的便利性和AOP(面向切面编程)技术来实现对应用程序日志的高效、统一处理。让我们深入探讨一下这个项目的核心知识...

    解决springboot的aop切面不起作用问题(失效的排查)

    解决SpringBoot的AOP切面不起作用问题排查 SpringBoot中的AOP(Aspect-Oriented Programming)切面是指在业务逻辑中添加的额外功能,以实现日志记录、安全检查、事务管理等功能。但是,在实际开发中,我们可能会...

    springboot+aspect实现springaop拦截指定方法.zip

    SpringBoot结合AspectJ实现SpringAOP拦截指定方法的知识点涵盖了多个方面,这包括Spring AOP的基本概念、SpringBoot的应用、切点(Pointcut)与通知(Advice)的定义、自定义注解以及AspectJ的使用。以下是这些知识...

    springBoot+mybatis读写分离(AOP)

    本文将详细讲解如何利用Spring Boot、MyBatis和AOP(面向切面编程)来实现这一技术。 首先,让我们理解什么是读写分离。在传统的单库模式中,所有的读写操作都在同一个数据库上执行,当并发量增大时,数据库的压力...

    springboot aop切面实现方法入参及返回结果数据加解密

    springboot+aop 自定义注解(切入点为方法) 可对请求入参或者返回结果进行加解密 可允许用户自定义加解密工具类 本工具自带默认加解密工具类,用户可自行选择是否使用

    springboot spring aop 拦截器注解方式实现脱敏

    在Spring Boot应用中,Spring AOP(面向切面编程)是一种强大的工具,它允许我们创建横切关注点,如日志记录、权限检查等,这些关注点可以被编织到应用程序的多个点上,而无需侵入核心业务逻辑。在本案例中,我们将...

    spring boot aop 统一处理日志

    在Spring Boot应用中,AOP(面向切面编程)是一种强大的工具,用于实现代码的解耦和模块化,尤其适用于处理横切关注点,如日志记录、事务管理、安全控制等。本教程将深入探讨如何利用Spring Boot的AOP特性来实现日志...

    [] - 2023-11-19 SpringBoot AOP + Redis 延时双删功能实战.pdf

    互联网资讯,技术简介,IT、AI技术,人工智能互联网资讯,技术简介,IT、AI技术,人工智能互联网资讯,技术简介,IT、AI技术,人工智能互联网资讯,技术简介,IT、AI技术,人工智能互联网资讯,技术简介,IT、AI技术...

    SpringBoot使用AOP注解记录操作日志

    AOP(面向切面编程)是一种强大的工具,它允许我们在不改变原有业务逻辑的情况下,对代码进行横向扩展,比如添加日志记录功能。本篇文章将深入探讨如何在Spring Boot中利用AOP注解来实现操作日志的记录。 首先,...

Global site tag (gtag.js) - Google Analytics