Java 自定义注解

Java 自定义注解, 以及@interface @Target @Retention @Around @Before @After ProceedingJoinPoint JoinPoint 等用法

注解应用非常广泛,我们自定义注解能简化开发各种各种业务

一、关键字解释
(1) 定义注解时,关键字
@interface 来表示注解类的类型
在这里插入图片描述
@Target @Retention 这两个具体值,需要分析注解的应用场景来确定;
对于“调用方法时打印入参和出参”的例子,是在调用调用方法时,则使用RetentionPolicy.RUNTIME, 且作用于方法上,则使用ElementType.METHOD;

(2) 实现注解时,关键字
在这里插入图片描述

@Before、@After、@AfterReturning 方法的入参是JoinPoint类型
@Around 方法的入参是ProceedingJoinPoint类型

ProceedingJoinPoint继承了JoinPoint类型,并扩展出了proceed()方法,执行proceed()也就是执行原始的函数具体业务方法,可以通过JoinPoint对象获取一些请求上的参数,比如request,parms等;

执行顺序:
@Around >> @Before >> 被添加注解的方法业务执行 >> @After >> @AfterReturning

特别注意:
注解中,可以存在@Around、@Before 、@After或、@AfterReturning任意组合
注解中,存在@Around ,也存在@Before 、@After或、@AfterReturning时、会先执行@Around;

在@Around中,执行参数的ProceedingJoinPoint.proceed(), 会触发@Before 、“被添加注解的方法业务执行” 、@After、@AfterReturning的执行,

在@Around中,不执行参数的ProceedingJoinPoint.proceed(), 不会触发@Before 、“被添加注解的方法业务执行”,特别注意;所以正常逻辑中,ProceedingJoinPoint.proceed()都应该触发执行。

@Around 的返回值应该为 “被添加注解的方法业务执行” 的返回值。通过获取Object bizData = ProceedingJoinPoint.proceed(), 也可以对返回值加工再返回;

三、代码实现
(1) 定义注解

package com.xxxxx.annotation;

import java.lang.annotation.*;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MethodParam {

    /**
     * 自定义方法, 日志描述信息, 可有可无
     *
     * @return
     */
    String description() default "";

    /**
     * 自定义方法1, 日志描述信息, 可有可无
     *
     * @return
     */
    String description1() default "";

    /**
     * 自定义方法2, 日志描述信息, 可有可无
     *
     * @return
     */
    String description2() default "";
}

其中description() description1() description2() 都是自定义方法(相当于调用注解时的传参),当业务需要就声明,不需要就无需声明

(2) 实现注解

package com.xxxxx.annotation.annotationAspect;

import com.xxxxx.annotation.MethodParam;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
public class MethodParamAspect {

    /**
     * 声明切点
     */
    @Pointcut(value = "@annotation(com.xxxxx.annotation.MethodParam)")
    public void doPointCut() {
        System.out.print("执行doPointCut \n");
    }

    /**
     * 调用方法前后执行
     * @param joinPoint
     */
    @Around(value = "doPointCut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.print("执行doAround \n");

        //获取注解入参
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        MethodParam methodParamNew = method.getAnnotation(MethodParam.class);
        String description = methodParamNew.description();
        String description1 = methodParamNew.description1();
        String description2 = methodParamNew.description2();


        //被添加注解的方法业务执行
        Object bizData = joinPoint.proceed();

        //处理其他业务
        
        return bizData;
    }

    /**
     * 调用方法之【前】执行
     * @param joinPoint
     */
    @Before(value = "doPointCut()")
    public void doBefore(JoinPoint joinPoint){
        System.out.print("执行doBefore \n");
        //处理其他业务
    }


    /***
     * 调用方法之【后】执行
     *
     * @param joinPoint
     */
    @After(value = "doPointCut()")
    public void doAfter(JoinPoint joinPoint){
        System.out.print("执行doAfter \n");
        //处理其他业务
    }


    /***
     * @After执行之【后】执行
     *
     * @param joinPoint
     * @param res 具体业务的返回值 (可有可无)
     */
    @AfterReturning(value = "doPointCut()",returning = "res")
    public void doAfterReturning(JoinPoint joinPoint, String res){
        System.out.print("执行doAfterReturning \n");
        //处理其他业务
    }
}

(3) 使用注解

package com.xxxxx.component;

import com.xxxxx.annotation.MethodParam;
import org.springframework.stereotype.Component;
import java.util.Random;

@Component
public class OrderComponent {

    @MethodParam(description = "aaa", description1 = "bbb", description2 = "ccc")
    public String testAnnotation(String val1, String val2){
        String aa = val1.concat(val2)
        .concat(String.valueOf(String.format("%04d",new Random().nextInt(9999))));
        System.out.print(aa + "\n");
        return aa;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/258559.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

高级算法设计与分析(二) -- 递归与分治策略

系列文章目录 高级算法设计与分析(一) -- 算法引论 高级算法设计与分析(二) -- 递归与分治策略 高级算法设计与分析(三) -- 动态规划 未完待续【 高级算法设计与分析(四) -- 贪…

谷歌新款 Pixel 8 更小、更智能!

一、谷歌 Pixel 8 更小、更智能——比去年的 Pixel 7 贵了 100 美元——不是一点点——贵 与 Pixel 7 一样,Pixel同样在今天 8 比正式发布的更大的 Pixel 8 Pro 兄弟产品更小、更便宜。但今年价格有所上涨,128GB 存储型号的 Pixel 8 起售价为 699.99 美…

腾讯云消息队列11月产品月报 | RocketMQ 5.x 国际站上线

2023年 11月动态 消息队列 RocketMQ 版 1、5.x 形态国际站上线 国际站上线 5.x 集群全系列,第一批先开放新加坡和硅谷地域。 控制台链接:https://console.tencentcloud.com/trocketmq 2、 无感迁移能力 支持用户白屏化操作,将自建的 Roc…

夜莺项目发布 v6.5.0 版本,暗黑菜单来了

大家好,夜莺项目发布 v6.5.0 版本,启用新 logo,菜单支持换肤,支持了暗黑版本的菜单,下一步会支持全站暗黑主题,敬请期待,下面是新 logo。 暗黑菜单 页面右上角点击用户名,在下拉框里…

盘点ASO优化过去到现在的进步

ASO优化行业十年老兵报道!从以下几个方面总结了ASO优化的一些变化和进步,给大家分享。 一、优化手段: 过去,ASO优化主要依赖于机刷,通过破解苹果的算法,对苹果账号进行一系列的定向操作行为(搜…

React Jsx转换成真实DOM过程?

面试官:说说React Jsx转换成真实DOM过程? 一、是什么 react通过将组件编写的JSX映射到屏幕,以及组件中的状态发生了变化之后 React会将这些「变化」更新到屏幕上 在前面文章了解中,JSX通过babel最终转化成React.createElement这…

双碳背景下能耗在线监测系统硬件选型详述

Acrel-5000web建筑能耗分析系统是用户端能源管理分析系统,在电能管理系统的基础上增加了对水、气、煤、油、热(冷)量等集中采集与分析,通过对用户端所有能耗进行细分和统计,以直观的数据和图表向管理人员或决策层展示各类能源的使用消耗情况&…

SpringBoot访问外部接口的常见方式

文章目录 SpringBoot访问外部接口模拟服务接口RestTemplatepom.xmlRestTemplateConfigClientTestRestTemplateController.java结果 WebClientpom.xmlClientTestWebClientController.java结果 HttpClientpom.xmlClientTestHttpClientController.java结果 OkHttppom.xmlClientTes…

《数据结构、算法与应用C++语言描述》- 最小赢者树模板的C++实现

赢者树 完整可编译运行代码见:Github::Data-Structures-Algorithms-and-Applications/_30winnerTree 比赛规则 假定有 n 个选手参加一次网球比赛。比赛规则是“突然死亡法”(sudden-death mode):一名选手只要输掉一场球,就被淘汰。一对一对…

【Linux 驱动】Linux设备树(四)—— 设备树驱动LED

有了设备树以后,我们可以将寄存器信息保存到设备树,即便是更换了一个设备,我们也无需修改驱动文件,只需要修改设备树文件并重新编译。 下面介绍两种通过设备树驱动 LED 的最简单的方式,这两种方式的主要是设备树中 re…

自营商城与多商户入驻商城功能与开发流程_OctShop

如今互联网以及电子商务的大趋势下,很多企业或商家都意识到自营商城的重要性。当然,要搭建一个属于自己的自营商城并非简单。需要综合考虑众多的因素,如:用户体验、商品管理、在线支付、功能需求、市场分析等等多个方面。如果是自…

dell服务器 R740xd安装windows server 2019过程记录

公司有两台dell服务器型号是R740xd,增加了存储,更新系统到windows server 2019标准版。 查找了网上的系统安装方式,都没有实践成功,做一下工作记录,给大家做参考。 网络搜索到的两种方式,进行安装 &#x…

全都没有问题(二点五)

java 接口默认方法冲突等问题 基础基础基础 子接口覆盖父接口的默认方法 package com.book;interface AA{public abstract void print();public default void ID(){System.out.println("AA");} } interface BB extends AA{ //接口BB继承AAOverridepublic default…

C#线程的定义和使用方法

引言 在C#编程语言中,线程是一种并发执行的机制,允许程序同时执行多个任务。线程的使用使得我们能够利用计算机的多核处理器,实现程序的并行执行,提高系统的性能和响应能力。本文将详细介绍C#中线程的定义和使用方法,涵…

学习体系结构 - AArch64 虚拟化

学习体系结构 - AArch64 虚拟化 Learn the architecture - AArch64 virtualization Version 1.0 借助 Deepl 翻译文档 个人对文档补充的一部分解释, 仅供学习参考 前 3 章为了解内容,引入虚拟化 第 4-7 章为虚拟化比较核心的内容 第 4 章为第二阶段地址…

windows安装、基本使用vim

标题:windows安装、基本使用vim 1.下载并安装GVIM 百度网盘链接 提取码:2apr 进入安装界面,如下,勾选 其它都是默认即可 参考; 2.在powershell中使用vim 参考blog:window10安装vim编辑器 安装好后&…

机器人制作开源方案 | “校园卫士”-智能巡检机器人

作者:程训聪、柳贺凯、赵坤峰、叶智超、高仁伟 单位:黑龙江科技大学 指导老师:邵文冕、李杨 1. 摘要 针对校园巡检需求设计机器人本体结构,借助Arduino作为控制核心的巡检机器人控制系统构建方法研究了巡检机器人在校园环境下的…

数据结构:图解手撕B-树以及B树的优化和索引

文章目录 为什么需要引入B-树?B树是什么?B树的插入分析B树和B*树B树B*树分裂原理 B树的应用 本篇总结的内容是B-树 为什么需要引入B-树? 回忆一下前面的搜索结构,有哈希,红黑树,二分…等很多的搜索结构&a…

Maven仓库上传jar和mvn命令汇总

目录 导入远程仓库 命令结构 命令解释 项目pom 输入执行 本地仓库导入 命令格式 命令解释 Maven命令汇总 mvn 参数 mvn常用命令 web项目相关命令 导入远程仓库 命令结构 mvn deploy:deploy-file -Dfilejar包完整名称 -DgroupIdpom文件中引用的groupId名 -Dartifa…

使用 Node.js 删除文件 - 完整步骤教程

引言 在 Node.js 中处理文件尤其是移除文件,对于维护高效应用程序至关重要。储存和秩序当道的今天,删除不必要或冗余的文件能力显得尤为关键。本文深入探讨你会想要使用这个强大功能的时刻和原因,并通过各种案例展示了这个概念,同…