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功能.好了,你现在就有阅读源码的技术基础 ...
随机推荐
- 【转】Android7.0适配心得
本文出自:贾鹏辉的技术博客(http://www.devio.org) http://www.devio.org/2016/09/28/Android7.0%E9%80%82%E9%85%8D%E5% ...
- snmpwalk,iptables
-A RH-Firewall-1-INPUT -i lo -j ACCEPT -A INPUT -s 1.1.1.1 -p udp -d 2.2.2.2 --dport 161 -j ACCEPT - ...
- JSP中使用JDBC连接MySQL数据库的详细步骤
1,首先在自己新建的项目文本框中输入Web Project的名称,然后单击下一步. 2,继续单击下一步 3,把Generate web.xml deployment descriptor复选框勾上. ...
- ORACLE官网下载登陆账号能够使用
username: responsecool@sina.com password: abc123ABC http://www.oracle.com/index.html
- test zhenai
web.Document.InvokeScript("eval",new string[]{"document.getElementById('passwordbt'). ...
- [c#]记一次实验室局域网的ARP欺骗
起因 某天中午午睡时,笔者被激烈的键盘和鼠标声音吵醒,发现实验室的同学在那边忘我地打LOL,顿觉不爽,于是决定整他一下.想了一下之后觉得就让他掉线一下作为惩罚好了.结合以往的理论知识,大家在同一个局域 ...
- python 网络爬虫requests模块
一.requests模块 requests模块是python中原生的基于网络请求的模块,其主要作用是用来模拟浏览器发起请求.功能强大,用法简洁高效. 1.1 模块介绍及请求过程 requests模块模 ...
- 4、Docker数据管理
一.挂载类型 1.volumes Docker管理宿主机文件系统的一部分(/var/lib/docker/volumes).保存数据的最佳方式. 使用场景:将容器中的数据持久化到宿主机,比如容器是my ...
- 萌新程序媛的首个作品,基于NoSQL的内容管理及低码开发平台
尽管入行有一段时间了,但之前还从来没想过要开发一款完整的软件产品.这个我跟朋友开发的第一款软件,希望大家帮我们多宣传推广.首个版本肯定有很多的不足,大家也给我们多提意见,还有很多规划中的功能要在之后的 ...
- mark一下岗位
一.中国移动杭州研发中心——测试开发工程师 https://campusresume.zhaopin.com/resume/14375/1 等内推信息 岗位描述:作为产品的质量守护者,在全面理解被 ...