java自定义注解学习(三)_注解解析及应用
上篇文章已经介绍了注解的基本构成信息。这篇文章,主要介绍注解的解析。毕竟你只声明了注解,是没有用的。需要进行解析。主要就是利用反射机制在运行时进行查看和利用这些信息
常用方法汇总
在Class、Field、Method、Constructor中都有如下方法:
//获取所有的注解
public Annotation[] getAnnotations()
//获取所有本元素上直接声明的注解,忽略inherited来的
public Annotation[] getDeclaredAnnotations()
//获取指定类型的注解,没有返回null
public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
//判断是否有指定类型的注解
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
Annotation 是一个借口,它表示注解,源码为:
public interface Annotation {
boolean equals(Object obj);
int hashCode();
String toString();
//返回真正的注解类型
Class<? extends Annotation> annotationType();
}
实际上,所有的注解类型、内部实现时,都是扩展的Annotation
对于Method和Contructor,他们都有方法参数
public Annotation[][] getParameterAnnotations()
应用注解
日常工作中,每个公司都会自定义注解进行记录日志的,我们就做一个简单的记录日志操作的注解,结合aop和springboot
1.建立springboot项目
这里不再赘述,主要需要引入aop
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2.定义自定义注解
package com.kevin.anno.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface KevinLog {
String value() default "";
}
3.定义aspect及解析注解
package com.kevin.anno.aspect;
import com.kevin.anno.annotation.KevinLog;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
@Aspect
@Component
public class LogAscpect {
private final static Logger logger = LoggerFactory.getLogger(LogAscpect.class);
@Pointcut("@annotation(com.kevin.anno.annotation.KevinLog)")
public void log() {
}
@Around("log()")
public Object aroundAdvice(ProceedingJoinPoint point) throws Throwable {
Object object = null;
long start = System.currentTimeMillis();
Method method = ((MethodSignature) MethodSignature.class.cast(point.getSignature())).getMethod();
KevinLog kevinLog = method.getAnnotation(KevinLog.class);
String operationName = kevinLog.value();
object = point.proceed(point.getArgs());
long end = System.currentTimeMillis();
Long excuteTime = end - start;
print(operationName, excuteTime, point);
return object;
}
private void print(String operationName, Long excuteTime, ProceedingJoinPoint point) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//operationName
logger.info("operationName={}", operationName);
//time
logger.info("time={}", excuteTime);
// url
logger.info("url={}", request.getRequestURL());
//method
logger.info("method = {}", request.getMethod());
//ip
logger.info("ip = {}", request.getRemoteAddr());
//类方法
logger.info("class_method={}", point.getSignature().getDeclaringTypeName() + "." + point.getSignature().getName());
//参数
logger.info("args = {}", point.getArgs());
}
}
4. 在请求方法上加上自定义注解
package com.kevin.anno.controller;
import com.kevin.anno.annotation.KevinLog;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping(value = "/hello")
@KevinLog("kevin test !")
public String hello() {
return "hello kevin";
}
}
5.启动测试
访问:http://localhost:8080/hello
页面出现:hello kevin
控制台打印信息如下:
2018-10-22 10:38:22.456 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno : operationName=kevin test !
2018-10-22 10:38:22.456 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno.aspect.LogAscpect : time=7
2018-10-22 10:38:22.456 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno.aspect.LogAscpect : url=http://localhost:8080/hello
2018-10-22 10:38:22.456 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno.aspect.LogAscpect : method = GET
2018-10-22 10:38:22.457 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno.aspect.LogAscpect : ip = 0:0:0:0:0:0:0:1
2018-10-22 10:38:22.457 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno.aspect.LogAscpect : class_method=com.kevin.anno.controller.HelloController.hello
2018-10-22 10:38:22.457 INFO 3916 --- [nio-8080-exec-2] com.kevin.anno.aspect.LogAscpect : args = {}
总结
其实, 大家可以自己写这玩玩,比较这个demo还用到了aop,工作中很少接触到aop。以至于面试的时候,问你aop的时候,自己都没有实际的应用过。
好了。玩的开心!
java自定义注解学习(三)_注解解析及应用的更多相关文章
- Java编程思想学习(十五) 注解
注解Annotation又叫元数据,是JDK5中引入的一种以通用格式为程序提供配置信息的方式.使用注解Annotation可以使元数据写在程序源码中,使得代码看起来简洁,同时编译器也提供了对注解Ann ...
- Django基础学习三_路由系统
今天主要来学习一下Django的路由系统,视频中只学了一些皮毛,但是也做下总结,主要分为静态路由.动态路由.二级路由 一.先来看下静态路由 1.需要在project中的urls文件中做配置,然后将匹配 ...
- spring boot 学习(三)API注解记录及测试
spring boot API注解记录及测试 部分注解解析 @Controller : 修饰创建处理 http 处理对象,一般用于页面渲染时使用. @RestController : Json数据交互 ...
- Java注解【三、注解的分类】
按运行机制分 源码注解 只在源码中存在 编译时注解 在class中依然存在,如@Deprecated 运行时注解 运行阶段起作用,如@Autowired 按来源分 JDK自带注解 三方注解 最常见 自 ...
- Android自定义View(三、深入解析控件测量onMeasure)
转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51490283 本文出自:[openXu的博客] 目录: onMeasure什么时候会被调用 ...
- 写给自己的Java程序员学习路线图_转载
如下是我做开发这三年经常使用一些技术和工具,当然这些技术也都是需要加强的(有些是我一直使用的,不过不深入,有些内部的原理等等不是很清楚) 前端部分: 1)HTML:网页的核心语言,构成网页的基础 2) ...
- 浅谈Java的主要学习要点_上海尚学堂java培训课程思维导图
Java是一种可以撰写跨平台应用程序的面向对象的程序设计语言.Java 技术具有卓越的通用性.高效性.平台移植性和安全性,广泛应用于PC.数据中心.游戏控制台.科学超级计算机.移动电话和互联网,同时拥 ...
- Java并发编程学习:volatile关键字解析
转载:https://www.cnblogs.com/dolphin0520/p/3920373.html 写的非常棒,好东西要分享一下 Java并发编程:volatile关键字解析 volatile ...
- JAVA多线程基础学习三:volatile关键字
Java的volatile关键字在JDK源码中经常出现,但是对它的认识只是停留在共享变量上,今天来谈谈volatile关键字. volatile,从字面上说是易变的.不稳定的,事实上,也确实如此,这个 ...
- Java 源码学习线路————_先JDK工具包集合_再core包,也就是String、StringBuffer等_Java IO类库
http://www.iteye.com/topic/1113732 原则网址 Java源码初接触 如果你进行过一年左右的开发,喜欢用eclipse的debug功能.好了,你现在就有阅读源码的技术基础 ...
随机推荐
- ubuntu系统中Qt creator 编辑和应用使用中文输入法
在ubuntu系统的GUI开发过程中遇到在编辑器里面不能使用中文输入法,前提我已经安装了搜狗输入法,但是还是不能使用,原因是QT的库里没有最新fcix的库,. 没有安装搜狗的输入法的 https:// ...
- 缩点tarjan
给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和.允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次. 缩点含义:将一个环缩成 ...
- Intel 面试(就不该报外企,英语是硬伤)
1 自我介绍(用英文) 啊啊啊,能不能用中文啊,最好用英文,蒙了.... 2 你对硬件了解吗,对X86系统了解吗,知道CPU是怎么处理读一个数据的吗,说说cpu从读一个数据,到内存怎么进行处理? 说的 ...
- 在 R 中估计 GARCH 参数存在的问题
目录 在 R 中估计 GARCH 参数存在的问题 GARCH 模型基础 估计 GARCH 参数 fGarch 参数估计的行为 结论 译后记 在 R 中估计 GARCH 参数存在的问题 本文翻译自< ...
- 20155213免考项目——bof进阶及简易的HIDAttack
20155213免考项目--bof进阶及简易的HIDAttack 目录 序 任务一:构造Shellcode(64位) 任务二:64位Shellcode的注入 任务三:32位及64位bof攻击(开启堆栈 ...
- 网络对抗技术 2017-2018-2 20152515 Exp1 PC平台逆向破解 笔记
Exp1 PC平台逆向破解 1.堆栈不可保护: ROP 2.alsr 随机化: 填充NOPS "\90" 3.不加堆栈保护 shellcode: 1.不依赖外部函数 2.不含\00 ...
- UWP-开发一个具有闹钟,天气预报,翻译,语音功能的Demo
UWP即Windows 10中的Universal Windows Platform简称.即Windows通用应用平台,在Windows 10 Mobile/Surface(Windows平板电脑)/ ...
- 洛谷 P3302 [SDOI2013]森林
->题目链接 题解: #include<queue> #include<cstdio> #include<cstring> #include<iostr ...
- vsftp在防火墙开启需要开放的端口
1.开放tcp端口 firewall-cmd --zone=public --add-port=20/tcp --permanent firewall-cmd --zone=public --add- ...
- OD之绕过序列号验证(二)
上次是修改程序的标题,大家应该感觉这只是一个起点而已,接下来我们可以尝试绕过序列号验证,这种技术应用在很多软件中,比如淘宝上要买什么的软件,商家都会发给`你一个用户名和密码,而且还有试用期什么的,这确 ...