上篇文章已经介绍了注解的基本构成信息。这篇文章,主要介绍注解的解析。毕竟你只声明了注解,是没有用的。需要进行解析。主要就是利用反射机制在运行时进行查看和利用这些信息

常用方法汇总

在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自定义注解学习(三)_注解解析及应用的更多相关文章

  1. Java编程思想学习(十五) 注解

    注解Annotation又叫元数据,是JDK5中引入的一种以通用格式为程序提供配置信息的方式.使用注解Annotation可以使元数据写在程序源码中,使得代码看起来简洁,同时编译器也提供了对注解Ann ...

  2. Django基础学习三_路由系统

    今天主要来学习一下Django的路由系统,视频中只学了一些皮毛,但是也做下总结,主要分为静态路由.动态路由.二级路由 一.先来看下静态路由 1.需要在project中的urls文件中做配置,然后将匹配 ...

  3. spring boot 学习(三)API注解记录及测试

    spring boot API注解记录及测试 部分注解解析 @Controller : 修饰创建处理 http 处理对象,一般用于页面渲染时使用. @RestController : Json数据交互 ...

  4. Java注解【三、注解的分类】

    按运行机制分 源码注解 只在源码中存在 编译时注解 在class中依然存在,如@Deprecated 运行时注解 运行阶段起作用,如@Autowired 按来源分 JDK自带注解 三方注解 最常见 自 ...

  5. Android自定义View(三、深入解析控件测量onMeasure)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51490283 本文出自:[openXu的博客] 目录: onMeasure什么时候会被调用 ...

  6. 写给自己的Java程序员学习路线图_转载

    如下是我做开发这三年经常使用一些技术和工具,当然这些技术也都是需要加强的(有些是我一直使用的,不过不深入,有些内部的原理等等不是很清楚) 前端部分: 1)HTML:网页的核心语言,构成网页的基础 2) ...

  7. 浅谈Java的主要学习要点_上海尚学堂java培训课程思维导图

    Java是一种可以撰写跨平台应用程序的面向对象的程序设计语言.Java 技术具有卓越的通用性.高效性.平台移植性和安全性,广泛应用于PC.数据中心.游戏控制台.科学超级计算机.移动电话和互联网,同时拥 ...

  8. Java并发编程学习:volatile关键字解析

    转载:https://www.cnblogs.com/dolphin0520/p/3920373.html 写的非常棒,好东西要分享一下 Java并发编程:volatile关键字解析 volatile ...

  9. JAVA多线程基础学习三:volatile关键字

    Java的volatile关键字在JDK源码中经常出现,但是对它的认识只是停留在共享变量上,今天来谈谈volatile关键字. volatile,从字面上说是易变的.不稳定的,事实上,也确实如此,这个 ...

  10. Java 源码学习线路————_先JDK工具包集合_再core包,也就是String、StringBuffer等_Java IO类库

    http://www.iteye.com/topic/1113732 原则网址 Java源码初接触 如果你进行过一年左右的开发,喜欢用eclipse的debug功能.好了,你现在就有阅读源码的技术基础 ...

随机推荐

  1. PNS settings

    Before PNS,some settings should be ready: firstly,make sure that the power/ground nets exist,if not, ...

  2. .NET批量操作窗口样式

    1. 背景 我们在开发过程中,可能会遇到需要批量控制程序中窗体的大小或其它一些操作, 这些窗体有可能是属于程序本身的,也许是其它程序的窗口.本文就是基于此的一篇关于如何批量操作窗口样式的,我们主要是通 ...

  3. JAVA框架 Spring 引入多个配置文件

    1.如果配置文件比较长,可以分多个配置文件.有两种方式: 1)在主配置文件加标签<import/> <import resource="jd/com/other/appli ...

  4. JAVA框架:hibernate

    一:介绍 hibernate是java中的dao层,即和持久层打交道.底层也是数据库驱动.连接等.他也有orm,类和数据库的映射. 二.部署 下载地址:https://sourceforge.net/ ...

  5. Android 在测试阶段当出现多个测试服务器地址时打包的小技巧

    前提:服务端没有做特殊处理 在开发android网络客户端项目时,不可避免的会用到“测试服务器地址”和“云端服务器地址”等.(有时可能会有多个) 这时在打包给测试那帮哥们时,你就需要一个服务器地址打上 ...

  6. 【本地服务器】利用openssl生成证书

    (一)下载openssl软件,解压,进入bin目录 下载地址 (二)1.在当前bin目录,按住shift键右击,选择"在此处打开命令窗口" 2.打开cmd命令窗口之后,在窗口中输入 ...

  7. 一个有趣的异步时序逻辑电路设计实例 ——MFM调制模块设计笔记

    本文从本人的163博客搬迁至此. MFM是改进型频率调制的缩写,其本质是一种非归零码,是用于磁介质硬盘存储的一种调制方式.调制规则有两句话,即两个翻转条件: 1.为1的码元在每个码元的正中进行一次翻转 ...

  8. EZ 2018 05 06 NOIP2018 慈溪中学集训队互测(五)

    享受爆零的快感 老叶本来是让初三的打的,然后我SB的去凑热闹了 TM的T2写炸了(去你妹的优化),T1连-1的分都忘记判了,T3理所当然的不会 光荣革命啊! T1 思维图论题,CHJ dalao给出了 ...

  9. 阿里云代金券 - 双12疯了~~~ 4核8G 3M带宽只要1890元/3年

    阿里云双12大促简直疯了,4核8G 3M带宽只要1890元/3年,比双11疯狂多了,双11没有上车的赶快来买吧!!! 前去阿里云双12活动页面 截图如下: 从截图中可以看出,不仅4核8G降到了地板,1 ...

  10. libgdx学习记录7——Ui

    libgdx中的UI设计主要通过其对应的Style类进行实现,也可以通过skin实现.如果没有编辑好的skin文件,可以创建一个默认的skin,再添加已经设计好的style类即可,然后在需要使用的地方 ...