SpringBoot搭配AOP实现自定义注解

目录
  • 1.springBoot的依赖
  • 2.自定义注解的步骤
    • 2.1定义注解类
    • 2.2定义切面
    • 2.3使用注解
  • 3.知识点补充
    • 3.1 关于Target注解补充
    • 3.2 关于Retention注解补充
    • 3.3 关于AOP的一些概念补充
    • 3.4关于AOP中一些类及函数的使用

1.springBoot的依赖

确定项目中包含可以注解的依赖

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

2.自定义注解的步骤

在项目中自定义注解的步骤主要有两步,第一步:定义注解类,第二步:定义切面

2.1定义注解类

直接创建 @interface的类,使用注解@Target和 @Retention指定其适用范围及保留时长,如下:

@Target(ElementType.METHOD) // 指定注解的适用范围
@Retention(RetentionPolicy.RUNTIME) //指定运行时
public @interface ApiLog {

    String desc() default "";

    boolean timeSpan() default true;

}

注解类的内容一般很简单,类似于Enum类一样,里面是简单的方法及属性

2.2定义切面

通过@Aspect注解指定一个类,该类必须实现

@Component
@Aspect
@Slf4j(topic = "ApiLogNote")
public class ElasticSearchExecuteLog {

    @Around("@annotation(com.gcc.ApiLog)")
    public Object aroundAdvice(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        //获取被调用方法
        Method method = signature.getMethod();
        //取出被调用方法的注解,方便后续使用注解中的属性
        ApiLog loglinstener = method.getAnnotation(ApiLog.class);
        log.info("----------------------method[{}]start--------------------",method.getName());
        log.info("方法描述:{}",loglinstener.desc());
        log.info("参数 :{}",point.getArgs());
        long startTime = System.currentTimeMillis();
        Object proceed = point.proceed();
        long endTime = System.currentTimeMillis();
        log.info("耗时:{}ss",endTime-startTime);
        log.info("----------------------method[{}] end--------------------\n",method.getName())
        return proceed;
    }
}

2.3使用注解

因为此例子使用的类型为METHOD即方法级的注解,直接在方法上使用即可:

    @ApiLog
    public JSONObject seachEsData(String indexName, SearchSourceBuilder searchSourceBuilder) {
        JSONObject resultMap = new JSONObject();
        .......
        return resultMap;
    }

3.知识点补充

3.1 关于Target注解补充

注解@Target常常配合枚举类ElementType来指定注解的作用位置,也叫合法位置,即你定义了一个注解,这个注解是类注解还是方法注解还是XX注解等,具体作用的范围,取决于@Target({ElementType.TYPE})中,ElementType的枚举值,在进行自定义枚举时,根据自己的需求,决定定义的注解是哪类层级使用的注解,例如上面的例子中,@ApiLog这个自定义的注解就是方法级的注解

ElementType的枚举值有

枚举值 含义
TYPE 类, 接口 (包括注解类型), 或 枚举 声明
FIELD 字段、包括枚举常量
METHOD 方法声明
PARAMETER 正式的参数声明
CONSTRUCTOR 构造函数的声明
LOCAL_VARIABLE 局部变量的声明
ANNOTATION_TYPE 注解类型的声明
PACKAGE 包声明

3.2 关于Retention注解补充

注解@Retention常常配合枚举类RetentionPolic来指定注解的各种策略,注解的保留时间,也就是何时生效,即你定义了一个注解,这个注解是编译时生效还是仅仅只是在代码中标记等等,具体作用的范围,取决于@Retention({RetentionPolic.TYPE})中,RetentionPolic的枚举值,在进行自定义枚举时,大多数都是使用RUNTIME(编译时生效)

RetentionPolic的枚举值

枚举值 含义
SOURCE 解只在源代码级别保留,编译时被忽略
CLASS 注解将被编译器在类文件中记录 , 但在运行时不需要JVM保留。这是默认的
RUNTIME 注解将被编译器记录在类文件中,在运行时保留VM,也是使用最多的(一般自定义均使用这个)

3.3 关于AOP的一些概念补充

这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程

切面

切面是一个横切关注点的模块化,一个切面能够包含同一个类型的不同增强方法,比如说事务处理和日志处理可以理解为两个切面。切面由切入点和通知组成,它既包含了横切逻辑的定义,也包括了切入点的定义。 Spring AOP就是负责实施切面的框架,它将切面所定义的横切逻辑织入到切面所指定的连接点中。简单点理解,在SpringBoot中使用了Aspect注解的类就是切面

@Component
@Aspect
public class LogAspect {
}

目标对象

目标对象指将要被增强的对象,即包含主业务逻辑的类对象。或者说是被一个或者多个切面所通知的对象。

在我们的例子中,即是使用了@ApiLog注解的地方

连接点

程序执行过程中明确的点,如方法的调用或特定的异常被抛出。连接点由两个信息确定:

方法(表示程序执行点,即在哪个目标方法)

相对点(表示方位,即目标方法的什么位置,比如调用前,后等)

简单来说,连接点就是被拦截到的程序执行点,因为Spring只支持方法类型的连接点,所以在Spring中连接点就是被拦截到的方法。

切入点

切入点是对连接点进行拦截的条件定义。切入点表达式如何和连接点匹配是AOP的核心,Spring缺省使用AspectJ切入点语法。 一般认为,所有的方法都可以认为是连接点,但是我们并不希望在所有的方法上都添加通知,而切入点的作用就是提供一组规则(使用 AspectJ pointcut expression language 来描述) 来匹配连接点,给满足规则的连接点添加通知。

//此处的匹配规则是 com.remcarpediem.test.aop.service包下的所有类的所有函数。
@Pointcut("execution(* com.remcarpediem.test.aop.service..*(..))")
public void pointcut() {
}

这里切入点的概念其实就是确定对哪些目标对象进行切面插入功能,一开始的例子是采用注解的方式来达到切入**点的作用

 @Around("@annotation(com.gcc.ApiLog)")

通知

通知是指拦截到连接点之后要执行的代码,包括了“around”、“before”和“after”等不同类型的通知。Spring AOP框架以拦截器来实现通知模型,并维护一个以连接点为中心的拦截器链。

// @Before说明这是一个前置通知,log函数中是要前置执行的代码,JoinPoint是连接点,
@Before("pointcut()")
public void log(JoinPoint joinPoint) {
}

​​​​​​​//@After 为后置通知

//@Around 为环绕通知

织入(Weaving)

这里的织入概念是个动作,即Spring将前面的切面、连接点、切入点关联起来并创建通知代理的过程。织入可以在编译时,类加载时和运行时完成。在编译时进行织入就是静态代理,而在运行时进行织入则是动态代理。

增强器(Advisor)

Advisor是切面的另外一种实现,能够将通知以更为复杂的方式织入到目标对象中,是将通知包装为更复杂切面的装配器。Advisor由切入点和Advice组成。 Advisor这个概念来自于Spring对AOP的支撑,在AspectJ中是没有等价的概念的。Advisor就像是一个小的自包含的切面,这个切面只有一个通知。切面自身通过一个Bean表示,并且必须实现一个默认接口。

简单来讲,整个 aspect 可以描述为: 满足 pointcut 规则的 joinpoint 会被添加相应的 advice 操作。

将上方通过注解使用切面的方式改写一下:

@Component
@Aspect
@Sl4fj
public class ElasticSearchExecuteLog {

  // 不使用注解,而通过基础的规则配置选择切入点,表达式是指com.gcc.controller
 // 包下的所有类的所有方法
 @Pointcut("execution(* com.gcc.controller..*(..))")
 public void aspect() {}

  // 通知,在符合aspect切入点的方法前插入如下代码,并且将连接点作为参数传递
 @Before("aspect()")
 public void log(JoinPoint joinPoint) { //连接点作为参数传入
   // 获得类名,方法名,参数和参数名称。
   Signature signature = joinPoint.getSignature();
   String className = joinPoint.getTarget().getClass().getName();
   String methodName = joinPoint.getSignature().getName();
   Object[] arguments = joinPoint.getArgs();
   MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
   String[] argumentNames = methodSignature.getParameterNames();
   StringBuilder sb = new StringBuilder(className + "." + methodName + "(");
       for (int i = 0; i< arguments.length; i++) {
                  Object argument = arguments[i];
                  sb.append(argumentNames[i] + "->");
                  sb.append(argument != null ? argument.toString() : "null ");
       }
   sb.append(")");
   log.info(sb.toString());
  }
}

3.4关于AOP中一些类及函数的使用

JoinPoint对象

JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的JoinPoint对象.

方法 作用 返回对象
getSignature() 获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息 Signature
getArgs() 获取 获取传入目标方法的参数对象 Object[]
getTarget() 获取被代理的对象 Object

proceedingJoinPoin对象

proceedingJoinPoin对象是JoinPoint的子类,在原本JoinPoint的基础上,放开了Proceeed()的使用,一般在环绕通知@Around时使用:

Object proceed() throws Throwable //执行目标方法
Object proceed(Object[] var1) throws Throwable //传入的新的参数去执行目标方法

以上就是SpringBoot搭配AOP实现自定义注解的详细内容,更多关于SpringBoot AOP自定义注解的资料请关注我们其它相关文章!

(0)

相关推荐

  • Springboot利用Aop捕捉注解实现业务异步执行

    目录 一.先说说线程的几种创建方式(简要列举) 二.再聊一聊spring自带的@Async注解实现异步任务的方法 三.那么就来设计一下怎么使用自定义的注解实现异步任务 在开发过程中,尽量会将比较耗时且并不会影响请求的响应结果的业务放在异步线程池中进行处理,那么到时什么任务在执行的时候会创建单独的线程进行处理呢?我们可以在对应的业务方法上打上自定义的注解,再利用AOP去捕捉这个注解,就可以利用环绕通知的特性进行异步的设置. 一.先说说线程的几种创建方式(简要列举) 1.继承Thread类,复写ru

  • Springboot项目Aop与拦截器与过滤器横向对比

    目录 前言 功能特性对比 过滤器 拦截器 Spring AOP 代码实现 过滤器实现 拦截器实现 AOP实现 验证结果 工作原理 总结 前言 伟人曾经说过,没有调查就没有发言权(好像是伟人说的,不管谁说的,这句话是正确的),有些东西看着简单,张口就来,但很有可能是错的.我个人的经验是,aop.过滤器.拦截器的实现方式很简单,一学就会,不用就忘,忘了再学,学了再忘,如此循环内耗何必呢?因此,如果你和我一样,有一颗强烈的好奇之心,那么不管多简单,动手敲起来吧,温故而知新呢. 功能特性对比 过滤器 过

  • SpringBoot中的Aop用法示例详解

    目录 什么是Aop Aop概述 相关注解 相关概念 实例1 @PointCut 表达式详解 execution(表达式) within this target args: args用来匹配方法参数 @annotation: @args: 逻辑运算符 实例2 环绕通知 什么是Aop 主要介绍springboot中aop的使用,用过Spring框架的都知道,aop是spring框架的两大核心功能之一,还有一个就是ioc,下面我们就springboot中如何引入aop来做一下探讨 引入AOP依赖包后,

  • springboot实现拦截器的3种方式及异步执行的思考

    目录 springboot 拦截器 springboot 入门案例 maven 引入 启动类 定义 Controller 拦截器定义 基于 Aspect 基于 HandlerInterceptor 基于 ResponseBodyAdvice 测试 异步执行 定义异步线程池 异步执行的 Controller 思考 测试 反思 springboot 拦截器 实际项目中,我们经常需要输出请求参数,响应结果,方法耗时,统一的权限校验等. 本文首先为大家介绍 HTTP 请求中三种常见的拦截实现,并且比较一

  • Springboot项目快速实现Aop功能

    目录 前言 依赖引入 代码实现 核心注解和类 标记切入点的常用方式 Spring Aop的小技巧 Spring Aop注意事项 总结 前言 这篇文章的有几个关键点,第一,关于AOP的一些基础理论知识,在正式使用AOP前需要了解:第二,Springboot项目中怎么快速集成Aop功能的:第三,AOP的一些使用小技巧和注意事项. 依赖引入 Springboot引入AOP依赖包后,一般来说是不需要再做其他配置了,在比较低的版本或者有其他配置影响了AOP的相关功能,导致aop功能不生效,可以试试在启动类

  • 详解使用Spring AOP和自定义注解进行参数检查

    引言 使用SpringMVC作为Controller层进行Web开发时,经常会需要对Controller中的方法进行参数检查.本来SpringMVC自带@Valid和@Validated两个注解可用来检查参数,但只能检查参数是bean的情况,对于参数是String或者Long类型的就不适用了,而且有时候这两个注解又突然失效了(没有仔细去调查过原因),对此,可以利用Spring的AOP和自定义注解,自己写一个参数校验的功能. 代码示例 注意:本节代码只是一个演示,给出一个可行的思路,并非完整的解决

  • Spring Boot 通过AOP和自定义注解实现权限控制的方法

    本文介绍了Spring Boot 通过AOP和自定义注解实现权限控制,分享给大家,具体如下: 源码:https://github.com/yulc-coding/java-note/tree/master/aop 思路 自定义权限注解 在需要验证的接口上加上注解,并设置具体权限值 数据库权限表中加入对应接口需要的权限 用户登录时,获取当前用户的所有权限列表放入Redis缓存中 定义AOP,将切入点设置为自定义的权限 AOP中获取接口注解的权限值,和Redis中的数据校验用户是否存在该权限,如果R

  • SpringBoot 拦截器和自定义注解判断请求是否合法

    应用场景举例: 当不同身份的用户请求一个接口时,用来校验用户某些身份,这样可以对单个字段数据进行精确权限控制,具体看代码注释 自定义注解 /** * 对比请求的用户身份是否符合 * @author liuyalong * @date 2020/9/25 16:03 */ @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) public @interface CompareUser { /** * The name

  • Spring AOP 实现自定义注解的示例

    自工作后,除了一些小项目配置事务使用过 AOP,真正自己写 AOP 机会很少,另一方面在工作后还没有写过自定义注解,一直很好奇注解是怎么实现他想要的功能的,刚好做项目的时候,经常有人日志打得不够全,经常出现问题了,查日志的才发现忘记打了,所以趁此机会,搜了一些资料,用 AOP + 自定义注解,实现请求拦截,自定义打日志,玩一下这两个东西,以下是自己完的一个小例子,也供需要的同学参考. 1. 注解如下: package cn.bridgeli.demo.annotation;   import j

  • springboot中shiro使用自定义注解屏蔽接口鉴权实现

    目录 传统做法 使用自定义注解屏蔽接口鉴权 拓展内容:关于spring中的派生注解 传统做法 spring boot整合shiro后,如果某些接口需要屏蔽鉴权的话(比如登录)接口,我们一般会这么做: @Bean(name = "shiroFilter") public ShiroFilterFactoryBean shiroFilterFactoryBean(org.apache.shiro.mgt.SecurityManager securityManager) { ShiroFil

  • 详解使用Spring Boot的AOP处理自定义注解

    上一篇文章Java 注解介绍讲解了下Java注解的基本使用方式,并且通过自定义注解实现了一个简单的测试工具:本篇文章将介绍如何使用Spring Boot的AOP来简化处理自定义注解,并将通过实现一个简单的方法执行时间统计工具为样例来讲解这些内容. AOP概念 面向侧面的程序设计(aspect-oriented programming,AOP,又译作面向方面的程序设计.观点导向编程.剖面导向程序设计)是计算机科学中的一个术语,指一种程序设计范型.该范型以一种称为侧面(aspect,又译作方面)的语

  • AOP Redis自定义注解实现细粒度接口IP访问限制

    目录 系列说明 实现步骤 一.引入依赖 二.写注解 三.写逻辑(注解环绕) 1. 添加注解 2. 注入 RedisTemplate 3. 定义方法 4. 实现方法 5. 开启spring自动装配 四.测试 总结 系列说明 GitHub地址:github.com/stick-i/scb… 目前项目还有很大改进和完善的空间,欢迎各位有意愿的同学参与项目贡献(尤其前端),一起学习一起进步. 项目的技术栈主要是: 后端 Java + SpringBoot + SpringCloud + Nacos +

  • Spring Boot之AOP配自定义注解的最佳实践过程

    前言 AOP(Aspect Oriented Programming),即面向切面编程,是Spring框架的大杀器之一. 首先,我声明下,我不是来系统介绍什么是AOP,更不是照本宣科讲解什么是连接点.切面.通知和切入点这些让人头皮发麻的概念. 今天就来说说AOP的一些应用场景以及如何通过和其他特性的结合提升自己的灵活性.下面话不多说了,来一起看看详细的介绍吧 AOP应用举例 AOP的一大好处就是解耦.通过切面,我们可以将那些反复出现的代码抽取出来,放在一个地方统一处理. 同时,抽出来的代码很多是

  • SpringBoot中利用AOP和拦截器实现自定义注解

    目录 前言 Spring实现自定义注解 1.引入相关依赖 2.相关类 Java实现自定义注解 通过Cglib实现 通过JDk动态代理实现 Cglib和JDK动态代理的区别 写在最后 前言 最近遇到了这样一个工作场景,需要写一批dubbo接口,再将dubbo接口注册到网关中,但是当dubbo接口异常的时候会给前端返回非常不友好的异常.所以就想要对异常进行统一捕获处理,但是对于这种service接口使用@ExceptionHandler注解进行异常捕获也是捕获不到的,应为他不是Controller的

  • SpringBoot使用AOP记录接口操作日志的方法

    目录 一.操作日志简介 1.1.系统日志和操作日志的区别 1.2.操作日志记录实现方式 二.AOP面向切面编程 2.1.AOP简介 2.2.AOP作用 2.3.AOP相关术语 2.4.JointPoint和ProceedingJoinPoint 2.5.AOP相关注解 三.AOP切面实现接口日志记录 3.1.引入AOP依赖 3.2.创建日志信息封装类WebLog 3.3.创建切面类WebLogAspect 3.4.调用接口进行测试 四.AOP切面+自定义注解实现接口日志记录 4.1.自定义日志注

随机推荐