SpringBoot注解+AOP实现

2023-11-07

SpringBoot注解+AOP实现

Java Annotation注解的详解

​ Java注解是一种元数据,它可以用于在类、方法或其他代码结构中声明关于程序元素的信息和标记。在Java中,注解以 @ 符号开头,在编译时或运行时由Java虚拟机(JVM)或其他工具进行处理。

注解可以用于许多不同的用途,包括:

  1. 编译时检查:注解可以让编译器在编译期间检查程序是否满足一些条件,例如@Deprecated标记弃用的代码,编译器会在编译期间提示有关该代码的警告。
  2. 运行时处理:注解允许代码在运行时根据指定的元数据来执行特定操作。例如,许多Web框架使用注解对请求处理器和URL进行映射。
  3. 文档生成:注解可以用于生成文档以描述代码的特定方面,使得文档维护更简单方便。
  4. 安全性:注解可以用于标记代码中的潜在安全漏洞,帮助开发人员快速找到和修复这些问题。

@Target指定注解针对的地方

在Java开发中,自定义注解是一种非常常见的技术手段,它可以用于定义元数据,对程序的逻辑进行标注、配置和调度等操作。@Target 是一个元注解(即注解的注解),它用来规定自定义注解可以修饰的程序单元(如类、方法、字段等)。@Target 的类型包括以下几种:

  1. ElementType.ANNOTATION_TYPE 表示自定义的注解可以修饰其他注解,例如 @SuppressWarnings。
  2. ElementType.CONSTRUCTOR 表示自定义的注解可以修饰构造函数,用于配置依赖注入等操作。
  3. ElementType.FIELD 表示自定义的注解可以修饰类的属性(字段),用于配置依赖注入、序列化等操作。
  4. ElementType.LOCAL_VARIABLE 表示自定义的注解可以修饰局部变量,通常用于实现某些特定功能或业务逻辑的处理。
  5. ElementType.METHOD 表示自定义的注解可以修饰方法,通常用于配置事务、权限校验、缓存管理等操作。
  6. ElementType.MODULE 表示自定义的注解可以修饰 Java 9 中的模块(Module)。
  7. ElementType.PACKAGE 表示自定义的注解可以修饰 Java 包(Package)内的所有类。
  8. ElementType.PARAMETER 表示自定义的注解可以修饰方法的参数,通常用于配置参数校验、日志打印等操作。
  9. ElementType.TYPE 表示自定义的注解可以修饰类、接口(Interface)或枚举类型(Enum),通常用于配置声明周期、依赖注入、AOP等操作。

总之,通过合理使用 @Target,我们可以更加精细地控制自定义注解的使用范围,避免滥用或误用。需要注意的是,多个 @Target 可以同时出现在同一个注解上面,使用大括号括起来即可,例如:@Target({ElementType.METHOD, ElementType.FIELD}) 表示该注解可以同时修饰方法和属性。

@Retention指定注解的保留域

在Java开发中,自定义注解是一种非常常见的技术手段,它可以用于定义元数据,对程序的逻辑进行标注、配置和调度等操作。而 @Retention 是一个元注解(即注解的注解),它用来规定自定义注解的生命周期。

在Java语言中,共有三种 @Retention 类型:

  1. RetentionPolicy.SOURCE 表示自定义注解只在源代码中保留,编译器会在编译时丢弃该注解,不会被包含在编译后生成的 class 文件中。这种类型的注解通常用于对开发者进行提示或注释,对实际的程序并没有实质性的影响。
  2. RetentionPolicy.CLASS(默认值) 表示自定义注解在编译时保留,但不会被加载到 JVM 中运行。当程序运行时,JVM 不会将该注解加载进来,因此在运行期间无法获取该注解及其信息。这种类型的注解通常用于字节码分析工具等场景。
  3. RetentionPolicy.RUNTIME 表示自定义注解在编译时与运行时都会保留,可以通过反射机制获取注解以及注解的属性。这种类型的注解通常用于在运行时进行动态处理,例如 AOP 、代理模式 等场景。

需要注意的是,@Retention 和 @Target 一样,均可以出现在自定义注解声明上,用于指定注解的生命周期及使用范围,例如:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
    // ...
}

通过合理地控制 @Retention 的属性值,我们可以更好地适应程序的需求,并充分发挥自定义注解的优势和特点。

自定义注解

自定义一个注解用于方法,自定义注解的保留域是运行时。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InitDemo {
}

如下是定义一个类,用于使用该注解。

public class InitInvoke {
    @InitDemo
    public void initDemo(){
        System.out.println("使用了@InitDemo 注解");
    }
}

通过反射机制,查看InitInvoke的类是否使用了InitDemo的注解。

public class InitMain {
    public static void main(String[] args) throws ClassNotFoundException {
        // 通过反射机制获取类
        Class aClass = Class.forName("com.juc.aop.InitInvoke");
        // 通过类获取所有的方法
        Method[] methods = aClass.getMethods();
        // 通过stream流过滤是否存在该method
        Object[] objects = Arrays.stream(methods)
                .filter(method -> method.isAnnotationPresent(InitDemo.class))
                .map((Function<Method, Object>) method -> method)
                .toArray();
        // 打印当前的方法
        System.out.println(objects[0]);
    }
}

打印结果如下:

public void com.juc.aop.InitInvoke.initDemo()

自定义注解 + AOP

自定义注解和面向切面编程(AOP)是两种常用的技术手段,它们的结合可以帮助程序员更好地构建高可维护、高性能且易于扩展的应用程序。

自定义注解在Java开发中被广泛使用,通常用于将元数据添加到代码中并实现复杂的逻辑控制。而AOP则是一种技术框架,在运行时动态地将代码分为多个关注点(Aspect),从而实现对系统中不同层次模块的解耦和通用处理。

使用自定义注解与 AOP 相结合的方式,可以为业务需求和技术层面提供更灵活的解决方案。具体来说,在某些场景下,我们可以通过自定义注解为方法、类或对象打上标记,并结合 AOP 同时实现横向切面的操作,例如:

  • 权限校验:通过自定义注解标记方法或类,并基于 AOP 实现拦截器进行权限校验;
  • 日志记录:通过自定义注解标记方法或类,并基于 AOP 实现切面服务来记录日志信息;
  • 事务管理:通过自定义注解标记方法或类,并基于 AOP 实现拦截器对事务进行管理。

总之,自定义注解和 AOP 的相互配合,可以有效地降低业务逻辑代码的复杂度,提高程序的可维护性和灵活性。

1、创建日志打印注解

定义了一个名为 InvokeLog 的注解,它被 @Target(ElementType.METHOD) 指定为方法级别的注解,即只能在方法上使用。同时,通过 @Retention(RetentionPolicy.RUNTIME) 可知该注解的生命周期为 RUNTIME,表示可以在运行时获取到该注解对象及其属性。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InvokeLog {
}

2、创建一个Aspect切面类

使用Spring AOP框架实现的切面类 InvokeLogAspect ,它通过自定义注解 @InvokeLog@Pointcut 切点,对程序中添加了 @InvokeLog 注解的方法进行切面编程,在方法执行前、后或抛出异常时,记录日志信息。

具体来说:

  • @Aspect@Component 分别表示该类是一个切面类且可被 Spring IOC 容器管理。
  • @Pointcut 定义了一段表达式,用于确定哪些方法需要被拦截(即连接点),这里通过判断方法是否添加了 @InvokeLog 注解来决定切入点。
  • @Around 表示这是一个环绕通知,将目标方法包围起来,可以在目标方法执行之前和之后分别执行特定的处理逻辑。其中,ProceedingJoinPoint 对象可以在通知方法中获取执行目标方法的信息。
  • 在 @Around 方法中,首先获取目标方法的方法名。然后通过 log.info()方法输出一些相关的日志信息,以便于进行调试和排查问题。
  • 最后通过 proceedingJoinPoint.proceed() 方法执行目标方法,并记录方法执行前、后、抛出异常时的日志信息,这样可以更方便地追踪程序运行状态,提高系统的可维护性和可靠性。
@Aspect
@Component
@Slf4j
public class InvokeLogAspect {

    // 确认切点
    @Pointcut("@annotation(cn.itcast.order.aop.InvokeLog)")
    public void pt(){

    }

    @Around("pt()")
    public Object printInvokeLog(ProceedingJoinPoint proceedingJoinPoint){
        Object proceed = null;
        // 目标方法执行前
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        String methodName = signature.getMethod().getName();
        log.info("这是方法执行前: {}",methodName);
        try {
            proceed = proceedingJoinPoint.proceed();
            // 目标方法执行后
            log.info("这是方法执行后: {}",methodName);
        } catch (Throwable e) {
            e.printStackTrace();
            // 目标方法执行抛出错误的时候
            log.info("这是方法出现异常后:{}",methodName);
        }
        return proceed;
    }
}

3、在业务上使用注解

    @InvokeLog
    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 2.用Feign远程调用
        User user = userClient.findById(order.getUserId());
        // 3.封装user到Order
        order.setUser(user);
        // 4.返回
        return order;
    }

image-20230503135102244

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpringBoot注解+AOP实现 的相关文章

随机推荐

  • js键盘移动事件

    keyboard box move
  • 第十三届蓝桥杯省赛Java A 组 F 题、Python A 组 G 题、Python B 组 G题——全排列的价值 (AC)

    目录 1 全排列的价值 1 题目描述 2 输入格式 3 输出格式 4 样例输入1 5 样例输出2 6 样例输出1 7 样例输出2 8 样例解释 9 原题链接 2 解题思路 3 Ac code 1 全排列的价值 1 题目描述 对于一个排列 A
  • GitHub Desktop官方下载链接

    Github Desktop官方下载 点击直达 https desktop github com
  • 云服务器vCPU与物理CPU关系

    CPU个数 看得见摸得找的CPU个数 插在主版上面的 在linux系统下面的 proc cpuinfo文件的条目中 有多少个不同的physical id就有多少个物理CPU CPU物理核 一个CPU可能有多个核 在linux系统下面的 pr
  • Android应用程序资源的查找过程分析

    我们知道 在Android系统中 每一个应用程序一般都会配置很多资源 用来适配不同密度 大小和方向的屏幕 以及适配不同的国家 地区和语言等等 这些资源是在应用程序运行时自动根据设备的当前配置信息进行适配的 这也就是说 给定一个相同的资源ID
  • 京东面试:如何实现分布式锁?

    案例背景 分布式锁是解决协调分布式系统之间 同步访问共享资源的一种方式 详细来讲 在分布式环境下 多个系统在同时操作共享资源 如写数据 时 发起操作的系统通常会通过一种方式去协调其他系统 然后获取访问权限 得到访问权限后才可以写入数据 其他
  • Python使用win32com.client()和load_workbook()追加写入excle

    win32com client 和load workbook 均可以实现在原有excle文件中写入内容 在实际使用中win32com client 使用的方法类似VBA来模拟用户进行操作 运行速度不如load workbook 1 win3
  • 数字锁相环——环路滤波器参数设计

    太难了 好像懂了 又好像没懂 梳理一下 模拟环路滤波器分别有RC积分滤波器 无源比例积分滤波器 有源比例积分滤波器 上图为有源比例积分滤波器 固有频率 n omega n n 和阻尼系数
  • An Introduction to GCC

    对于GCC特别的不熟练 只会google baidu来使用 最近想看看到底gcc如何使用 于是找到了这本书 写的很浅显易懂 而且框架写明白了 真的不错 1 gcc c 是编译的命令 编译与链接是不同的 gcc 不加任何选项时就是编译 链接了
  • VirtualBox安装Ubuntu教程(超详细)

    下载ubuntu系统镜像 准备虚拟机挂载镜像用 选择新建 创建虚拟机 选择系统版本 因为要安装ubuntu 所以选择ubuntu 设置虚拟机ubuntu的内存 创建虚拟机的磁盘 分配20G空间 动态分配是逐渐占用物理机硬盘空间
  • 软件外包公司到底干啥的?要不要去外包公司?

    一 什么是外包 软件外包分为 人力外包和项目外包两个方向 1 劳务派遣 指的是把员工外派到对应的用工企业打 短工 比如很多工程师虽然签约了中软国际 东软 文思海辉 软通动力 润和等软件公司 但实际工作地点是在华为 接受华为员相关负责人的工作
  • Spring系列之缓存使用(@EnableCaching、@Cacheable、@CachePut、@CacheEvict、@Caching、@CacheConfig)

    本文主要详解spring中缓存的使用 背景 缓存大家都有了解过吧 主要用来提升系统查询速度 比如电商中商品详情信息 这些信息通常不会经常变动但是会高频访问 我们可以将这些信息从db中拿出来放在缓存中 比如redis中 本地内存中 当获取的时
  • Idea Maven项目打包工其他项目进行外部引用

    1 说明 我们在日常项目开发中经常会有许多公共的模块 如统一的父工程 工具类模块 中间实体类 DTO VO 如果我们针对每个子项目都单独的创建一套工具类 多个子项目会存在很多重复的工具类 中间实体类代码 因此 我们可以将这些公共模块统一打成
  • 关于STM32串口接收中断中只能接收一个字节()

    最近调试STM32的串口接收时发现例程中只能接收一个字节 例程如下 1 初始化串口1 2 void uart init u32 bound 3 GPIO端口设置 4 GPIO InitTypeDef GPIO InitStructure 5
  • BAPI_ACC_DOCUMENT_POST 简单理解过账BAPI使用,创建会计凭证

    业务场景 创建会计凭证BAPI 甲方是一家从事房屋租赁的公司 它的主营业务就是从各大租户手里收租子 月底了 小明发了工资美滋滋 钱到手没多久房东就催租子了 房租每月100 水电100 税费22 合计222 小明如约在手机APP上向房东支付了
  • Dynamics CRM 2015/2016/365 Web API:批处理任务

    Web API为我们提供的批量任务执行功能 我们可以在一个请求中混合多个不相干的创建查询请求 并且其还提供了事务功能 如果在事务中如果有脚本出现了错误 则其提供回滚功能 如下是批处理的请求报文 在报文里面我们需要设置批处理任务的编号 因为我
  • uniapp各种路由与页面跳转路径

    跳转有长度限制过长的时候用encodeURIComponent pages test test item encodeURIComponent JSON stringify item 1 保留当前B页面 跳转到应用内的某个页面 会计入栈中
  • 【毕业设计】深度学习行人重识别系统 - person reid

    文章目录 0 前言 1 技术背景 2 技术介绍 3 重识别技术实现 3 1 数据集 3 2 Person REID 3 2 1 算法原理 3 2 2 算法流程图 4 实现效果 5 部分代码 6 最后 0 前言 Hi 大家好 这里是丹成学长的
  • css强制换行和禁止换行

    强制换行 word break break all 只对英文起作用 以字母作为换行依据 word wrap break word 只对英文起作用 以单词作为换行依据 white space pre wrap 只对中文起作用 强制换行 禁止换
  • SpringBoot注解+AOP实现

    SpringBoot注解 AOP实现 Java Annotation注解的详解 Java注解是一种元数据 它可以用于在类 方法或其他代码结构中声明关于程序元素的信息和标记 在Java中 注解以 符号开头 在编译时或运行时由Java虚拟机 J