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

Java 开发注解会入侵代码吗?

  •  
  •   qdyoungk · 2019-08-30 08:53:41 +08:00 · 7452 次点击
    这是一个创建于 1912 天前的主题,其中的信息可能已经有所发展或是发生改变。

    java 开发注解会入侵代码吗?昨晚架构在代码走查时点了一个人的代码,告诉我们他是尽量不想用注解的, 如 @Autowired,他会推荐用 set 写。 他说到“用注解,我们的项目打出的包给别人用时,别人可能只要一个功能,但是我们就要把全部路径暴露给别人”。 我不太懂这句话是什么意思,麻烦大佬们给个解释。 另外,如 lombok 的 @Slf4j,这个好还是手写的 getLogger 好?和上面的问题有关系吗?

    32 条回复    2019-09-02 22:10:55 +08:00
    qping
        1
    qping  
       2019-08-30 09:05:50 +08:00
    lombok 是改字节码的,你把 class 反编译可以看到,它给你加了一句 getLogger,和你手写是一样的效果
    qdyoungk
        2
    qdyoungk  
    OP
       2019-08-30 09:09:48 +08:00
    @qping 嗯。那这种注解会造成上面说的那种“暴露路径”或者“代码入侵”吗?
    qping
        3
    qping  
       2019-08-30 09:09:51 +08:00
    你同事真的理解注解的原理和怎么用了吗
    liuxey
        4
    liuxey  
       2019-08-30 09:12:06 +08:00
    胡扯,@Autowired 会暴露,set 就不会了?

    好好让他理解下 Spring Boot autoconfiguration 精髓

    说到 Lombok,连原理都没搞清楚,就说手写 Logger ?

    你们的架构可能很有"经验",但他已经走进自我感觉良好的死路
    nnnToTnnn
        5
    nnnToTnnn  
       2019-08-30 09:14:20 +08:00   ❤️ 1
    我是真的不太明白你同事说的话,注解不过是运行时候的一个标志,本身不起任何作用,起作用的是注解解析器。


    至于你说的“暴露路径”或者“代码入侵”,这些东西和用注解无关吧,提供 sdk,都可以反编译代码了,你觉得。


    话说你同事真的是 Java 出身? 感觉不像 Java 开发的,Java 开发都是 spring boot 用也得用,不用也得用,不然都无法启动
    lzxz1234
        6
    lzxz1234  
       2019-08-30 09:15:06 +08:00
    首先,注解是代码的一部分,不是配置项,所以根本没有入侵代码的问题,它本身就是代码

    然后,具体场景具体分析,如果是提供给别人用的代码,尽量连 spring 都不要用,因为别人的项目可能并不是 spring 管理的,或者可能是其它版本管理的,容易引起冲突或者其它问题。

    至于 “全体路径暴露” 的问题不是很明白,你把包打给别人了,你能 set 别人也能,根本解决不了问题,最多做到默认不加载

    lombok 这个老话题了,看团队,要么所有人都用,要么所有人都不用
    hangszhang
        7
    hangszhang  
       2019-08-30 09:17:58 +08:00
    都 9102 年了,springboot 的大版本都到 2 了,还有人说这种话
    chendy
        8
    chendy  
       2019-08-30 09:18:25 +08:00
    autowired 用 set 写是啥意思?
    项目打包给别人的场景确实和自己用的场景不一样,需要区别对待,但是感觉没说到点上
    Aresxue
        9
    Aresxue  
       2019-08-30 09:21:51 +08:00
    spring3.0 以前的注解会有入侵,但入侵不是因为注解而是对注解的业务处理对整个系统的耦合。在 spring 5.0 以上可以放心大胆的使用,set 方法一般还是搭配 xml 配置使用,xml 配置这东西能不用还是不用的好(但其功能的强大目前诸多配置仍旧比不上,这也是目前虽然在去 xml'化但仍然效果不甚理想的原因),set 代码本身也是极其无用的代码,代码这东西越少 bug 也就越少问题也更好定位。同时不推荐使用 AutoWired 进行 field 注入,尽量使用构造器注入。
    qdyoungk
        10
    qdyoungk  
    OP
       2019-08-30 09:31:13 +08:00
    谢谢各位大佬,提到的很多名词我正查个不停。。谢谢!
    passerbytiny
        11
    passerbytiny  
       2019-08-30 09:35:11 +08:00   ❤️ 4
    你同事说得那么玄乎,但我不知道他在说什么。

    @Autowired 要是写在变量上,同时又不提供 set 方法(包括通过构造方法 set ),那么这个类离开了 Spring 将无法自举,即你直接 new 出来的对象,是无法使用的,@Autowired 的变量永远是 null。Spring 官方推荐的做法是,@Autowired 放到构造器或者 set 方法上,这样即使脱离了 Spring,你这个类还能通过 new 方法实例出一个可用的对象。这里还有另一层含义,传统的依赖注入概念,是让容器 new、set 之后把 bean 给你,后者是符合这种传统概念的,这意味着你的依赖注入容器,可用方便地从 Spring 换成其它容器。

    But,Java 不用 Spring 是个伪命题,@Autowired 写在变量上能极大地提高代码可读性,以及更重要地,重构方便性。

    另外只写 set 方法但是不加 @Autowired 注解,是一种严重影响代码可读性地行为,它要求读代码的人必须知道“ Spring 会通过反射扫描到该方法,进而知道这是用来做注入的”,否则将会非常困惑“这叼变量是怎么注入的”。

    lombok.@Slf4j 与上面没关系,但是 lombok.@Setter 与 @Autowired 有关系,用了 @Setter,你源代码就没有 set 方法了,自然也没办法在 set 方法上加 @Autowired,lombok 尝试解决这种冲突,但到目前为止实现方式还是很丑陋。
    x66
        12
    x66  
       2019-08-30 09:43:05 +08:00
    Spring 官方在 3.x 的时候是推荐使用 set 注入的,但现在已经是 5.x 了,官方推荐使用构造器注入,所以你们的架构或许还在使用过时的经验?
    BigDogWang
        13
    BigDogWang  
       2019-08-30 09:46:35 +08:00 via iPhone
    我大致懂了一点了,Autowired 会要求 bean 必须 public,set 则无这样要求,你同事应该是这么考虑的
    sambawy
        14
    sambawy  
       2019-08-30 09:47:47 +08:00
    springboot 的出现就是为了消灭配置里面大量 xml 的,xml 多可读性差,springboot 现在都已经到 2.x 版本了,应该来说是经过了实践验证过的东西了,你的同事是不是太过于保守
    BigDogWang
        15
    BigDogWang  
       2019-08-30 09:55:57 +08:00
    是我学艺不精了。Bean 也可以 package-privage
    90d0n
        16
    90d0n  
       2019-08-30 10:06:22 +08:00
    @Autowired 这老哥被你们这么艾特, 会不会烦得要死
    eGlhb2Jhb2Jhbw
        17
    eGlhb2Jhb2Jhbw  
       2019-08-30 10:07:56 +08:00
    @Autowired 出来聊聊,哈哈哈哈哈
    optional
        18
    optional  
       2019-08-30 10:14:55 +08:00
    private autowired 确实破坏了封装性,也破坏了离开 spring 的可能性,而且搞得代码到处都是 import spring,推荐直接 @allArgsConstructor
    mosliu
        19
    mosliu  
       2019-08-30 10:15:45 +08:00
    @Autowired 现在 springboot 推荐的是构造里注入吧

    其实上面讲的挺好的 回复这条主要是想 at 一下 Autowired 兄
    no1xsyzy
        20
    no1xsyzy  
       2019-08-30 11:15:40 +08:00
    看看 @Override 你们就知道了,这些喜欢把 @ 常跟的东西当名字的就是想知道谁在谈论这事
    wysnylc
        21
    wysnylc  
       2019-08-30 11:16:06 +08:00
    @Aresxue #9 构造器存在强制依赖问题,如果发现无法注入整个项目都无法启动也无法在运行是修改注入的 bean,当多个构造器(5 个以上)时代码会变得很难看
    构造器虽好,但是不建议使用
    notreami
        22
    notreami  
       2019-08-30 11:20:46 +08:00
    反射+字节码,什么 java 代码不能暴露??
    vjnjc
        23
    vjnjc  
       2019-08-30 11:36:13 +08:00
    应该就是 9 楼说的,用 @会使得这段代码复用性不够强,可以用 set 或者构造函数(推荐)。
    这样的话这个类就没有 annotation 的 import 了,也就没有 spring 的依赖了。不过相信我,这种复用性大部分情况都用不上,很难用场合会迁移到一个没有 spring 的项目里
    passerbytiny
        24
    passerbytiny  
       2019-08-30 11:52:12 +08:00
    @vjnjc #21 要没有 annotation,你必须使用 xml,否则你最起码要有一个 @Component
    luozic
        25
    luozic  
       2019-08-30 13:39:45 +08:00 via iPhone
    扯犊子呢,封装和开闭是放这里的?
    Takamine
        26
    Takamine  
       2019-08-30 14:46:17 +08:00
    没看懂 Autowire 怎么了,说到 lombok 倒是团队里被禁用了。
    这一翻开代码里面都是 Configuration,FeignClient,EnableHystrix 这些注解的那不是炸了。:doge:
    chendy
        27
    chendy  
       2019-08-30 14:48:18 +08:00
    @wysnylc 组件类有很多构造方法是啥场景?…
    heian0224
        28
    heian0224  
       2019-08-30 18:02:38 +08:00 via Android
    我觉得应该是不用变量直接注入,而是通过构造器注入。这个 spring 是这样推荐的
    aguesuka
        29
    aguesuka  
       2019-08-31 02:08:13 +08:00 via Android
    注入有三种方法,其一是 field 注入,缺点耦合 spring。其二是构造器,缺点是不能循环引用。其三是 setter,我没找到怎么用 idea 生成,而且 setter 太啰嗦。
    我觉得 java 应该从语法层次解决配置文件,依赖注入,aop,日志的问题,就像 jdbc 一样。感觉很多 jvm 可以做的东西都由框架去实现了。
    br00k
        30
    br00k  
       2019-08-31 09:26:18 +08:00 via iPhone
    @aguesuka 构造方法可以循环引用,添加 @Lazy 注解。不过出现这种问题首先要考虑代设计是不是有问题。
    Aresxue
        31
    Aresxue  
       2019-09-02 09:38:56 +08:00
    @wysnylc 正是为了强制注入,不然实际运行时注入失败还可以正常启动但业务代码还会报 npe, 当然在前期开发中使用 field 也无可厚非,相互之间可以独立,因为注入本身此时也变动的十分频繁,但当项目进入正常的迭代周期了,就不应该使用此种方式。构造器注入使得注入的服务不可变, 在实际的代码运行可以规避很多问题, 此外 5 个以上的依赖使得代码过于臃肿, 这时候应该考虑下设计模式了,为什么你会有这么多的服务要注入, 是不是拆分的不够细, 一个拥有 5 个注入以上的类大概率本身就很臃肿。当然在传统行业中业务本身确实及其复杂,但实际中仍不应该随意复用,举个极端的例子,我有一个列表查询, 我已经有了一个单个的查询,此时要不要复用是有待商榷的而不是无脑复用, 我见过有人为了复用竟然单个的查询也用列表查询查出来然后再取出来,完全罔顾了列表查询中不必要的操作和数据库更大的耗时。
    Asimov01
        32
    Asimov01  
       2019-09-02 22:10:55 +08:00
    居然还真有 Autowired 这么一个人,哈哈哈哈哈哈哈哈
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2621 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 01:57 · PVG 09:57 · LAX 17:57 · JFK 20:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.