一个正在学习的 javaer 对注解的疑问求解惑

2023-01-16 12:36:44 +08:00
 dzdh

学到自定义注解这个过程了

注解是不是必须只能依靠类的反射来手动处理对应的逻辑。如果是,那就是手动 new class 的时候注解是啥都不干的?

因此,像 @RequestMapping 也就是在框架启动的时候要把所有的 class 都挨个的通过反射获取所有的 method 的注解然后 add 到一个大的 map 中么?

然后像 go 一样有个类似 ServeHTTP 的方法,获取到 HTTP 的 Path ,从 map 里挨个找?然后动态的 newInstance?

是这样么?

2692 次点击
所在节点    Java
20 条回复
seashell2000
2023-01-16 12:55:41 +08:00
确实是有一个 MappingRegistry
hyperdak288
2023-01-16 12:58:37 +08:00
注解类似代码的"代码",所有的注解都需要一个注解处理器,才能识别这部分代码金进行处理.
dzdh
2023-01-16 13:08:13 +08:00
@hyperdak288 那这个所谓的 [处理器] 就是通过反射实现么?那这个 [处理器] 类也需要执行才能处理 [注解] 咯?那就还是要扫描所有 class 文件么?
thinkershare
2023-01-16 13:08:58 +08:00
所有类似注解这样的东西都属于元编程领域(meta-programming)。 本质上就是编写代码去操作代码,而不是像普通代码是操作数据(或者说这里的数据就是代码),有些编程语言中,代码和数据是有明显边界的,有的语言则边界模糊。另外很多时候编写这种注解是为了实现另外一个概念面向切面编程(Aspect Oriented Programming)。这就是一种复用代码的常见方式。
dzdh
2023-01-16 13:09:37 +08:00
@hyperdak288

或者说。有没有一种方法。我定义好自定义注解,然后在其他类上应用这个注解。然后不需要任何操作在编译的时候会自动触发这个注解通过一种什么方法触发一个 class.method 然后接收并处理应用这个注解的类呢
thinkershare
2023-01-16 13:10:38 +08:00
大部分编程语言的元编程都是使用反射实现的,因为需要元数据才能去操作代码。元数据就是记录关于代码本身信息的对象。
liangkang1436
2023-01-16 13:15:38 +08:00
@dzdh 可以,Lombok 就是这么做的
thinkershare
2023-01-16 13:15:50 +08:00
@dzdh 是有办法的,编译器存在钩子,可以进行代码注入和编译后二次修改字节码的功能。而且现实中某些代码为了追求速度,的确会这么做,但这回失去动态性,因为某些反射信息在编译时候是不可能知道的,只能在运行时才能动态获取。
TtTtTtT
2023-01-16 13:40:33 +08:00
是这样,运行时反射是获取注解信息的主要方式。
编译期注解处理是另一种方式,但只建议读取,避免对源代码、源字节码进行修改。Lombok 是邪教,建议用,不建议学。
Leviathann
2023-01-16 13:49:00 +08:00
就是一个可以用反射获取到的标记(有些是让编译器获取)
注解本身没有任何功能
7911364440
2023-01-16 13:49:45 +08:00
之前写过的一个日志框架就是在编译阶段对特定的类做字节码注入,可以看下:
https://github.com/rainy-zhang/log4zy/blob/main/src/main/java/org/rainy/log4zy/processor/LoggerProcessor.java
dzdh
2023-01-16 14:30:30 +08:00
所以说,注解本身卵用没有。只有在通过别的 class 来通过反射实例化他的时候才有用,而且要人家刻意的解析、处理。


比如说 @Fk(Value={me}) 必须通过一个 Fker.main: getclass.getmethod.getanno('fk').getvalue() 。
然后调用 fker 的时候,才能使这个玩意儿有用。

单纯写个注解,卵用么的。
joeyFuck
2023-01-16 15:16:38 +08:00
@dzdh 是的,就是个标记。
banmuyutian
2023-01-16 16:26:38 +08:00
对呀,annotation 一般都有对应的 annotation handler
dqzcwxb
2023-01-16 16:33:08 +08:00
注解只是个标记需要额外处理,而且代码其实也是个标记真正执行的也是编译后的字节码,然后字节码也是个标记.....
这样解释 ok 吗?
dzdh
2023-01-16 17:02:19 +08:00
@joeyFuck
@banmuyutian
@dqzcwxb

所以说 Spring 家的 一堆 @ RequestMapping 。就是需要框架启动的时候扫一下包里的所有.class 挨个反射一遍。看看都谁被标记了 RequstMapping 呗
kenvix
2023-01-16 17:08:35 +08:00
> 注解是不是必须只能依靠类的反射来手动处理对应的逻辑
错,编译期用作**用户自定义关键词**也是注解的一大用途,用户能够自定义编译器遇到自定义关键词(注解)的行为,在不能使用 Kotlin 的时候我很喜欢用 Lombok 的 @Data 注解让它生成 pojo 相关方法。
LykorisR
2023-01-16 21:19:14 +08:00
@dzdh 可以这样说,所以 spring 被诟病的一点就是他的启动速度
br00k
2023-01-17 09:08:41 +08:00
Spring 6 AOT 就是把很多在运行时处理的放到编译时来处理。启动速度快非常多。
freemansuyu
2023-02-07 12:21:58 +08:00
注解是被动元数据,只是对语言元素(类、接口、方法...)等的一个 tag ,对这个 tag 怎么解释,取决于注解的处理器,注解本身并不会主动起作用

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/909240

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX