点击上方蓝色“程序猿DD”,选择“设为星标”

回复“资源”获取独家整理的学习资料!

作者 | 乱敲代码

来源 | 公众号「乱敲代码」

前言

注解是在JDK1.5之后引入的新特性位于java.lang.annotation,注解其实就是对代码进行一种特殊的标记,这些标记可以在编译,类加载和运行时被读取,并执行相应的处理。本文主要分析如何自定义注解和注解的一些基础知识,然后在配合这AOP在实际运用中玩出新花样。

本文分为三部分

  • 注解分析

  • 自定义注解

    • 编译时注解

    • 运行时注解

  • 整合AOP

原本可以分为两篇文章,但是想来想去还是写一篇。趁热打铁。

注解分析

注解怎么运行的

想要自定义注解就要知道注解是怎么构成的,结合着项目中常用的注解来分析一下注解到底是怎么工作的。

看一下@Override注解 其主要作用是编译时进行格式检查。点进去看一下@Override实现。

点进去发现里面是空的除了两个元注解什么都没有,那么它到底是怎么实现的呢

其实@Override可以理解为是一个标签,它并没有实际的逻辑处理,而实现逻辑的就是注解的用户。它本质就是一个 『标记式注解』,仅被编译器可知 。

举个例子你的老板让你整理一下重要的文档,但是文档太多了你肯定需要把一下重要的文档给标记出来,然后你交给你老板的时候,老板会怎么做?老板当然是看到有标记的文档就去检查一下。

结合着上面的例子使用@Override注解的就是你,你的老板就是 JVM虚拟机,在编译的时候就是你的老板进行检查的时候,JVM发现了这个注解(标记)则就会进行处理 其处理机制主要是JVM内部处理。

总结下来就是:

定义注解,扫描注解,执行逻辑

元注解

在自定义注解之前我们要知道几个JDK为我们提供的“元注解”,元注解就是定义注解的注解,下面看看都有什么作用。

元注解一共有四个,都可以在java.lang.annotation下找到

  • @Target

  • @Retention

  • @Documented

  • @Inherited

@Target

@Target注解主要用于定义注解使用的位置,被描述的注解可以用在什么地方 。@Target的参数是ElementType枚举类,下面详解都有什么作用。

枚举???? 作用????
ElementType.PACKAGE 注解用在包
ElementType.TYPE 注解作用于类型(类,接口,注解,枚举)
ElementType.ANNOTATION_TYPE 注解作用于注解
ElementType.CONSTRUCTOR 注解作用于构造方法
ElementType.METHOD 注解作用于方法
ElementType.PARAMETER 注解作用于方法参数
ElementType.FIELD 注解作用于属性
ElementType.LOCAL_VARIABLE 注解作用于局部变量

@Target如果不设置范围的话默认可以作用于所有目标上面

看一下@Target的源码

看一下里面有一个Value参数,它的返回值为ElementType[] , ElementType就是上面的枚举类。

@Retention

@Retention注解的作用就是指定注解的生命周期。比如在编译时可以处理运行时可以处理等。它的枚举类为RetentionPolicy

枚举???? 作用????
RetentionPolicy.SOURCE 源码中保留,编译期可以处理
RetentionPolicy.CLASS Class文件中保留,Class加载时可以处理
RetentionPolicy.RUNTIME 运行时保留,运行中可以处理

@Retention的默认值为 RetentionPolicy.CLASS即在Class加载时处理

@Retention源码

@Documented

@Documented注解的话就比较简单,主要作用就是描述注解文档化。就是在 在生成javadoc的时候,是不包含注释的,但是如果注解被@Documented修饰,则生成的文档就包含该注解。此注解在以后版本可能会被删除这里就不详细的看了。

@Inherited

@Inherited 注解修饰的注解时具有可继承性的,就是说我们用 @Inherited 修饰了一个类,那么这个类的子类也会默认继承此注解。

源码

自定义注解

上面介绍了注解的元注解,那现在就开始实战自定义注解。

GIT项目地址:https://github.com/scramblecode/project-demos

和往常套路一样先创建项目,上面是本文章的示例可以下载下来看。

首先先写一个简单的例子。然后实战在SpringBoot中使用自定义注解加拦截器获取到请求参数。

简单定义注解

这里介绍两个例子 一个是编译时注解,第二个例子是运行时注解。最后在配合着SpringBoot+AOP写一个项目中非常实用的例子

编译时注解

创建编译时注解我们首先要创建一个依赖项目作为注解处理器。

首先先创建一个注解接口,使用IDEA创建可以选择创建注解。

在创建一个DataTest注解,这里定义注解的目的就是如果使用了该注解在编译时打印出Hello World!

然后编写注解处理器,这里使用的AbstractProcessor,本文只限简单使用,如果有机会写一篇文章研究AbstractProcessor

具体代码

然后需要创建META-INF文件,这里推荐使用谷歌的auto-service可以自动生成META-INF/services/javax.annotation.processing.Processor

加入依赖即可

<dependency><groupId>com.google.auto.service</groupId><artifactId>auto-service</artifactId><version>1.0-rc5</version>
</dependency>

定义完后在你的主项目引入注解处理器。在POM文件中加入本地注解处理器的依赖

添加完成之后创建一个简单的类,然后加上@DataTest注解

运行开始编译,就会发现控制台输出以下信息。

编译时注解可以写一些生成工具比如lombok这种生成代码的工具可以使用。

运行时注解

简单创建一个注解来获取被注解标识的名称和包路径。

首先创建注解,定义为运行时注解目标为类属性等。

使用注解

@GetClassName(value = "测试注解")
publicclass Student {
}

然后创建一个注解处理类,运行

控制台输出。

整合AOP

在Web开发中经常要输出日志,然后还有接口的运行时间。现在我们就用自定义注解加AOP实现这种功能。

首先把项目完善一下,增加一个测试接口

然后创建log注解。

然后定义切面类

@Aspect
@Component
@Slf4j
publicclass LoggerAspect {privatestaticfinal Logger logger = LoggerFactory.getLogger(LoggerAspect.class);@Pointcut("@annotation(com.lqcoder.annotationdemo.annotation.OutputLog)")public void weblog(){}@Around("weblog()")public Object around(ProceedingJoinPoint point) throws Throwable {long beginTime = System.currentTimeMillis();ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();List<Object> logArgs = Arrays.stream(point.getArgs()).filter(arg -> (!(arg instanceof HttpServletRequest) && !(arg instanceof HttpServletResponse))).collect(Collectors.toList());try {logger.info("请求url={}, 请求参数={}", request.getRequestURI(), JSON.toJSONString(logArgs));} catch (Exception e) {logger.error("请求参数获取异常", e);}Object result = point.proceed();//执行时长(毫秒)long time = System.currentTimeMillis() - beginTime;try {logger.info("请求耗时={}ms, 返回结果={}", time, JSON.toJSONString(result));} catch (Exception e) {logger.error("返回参数获取异常", e);}return result;}}

定义好之后重启项目,然后调用一下接口

运行结果可以看到已经生效。

本文通过OpenWrite的Markdown转换工具发布

关注我,回复“加群”加入各种主题讨论群

  • 通过这12张手绘图,搞懂什么是微服务架构

  • Redis 到底是怎么实现“附近的人”这个功能的呢?

  • Spring Boot构建多租户SaaS平台核心技术指南

  • 有了这个IDEA插件,从此不用再开Postman了

  • 7000字 Redis 超详细总结笔记总 | 收藏必备!

朕已阅 

自定义注解加AOP怎么玩?相关推荐

  1. 通过自定义注解与aop统一存储操作记录

    模块开发完成后,接到通知需要添加操作记录功能,看着那一堆接口,如果一个方法一个方法的加,那真是太麻烦了.为了偷懒,就百度了一下,发现可以通过自定义注解和aop的形式来统一添加操作记录,只需要在每个方法 ...

  2. 一个简单的例子,学习自定义注解和AOP

    转载自   一个简单的例子,学习自定义注解和AOP 记得今年年初刚开始面试的时候,被问的最多的就是你知道Spring的两大核心嘛?那你说说什么是AOP,什么是IOC?我相信你可能也被问了很多次了. 1 ...

  3. java aop注解日志记录_springMVC自定义注解,用AOP来实现日志记录的方法

    需求背景 最近的一个项目,在项目基本完工的阶段,客户提出要将所有业务操作的日志记录到数据库中,并且要提取一些业务的关键信息(比如交易单号)体现在日志中. 为了保证工期,在查阅了资料以后,决定用AOP+ ...

  4. java方法设置切点_如何通过自定义注解实现AOP切点定义

    面向切面编程(Aspect Oriented Programming, AOP)是面向对象编程(Object Oriented Programming,OOP)的强大补充,通过横切面注入的方式引入其他 ...

  5. 通过自定义注解,AOP,反射,Group分组编写适用于各层级通用性手动调用validate方法

    通过自定义注解,AOP,反射,group分组编写适用于[*Controller,*RemoteImpl,*ServiceImpl]通用性手动调用validate方法 拓展方式:该通用方法可扩展性,通用 ...

  6. 深入Spring:自定义注解加载和使用

    转自:https://blog.csdn.net/z69183787/article/details/53784845 前言 在工作中经常使用Spring的相关框架,免不了去看一下Spring的实现方 ...

  7. 自定义注解实现AOP

    什么是AOP AOP是面向切面编程.AOP是OOP的延续,而这里的切面则代表动态的将代码加入到指定的方法或位置上,一句话总结:在不改变原有代码的条件下,对该有功能进行扩展: AOP的作用 可以将日志记 ...

  8. SpringBoot自定义注解和aop

    自定义注解类编写的一些规则: 1定义一个注解Annotation 定义为@interface,所有的Annotation会自动继承java.lang.Annotation这一接口,并且不能再去继承别的 ...

  9. 自定义注解和AOP的结合

    下面的代码我想实现的功能是凡是加了@CacheLock 的注解都要进行上锁 package run.halo.app.cache.lock;import org.springframework.cor ...

最新文章

  1. 实战:使用TCP/IP筛选保护服务器安全
  2. python接口 同花顺_这是真的么 | 学会了用Python预测股票价格
  3. java空值转datetime,关于java1.8中LocalDateTime实现日期,字符串互转小坑。
  4. 最囧的国庆,是一种怎样的体验?
  5. fmin在Matlab中,MATLAB-fminsearch函数的使用
  6. 2.12 向量化的更多例子
  7. gan怎么输入一维数据_GAN评价指标最全汇总
  8. ios更新了系统无服务器,iPhone更新iOS 12.0.1系统失败怎么办?
  9. mysql批量写入redis_如何高效地向Redis插入大量的数据(推荐)
  10. creo二次开发python_使用C#/.net语言进行ProE/Creo二次开发
  11. 在沙箱中IE不能上网的解决方法
  12. python中if not x_python使用 'if x is not None' 还是'if not x is None' – IT热血青年
  13. Oracle数据库--从入门到装逼
  14. STM32 ADC多通道规则采样和注入采样
  15. python装饰器哪个好_[Python] 对 Python 装饰器的理解心得
  16. 获取汉字偏旁部首 Python版本
  17. 卡巴斯基导致SVN不能正常工作
  18. 从客户端到服务器端,适配微信iOS OpenSDK中的Universal Links
  19. 网站打开缓慢或打不开的原因
  20. 第二篇 - 设计篇:静馨舍app功能设计

热门文章

  1. centos7 ntp设置 时间同步
  2. python3 时间、日期、时间戳的转换
  3. golang 函数 传入返回 slice/map/struct 本质
  4. linux c open fopen freopen 文件操作函数
  5. Ntop性能提升方案
  6. Linux国内源介绍
  7. Cmake知识----编写CMakeLists.txt文件编译C/C++程序
  8. Android之 AndroidManifest.xml 文件解析
  9. Java学习之while语句
  10. java一段时间后执行一块代码_java自带的ScheduledExecutorService定时任务正常执行一段时间后部分任务不执行...