V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dzdh
V2EX  ›  Java

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

  •  
  •   dzdh · 2023-01-16 12:36:44 +08:00 · 2980 次点击
    这是一个创建于 700 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

    是这样么?

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

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


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

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

    所以说 Spring 家的 一堆 @ RequestMapping 。就是需要框架启动的时候扫一下包里的所有.class 挨个反射一遍。看看都谁被标记了 RequstMapping 呗
    kenvix
        17
    kenvix  
       2023-01-16 17:08:35 +08:00
    > 注解是不是必须只能依靠类的反射来手动处理对应的逻辑
    错,编译期用作**用户自定义关键词**也是注解的一大用途,用户能够自定义编译器遇到自定义关键词(注解)的行为,在不能使用 Kotlin 的时候我很喜欢用 Lombok 的 @Data 注解让它生成 pojo 相关方法。
    LykorisR
        18
    LykorisR  
       2023-01-16 21:19:14 +08:00
    @dzdh 可以这样说,所以 spring 被诟病的一点就是他的启动速度
    br00k
        19
    br00k  
       2023-01-17 09:08:41 +08:00
    Spring 6 AOT 就是把很多在运行时处理的放到编译时来处理。启动速度快非常多。
    freemansuyu
        20
    freemansuyu  
       2023-02-07 12:21:58 +08:00
    注解是被动元数据,只是对语言元素(类、接口、方法...)等的一个 tag ,对这个 tag 怎么解释,取决于注解的处理器,注解本身并不会主动起作用
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1267 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 23:57 · PVG 07:57 · LAX 15:57 · JFK 18:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.