惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
Y
Y Combinator Blog
Cisco Talos Blog
Cisco Talos Blog
T
Threatpost
T
Tor Project blog
I
Intezer
T
Threat Research - Cisco Blogs
L
LINUX DO - 热门话题
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
L
Lohrmann on Cybersecurity
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
The Last Watchdog
The Last Watchdog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
P
Privacy & Cybersecurity Law Blog
N
News | PayPal Newsroom
N
News and Events Feed by Topic
C
CERT Recently Published Vulnerability Notes
T
Tenable Blog
K
Kaspersky official blog
V
Visual Studio Blog
T
Troy Hunt's Blog
Project Zero
Project Zero
博客园_首页
The Register - Security
The Register - Security
O
OpenAI News
G
Google Developers Blog
Simon Willison's Weblog
Simon Willison's Weblog
J
Java Code Geeks
D
DataBreaches.Net
F
Full Disclosure
Latest news
Latest news
C
CXSECURITY Database RSS Feed - CXSecurity.com
S
Security Affairs
Recent Commits to openclaw:main
Recent Commits to openclaw:main
腾讯CDC
有赞技术团队
有赞技术团队
Hacker News - Newest:
Hacker News - Newest: "LLM"
阮一峰的网络日志
阮一峰的网络日志
C
Cisco Blogs
Vercel News
Vercel News
V
Vulnerabilities – Threatpost
月光博客
月光博客
Hacker News: Ask HN
Hacker News: Ask HN
B
Blog RSS Feed
P
Palo Alto Networks Blog
Stack Overflow Blog
Stack Overflow Blog
The Cloudflare Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
G
GRAHAM CLULEY

技术改变视野

为程序员、设计师打造的摸鱼社区:摸鱼派! - 技术改变视野 大白话 | Java初学指♂男:“说说初学的误区与死结”( 壹 | 反射与Field ) - 技术改变视野 大白话之耦合性:什么是耦合性和内聚性?用编程语言实例讲解! - 技术改变视野 🎨 适用于 Solo / Bolo 的清新高级主题 —— Sakura | 移植自 WordPress 主题 - 技术改变视野 我在 GitHub 上的开源项目 - 技术改变视野 为IDEA/Git配置GPG密钥,点亮GitHub Verified Commit标识 - 技术改变视野 从 SpringMVC 转为使用 SpringBoot —— 手把手带你使用 Intellij IDEA 最快速地搭建 SpringBoot+MyBatis(无 XML)+Thymeleaf - 技术改变视野 无题 - 技术改变视野 年轻人的第一辆京牌电动车 - 技术改变视野 我们忙碌且漫长的一生,有多久是为自己而活? - 技术改变视野 一个最简单的实例理解Semaphore在Java中的作用 - 技术改变视野 说说《后浪》 - 技术改变视野 离线使用 Google Fonts:让你的网站更精致 | goofoffline 神器,一键下载生成离线字体库! - 技术改变视野 实例带你学会简单的Java Thread多线程 - 技术改变视野 一个实例理解Java的接口(interface)用处与用法 - 技术改变视野 一个实例带你理解JavaBean - 技术改变视野 WebFilter-SpringBoot过滤器注解实例讲解 - 技术改变视野 实例带你搞懂Java多线程&&线程池之(壹):线程池与多线程的关系和区别 - 技术改变视野 实例带你搞懂Java多线程&&线程池之(贰):简单的线程池应用 - 技术改变视野 实例带你获取多线程Thread的返回值之 (壹) - Callable的运行 - 技术改变视野 实例带你获取多线程Thread的返回值之 (贰) - Callable配合线程池返回数据 - 技术改变视野 一个实例理解Java Runnable多线程用处与用法 - 技术改变视野 从零开始OpenSSL之 (壹) - 使用genrsa、rsa、rsautl生成公私钥 - 技术改变视野 从零开始 OpenSSL 之 (贰) - 使用 rsautl 解密文件 - 技术改变视野 大白话之Docker(壹):快速入门&&简单官方实例 - 技术改变视野 大白话之Docker(贰):简单部署一个Tomcat服务并发布内容 - 技术改变视野 大白话之从零讲解DVWA(壹)-SQL注入(SQL Injection) Low Level - 技术改变视野 大白话之从零讲解DVWA(贰)-SQL注入(SQL Injection) Medium/High Level - 技术改变视野 Java日志插件-Slog4J下载 - 技术改变视野 大白话之必会Java Atomic | 线程一点也不安全(一):比自增和synchronized更快速、靠谱的原子操作(调用C语言) - 技术改变视野 Log-MySQL root用户登录后无法查看数据库全部表/正常访问数据库 Access denied for user 'root'@'localhost' to database - 技术改变视野 大白话之Docker(叁):制作一个运行Tomcat服务端的Docker镜像 - 技术改变视野 Github仅保留指定文件/文件夹当前Commit,删除所有历史记录,清除「敏感信息」 - 技术改变视野 将Tomcat、MySQL从Linux迁移到Windows的心路历程(干货):令人恐惧的字符编码 - 技术改变视野 Spring: java.lang.NoSuchMethodError: clearCache | ClassNotFoundException | Error during artifact deployment 思路及解决办法 - 技术改变视野 大白话之Java反射-初学最迷的概念:能干啥?咋用? - 技术改变视野 大白话之Java面向接口编程:最“正经”的中文实例讲解,看不懂来打我! - 技术改变视野 大白话 | 课堂实践:使用Iterator对数组进行遍历 - 技术改变视野 大白话之fail-fast | fail-safe:为什么会有这个机制?它有什么作用? - 技术改变视野 大白话之必会Java Atomic | 线程一点也不安全(二):Atomic的ABA问题会导致什么情况?如何解决? - 技术改变视野 随笔 | 奇淫技巧 | Java:记return和短路运算符的妙用 - 技术改变视野 随笔 | Tomcat:续-从Linux迁移到Windows编码问题彻底解决 - 技术改变视野 大白话之AutoClosable接口 | try-with-resources:JDK1.7的新特性,提高重复回收效率 - 技术改变视野 大白话之Java多线程join方法:开局一张图,试学一分钟,你就费和我一样,理解介个方法 - 技术改变视野 大白话之Java Stream流:将类数组流化,便捷批量修改,通俗讲解! - 技术改变视野 Java 困扰三周の问题:使用byte[]或skip()方法读取字节流Stream文件尾部多/少/缺字节解决方法 - 技术改变视野 大白话之Java级联调用:一个类,一条语句,同时调用好几个方法,串成一串 - 技术改变视野
刨根问底 | 大白话:在使用注解后,框架是怎么知道你哪个方法使用了注解的?用@RequestMapping注解举例详解! - 技术改变视野
adlered · 2019-12-09 · via 技术改变视野

前言

阅读本篇文章,你需要理解以下的知识:

  • 重要:反射 (参考
  • Java enum
  • 接口的使用
  • 了解注解是什么、该什么时候使用
  • 最好接触过Spring(因为用@RequestMapping举例)

先说说注解

如果你熟悉Spring框架,你一定使用过这个注解:

1@RequestMapping(value = "/admin/index.html", method = RequestMethod.GET)

这条注释的意思是:

  • 用户访问"/admin/index.html"页面,则执行下方方法
  • 限制用户只能使用"GET"方式访问

那么Spring在启动后是如何知道你用了这个注解,并且调用这个注解指定的方法的呢?

让我们先大体猜测一下:

  1. 我们可以配置Spring扫描的@Controller所在目录
  2. Spring扫描目录,并逐个扫描@Controller类中的注解
  3. 解析所有扫描到的注解,并通过反射,执行指定注释下的方法

实例

打开你的IDE,新建一个类Main.java,并复制下方语句:

 1import java.lang.annotation.ElementType;
 2import java.lang.annotation.Retention;
 3import java.lang.annotation.RetentionPolicy;
 4import java.lang.annotation.Target;
 5import java.lang.reflect.Method;
 6
 7/**
 8 * 模拟Spring的@RequestMapping注解实现原理
 9 * @implNote 注意:本示例仅用于展示@RequestMapping注释的原理,并非真正实现了@RequestMapping注解!
10 * @author GitHub: AdlerED
11 */
12
13/**
14 * 使用@interface定义一个注解,注解名为RequestMapping
15 * 枚举 RequestMethod 包含两个String对象:GET | POST
16 * value() 指定URL,必填
17 * method() 指定方式,选填,默认值RequestMethod.POST
18 *
19 * @Target 元注解,指定注解用于什么地方,ElementType.METHOD 表示用于描述方法
20 * @Retention 元注解,指定什么时候使用该注解,RetentionPolicy.RUNTIME 表示运行期也保留注解,因此可以使用反射机制读取该注解的信息。
21 */
22@Target(ElementType.METHOD)
23@Retention(RetentionPolicy.RUNTIME)
24@interface RequestMapping {
25    public enum RequestMethod {GET, POST}
26    String value();
27    RequestMethod method() default RequestMethod.POST;
28}
29
30/**
31 * Controller类,用两种方法使用自定义的@RequestMapping注解
32 */
33class Controller {
34    //由于method()方法有默认值,在注解只需要一个必填时,可以不指定方法名
35    @RequestMapping("/index.html")
36    public void mainPage() {
37        boolean status = true;
38    }
39
40    //手动指定value()方法值和method()方法值
41    @RequestMapping(value = "/admin/index.html", method = RequestMapping.RequestMethod.GET)
42    public void adminPage() {
43        boolean status = false;
44    }
45}
46
47public class Main {
48    /**
49     * 主方法,用于将Controller类中使用注解的内容进行反射
50     */
51    public static void main(String[] args) {
52        try {
53            //获取Controller类的反射
54            Class clazz = Controller.class;
55            //反射获取Controller类中的所有方法,并遍历
56            for(Method method : clazz.getMethods()) {
57                //获取方法中的@RequestMapping注解信息
58                RequestMapping methodAnnotation = method.getAnnotation(RequestMapping.class);
59                //如果该方法使用了@RequestMapping注解,则
60                if(methodAnnotation != null) {
61                    //打印方法名
62                    System.out.println(" Method Name : " + method.getName());
63                    //打印注解value()的值
64                    System.out.println(" Value : " + methodAnnotation.value());
65                    //打印注解method()的值
66                    System.out.println(" Method : " + methodAnnotation.method());
67                    System.out.println(" --------------------------- ");
68                }
69            }
70        } catch (Exception E) {
71            E.printStackTrace();
72        }
73    }
74}

反复理解并运行语句。

运行结果:

1 Method Name : mainPage
2 Value : /index.html
3 Method : POST
4 --------------------------- 
5 Method Name : adminPage
6 Value : /admin/index.html
7 Method : GET
8 --------------------------- 

整理实例语句,有以下几点:

  • @interface RequestMapping {} 定义一个自定义注解,此处的interface不是接口,因为在interface前边还有一个@
  • Controller {}类调用了@RequestMapping()接口,并演示了数据传递的定义
  • Main {}类用来模拟Spring,通过反射的方式扫描Controller类,并将使用了@RequestMapping()注解的方法也通过反射的方式,使其能够被修改调用。

后语

反射是Java的灵魂。 通过反射,我们才拥有了简单并优美的自定义注释,而不需要进行复杂的实例化,更具灵活性。