Java注解是一系列元数据,它提供数据用来解释程序代码,但是注解并非是所解释的代码本身的一部分。注解对于代码的运行效果没有直接影响。

网络上对注解的解释过于严肃、刻板,这并不是我喜欢的风格。尽管这样的解释听起来非常的专业。

为了缓解大家对“注解”的陌生感,我来说点有意思的。其实我对“注解”这个词的第一印象并不是Java的注解,而是朱熹的名作《四书章句集注》。为什么我会有这么大的脑洞呢?因为当我试着去翻译Annotation这个单词的时候,得到的结果是“注释”而不是“注解”。《四书章句集注》正是朱熹对《大学》、《中庸》、《论语》、《孟子》四书做出的重要的注释。要知道,该书可是明清以后科举考试的题库和标准答案!

注解(Annotation)是在 Java SE 5.0 版本中开始引入的概念,同classinterface一样,也属于一种类型。很多开发人员认为注解的地位不高,但其实不是这样的。像@Transactional@Service@RestController@RequestMapping@CrossOrigin等等这些注解的使用频率越来越高。

01、为什么要使用注解呢?

为什么要使用注解呢?让我们从另外一个问题说起。

“跨域”这两个字就像一块狗皮膏药黏在每一个前端开发者的身上;我也不例外,虽然我并不是一个纯粹的前端开发者。

跨域问题的出现,源于浏览器的同源策略——限制一个源加载的脚本去访问另外一个源的资源,可有效地隔离潜在的恶意文件,是一种重要的安全机制。

跨域问题

跨域问题的解决方案也有很多,比如说:

1)JSONP

2)Nginx代理

3)"跨域资源共享"(Cross-origin resource sharing),简称CORS,可以说是处理跨域问题的标准做法。

记得第一次遇到跨域问题的时候,我特意向一个同学请教了解决方案,他告诉我的答案如下。

第一步,在web.xml添加filter。

<filter><filter-name>contextfilter</filter-name><filter-class>com.cmower.filter.WebContextFilter</filter-class>
</filter>
<filter-mapping><filter-name>contextfilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>

第二步,实现WebContextFilter类。

public class WebContextFilter implements Filter {@Overridepublic void destroy() {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {HttpServletResponse  httpServletResponse = (HttpServletResponse) response;httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");httpServletResponse.setHeader("Access-Control-Allow-Headers", "accept,content-type"); httpServletResponse.setHeader("Access-Control-Allow-Methods", "OPTIONS,GET,POST,DELETE,PUT"); chain.doFilter(request, httpServletResponse);}@Overridepublic void init(FilterConfig arg0) throws ServletException {}}

看到这样的解决方案,我真的是蛮崩溃的。不就一个跨域问题嘛,用得着这么多代码吗?

我对这样的解决方案非常的不满意。于是下定决心要好好的研究一番,大概花了半天的时间吧,我终于搞清楚了“跨域”问题,以及它的标准解决方案CORS。并且找到了一个极为简洁的解决方案——@CrossOrigin,只要在Controller类上加上这个注解,就可以轻松地解决跨域问题。

代码如下。

@RestController
@RequestMapping("course")
@CrossOrigin
public class CourseController {
}

如果没有找到@CrossOrigin这个注解,我真的就要按照同学提供的方案去解决跨域的问题了。但那样做就好像,我们卖掉家里的小汽车,然后出行的时候驾一辆马车一样。

这也正是我想告诉你的,为什么要使用注解的原因:它让我们的代码看起来更简洁,更有时代的进步感。

02、该如何定义注解呢?

注解需要通过@interface关键字(形式和接口非常的相似,只是前面多了一个@)进行定义。我们可以打开@CrossOrigin的源码来看一下。

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrigin {/*** List of allowed origins, e.g. {@code "http://domain1.com"}.* <p>These values are placed in the {@code Access-Control-Allow-Origin}* header of both the pre-flight response and the actual response.* {@code "*"} means that all origins are allowed.* <p>If undefined, all origins are allowed.* @see #value*/@AliasFor("value")String[] origins() default {};/*** List of request headers that can be used during the actual request.* <p>This property controls the value of the pre-flight response's* {@code Access-Control-Allow-Headers} header.* {@code "*"}  means that all headers requested by the client are allowed.* <p>If undefined, all requested headers are allowed.*/String[] allowedHeaders() default {};/*** List of supported HTTP request methods, e.g.* {@code "{RequestMethod.GET, RequestMethod.POST}"}.* <p>Methods specified here override those specified via {@code RequestMapping}.* <p>If undefined, methods defined by {@link RequestMapping} annotation* are used.*/RequestMethod[] methods() default {};
}

从上面的代码可以看得出来,“注解”真的很“注解”,除了注释多和“元注解”多之外,真没有别的了。

“元注解”?什么是“元注解”呢?

“元注解”是用来注解(动词)注解(名词)的注解(名词)。请感受汉语的博大精深。@Target@Retention@Documented就是所谓的元注解。

1)@Target

Target是目标的意思,@Target指定了注解运用的场景。都有哪些场景值呢?

  • ElementType.ANNOTATION_TYPE:可以给注解进行注解

  • ElementType.CONSTRUCTOR:可以给构造方法进行注解

  • ElementType.FIELD:可以给字段进行注解

  • ElementType.LOCAL_VARIABLE:可以给局部变量进行注解

  • ElementType.METHOD:可以给方法进行注解

  • ElementType.PACKAGE:可以给包进行注解

  • ElementType.PARAMETER:可以给方法内的参数进行注解

  • ElementType.TYPE:可以给类型进行注解,比如类、接口和枚举

2)@Retention

Retention这个单词的意思为保留期。也就是说,当@Retention应用到一个注解上的时候,它解释说明了这个注解的存活时间。来看它的取值范围。

  • RetentionPolicy.SOURCE:注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。

  • RetentionPolicy.CLASS:注解只被保留到编译进行的时候,并不会被加载到 JVM 中。

  • RetentionPolicy.RUNTIME:注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。

3)@Documented

Documented就比较容易理解,它和文档有关。作用就是能够将注解中的元素包含到 Javadoc 中。

当我们了解了元注解的概念后,再回头看一下@CrossOrigin的源码,是不是感觉清晰多了呢?

如果能够细致地读一读源码中的注释,你就会看到WebContextFilter类中出现的关键字,诸如Access-Control-Allow-OriginAccess-Control-Allow-HeadersAccess-Control-Allow-Methods。也就是说,当我们通过@CrossOrigin对Controller类注解后,SpringMVC就能够在运行时对这个类自动加上解决跨域问题的过滤器。

03、注解可以反射吗?

注解是可以通过反射获取的。

1)可以通过 Class 对象的 isAnnotationPresent() 方法判断该类是否应用了某个指定的注解。

2)通过 getAnnotation() 方法来获取注解对象。

3)当获取到注解对象后,就可以获取使用注解时定义的属性值。

示例如下:

@CrossOrigin(origins = "http://qingmiaokeji.com", allowedHeaders = "accept,content-type", methods = { RequestMethod.GET, RequestMethod.POST })
public class TestController {public static void main(String[] args) {Class c = TestController.class;if (c.isAnnotationPresent(CrossOrigin.class)) {CrossOrigin crossOrigin = (CrossOrigin) c.getAnnotation(CrossOrigin.class);System.out.println(Arrays.asList(crossOrigin.allowedHeaders()));System.out.println(Arrays.asList(crossOrigin.methods()));System.out.println(Arrays.asList(crossOrigin.origins()));}}
}// 输出:[accept,content-type]
// [GET, POST]
// [http://qingmiaokeji.com]

04、注解经常用在哪里呢?

1)@Transactional:Spring 为事务管理提供的功能支持。

2)@ Service:Spring在进行包扫描的时候,会自动将这个类注册到Spring容器中。

3)@RestController:是@ResponseBody@Controller的组合注解。

也就是说,下面这段代码与下下面的代码等同。

@RestController
public class HelloController {@RequestMapping(value="hello")public String sayHello(){return "hello";}
}
@Controller
@ResponseBody
public class HelloController {@RequestMapping(value="hello")public String sayHello(){return "hello";}
}

4)@RequestMapping :Spring Web 应用程序中最常用到的注解之一,将 HTTP 请求映射到 MVC 和 REST 控制器的处理方法上。

5)@Select:MyBatis提供的查询语句注解。示例如下:

@Select("select * from city")
List<City> getCitys();

6)还有很多很多,就不再一一列举了。

最后

我想说的是,注解有许多用处,主要有:

  • 提供信息给编译器: 编译器可以利用注解来探测错误和警告信息。

  • 编译阶段时的处理:  软件工具可以利用注解信息来生成代码、HTML文档。

  • 运行时的处理:  某些注解可以在程序运行的时候接受代码的提取。

别忘了:

四书章句集注

近期热点推荐

Java 最常见的 200+ 面试题

Java 200+ 面试题补充③ Dubbo 模块

Java 200+ 面试题补充② Netty 模块

Java 200+ 面试题补充 ThreadLocal 模块

面试题 == 和 equals 的区别

面试经验分享|精华篇

精美简历合集II

精美简历合集I

彻底搞懂 Java 中的注解 Annotation相关推荐

  1. java 自旋锁_搞懂Java中的自旋锁

    轻松搞懂Java中的自旋锁 前言 在之前的文章<一文彻底搞懂面试中常问的各种"锁">中介绍了Java中的各种"锁",可能对于不是很了解这些概念的同学 ...

  2. Java中的注解(Annotation)处理器解析

    Java中的注解(Annotation)是一个很神奇的东西,特别现在有很多Android库都是使用注解的方式来实现的.一直想详细了解一下其中的原理.很有幸阅读到一篇详细解释编写注解处理器的文章.本文的 ...

  3. Java中的注解--annotation

    Java中的基本注解,几乎框架中的注解都是依赖Java中的基本注解,很有必要学习一下Java中的基本注解...jdk 5 增加的新特性 一.注解的定义以及Java中常见的注解 注解就相当于一种标记,加 ...

  4. 一句话搞懂Java中this和super的实现原理

    写在前面 本文隶属于专栏<100个问题搞定Java虚拟机>,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和文献引用请见100个问题搞定Java ...

  5. 四十七、面试前,必须搞懂Java中的线程池ThreadPoolExecutor(上篇)

    @Author:Runsen @Date:2020/6/9 人生最重要的不是所站的位置,而是内心所朝的方向.只要我在每篇博文中写得自己体会,修炼身心:在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰 ...

  6. 一文彻底搞懂Java中的值传递和引用传递!

    关于Java中方法间的参数传递到底是怎样的.为什么很多人说Java只有值传递等问题,一直困惑着很多人,甚至我在面试的时候问过很多有丰富经验的开发者,他们也很难解释的很清楚. 我很久也写过一篇文章,我当 ...

  7. java中编码问题_[干货预警]一次搞懂Java中的编码问题

    编码问题一直是一个困扰程序员的问题,尤其是对于java程序员.因为java的跨平台特性,经常需要在多个编码之间进行转换. 下面详细讲一讲java中的编码问题 一.为什么要编码 长话短说,原因如下: 1 ...

  8. 来吧,一文彻底搞懂Java中最特殊的存在——null

    没事的时候,我并不喜欢逛 P 站,而喜欢逛 programcreek 这些技术型网站,于是那天晚上,在夜深人静的时候,我就发现了一个专注基础但不容忽视的主题.比如说:Java 中的 null 到底是什 ...

  9. 教妹学Java(九):一文搞懂Java中的基本数据类型

    大家好,我是沉默王二,一个和黄家驹一样身高,和刘德华一样颜值的程序员.本篇文章通过我和三妹对话的形式来谈一谈"Java 中的数据类型". 教妹学 Java,没见过这么有趣的标题吧? ...

最新文章

  1. 人脸识别再遭弃用,美国之后这回轮到欧盟
  2. os项目icon和default 等相关图标命名规则和大小设置
  3. 剑指offer:变态跳台阶
  4. java在容器中导入图片_Java程序员必学技术:@Import直接导入类,在容器@Configuration、@Component中是怎么直接导入类注册到容器的?...
  5. CF1497E2 Square-free division (hard version)
  6. Win11系统使用Excel表格的时候很卡怎么办
  7. 消息队列解耦是骗小孩儿的
  8. 19电子设计速成实战宝典pdf_开发宝典丛书:Visual C++编程实战宝典PDF
  9. Selenium Automated test 's Installation environment
  10. 容器时代的DevOps部署-普元DevOps
  11. 太赞了! 豆瓣9.3分的《Linux 命令行大全》.pdf 限时下载
  12. 协同过滤推荐算法总结(转载)
  13. Audition CC 2019 Essential Training AuditionCC 2019基本训练 Lynda课程中文字幕
  14. 嗖嗖移动业务大厅项目_会员合作项目:10086移动外呼业务
  15. 对话仟峰资本Steven:DeFi大赢家是怎样炼成的 |链捕手
  16. stunserver 的几个公网地址及其问题
  17. 大学英语四级考试必读必备
  18. pygame小游戏开发 - 冰雪英雄会
  19. TF-IDF的原理概述
  20. Minecraft神奇玩家不用键盘,行走全部靠骑猪最后通关MC

热门文章

  1. logstash-input-redis插件使用详解
  2. MIP改造常见问题二十问
  3. go反射机制与类型识别
  4. Angular6_PWA
  5. 智慧园区-楼宇建模技巧之【建楼篇】
  6. DevOps平台中的自动化部署框架设计
  7. postgresql(2)
  8. 系统起动时加载的过程
  9. DirectX 矩阵
  10. PHP高并发高负载系统架构