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

Springboot 用 @Autowired 的坑

  •  
  •   gramyang · 2019-05-22 21:25:42 +08:00 · 10694 次点击
    这是一个创建于 2013 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我想很多老铁可能都碰到过,就是在 springboot 的非 controller 中使用 @Autowired 引发的空指针。

    我这里的 handler 报空指针:

    public class NettyHandler extends ChannelInboundHandlerAdapter {
    private ConcurrentHashMap<Long, Channel> channelMap;
    private Long key = System.currentTimeMillis();
    @Autowired
    private PlayerInfoHandler handler;

    查了一下,不少人都遇到过这样的问题,一个解决方法: https://blog.csdn.net/georgeshaw1/article/details/74943089

    代码:
    @Autowired
    protected HealthDataService healthDataService;
    private static ServerHandler serverHandler ;
    @PostConstruct //通过 @PostConstruct 实现初始化 bean 之前进行的操作
    public void init() {
    serverHandler = this;
    serverHandler.healthDataService = this.healthDataService;
    // 初使化时将已静态化的 testService 实例化
    }

    我这边试了一下不行啊。。。。咋搞呢??
    第 1 条附言  ·  2019-05-22 22:32:30 +08:00
    刚刚修改了一下就好了,原因是 @Component 调用链中断,有一个环节使用了 new 而不是 @Autowired
    37 条回复    2019-05-26 14:16:39 +08:00
    Lonely
        1
    Lonely  
       2019-05-22 21:35:54 +08:00 via iPhone
    你这 handler 有注册为 bean 吗?
    feiyuanqiu
        2
    feiyuanqiu  
       2019-05-22 21:37:05 +08:00 via Android
    类上加个 @Component 或者 @Service 试试
    reeco
        3
    reeco  
       2019-05-22 21:39:35 +08:00
    只有被 Spring 管理起来的 bean 才能使用注入,你这个类压根没被 Spring 管理,@Autowired 默认 required 是 true,注入是 null 直接启动失败了
    szq8014
        4
    szq8014  
       2019-05-22 21:40:40 +08:00 via Android
    怀疑你不了解 Spring,handler 都没让 Spring 来管理怎么能注入成功?要么把 handler 交给 Spring 来管理,要么拿到 ApplicationContext 然后 getBean(HealthDataService.class) 这样拿到 HealthDataService 实例使用
    jamesxu
        5
    jamesxu  
       2019-05-22 21:43:08 +08:00 via iPhone
    这不算坑
    npe
        6
    npe  
       2019-05-22 21:44:47 +08:00 via Android
    Spring 容器里都没这个类,你能注入个啥?
    aragakiyuii
        7
    aragakiyuii  
       2019-05-22 21:56:52 +08:00 via Android
    你找的这个不是说的挺清楚的嘛。。
    在你的 NettyHandler 类上加 @Component 或者 @Service,并且要保证你注入的 PlayerInfoHandler 这个类或者接口实现也交给 spring 管理了
    telami
        8
    telami  
       2019-05-22 22:04:25 +08:00   ❤️ 1
    emmmm..
    gramyang
        9
    gramyang  
    OP
       2019-05-22 22:29:13 +08:00
    @szq8014 确实 spring 用的不多
    NewDraw
        10
    NewDraw  
       2019-05-22 22:48:22 +08:00 via Android   ❤️ 2
    哥们你太有意思了😄😄😄😄
    Umenezumi
        11
    Umenezumi  
       2019-05-22 22:49:41 +08:00
    PlayerInfoHandler handler 你这个类没有被 spring 管理啊。。自动注入 required 默认是 true 自然报错
    trycatch
        12
    trycatch  
       2019-05-22 22:50:36 +08:00
    最好用构造函数注入
    serical
        13
    serical  
       2019-05-22 22:55:36 +08:00 via Android
    静态的通过 set 方法注入
    qwerthhusn
        14
    qwerthhusn  
       2019-05-22 23:08:05 +08:00
    BTW,如果把 Handler 注册成 Bean,并且是单例的话,
    别忘了加上注解 @Shared,Netty 好像对 @Shared 有处理,标记为可重用的 Handler
    gramyang
        15
    gramyang  
    OP
       2019-05-22 23:10:27 +08:00
    @qwerthhusn 基本上,netty 的业务 handler 是不会用到 @Sharable 的,所以我已经加上了
    gramyang
        16
    gramyang  
    OP
       2019-05-22 23:50:31 +08:00
    @qwerthhusn 不对,我上一句话说的有语病。
    handler 我不想加上 @Sharable,因为不是线程安全的。但是我这个是一个用 netty 写的持久化服务器,所以是线程安全的,可以加上 @Sharable
    wc951
        17
    wc951  
       2019-05-23 06:33:00 +08:00 via Android
    用构造器注入就不会出现你这种疑惑,因为直接启动就失败了,这也是 spring 官方推荐构造器注入的原因
    brust
        18
    brust  
       2019-05-23 08:16:50 +08:00
    用 spring4.0 出现过这种情况,但是 springboot 我还没遇到过,可以说下你的 spring 版本吗
    tedzhou1221
        19
    tedzhou1221  
       2019-05-23 08:17:08 +08:00 via Android   ❤️ 1
    题外话:建议你用 idea,或者学习怎么用。
    当前类如果被 spring 管理的话,左边是有绿色的叶子,.
    @Autowired 如果生效的话左边也有绿色的豆子(Bean)

    所以大部分情况下,有没有注入成功,一眼就看出来
    brust
        20
    brust  
       2019-05-23 08:18:12 +08:00
    我当时的解决方法是吧 @Autowired 换成 @resource
    szq8014
        21
    szq8014  
       2019-05-23 08:31:26 +08:00
    @gramyang 从你目前的情况来看个人觉得用 ApplicationContext.getBean(clazz) 更方便一些,至于 ApplicationContext 怎么拿,最简单的方法就是 springboot 的 main 方法里面唯一的那行调用其实是有返回值的,而且返回值就是那个 ApplicationContext
    BBCCBB
        22
    BBCCBB  
       2019-05-23 08:54:05 +08:00
    这个的确是你用法不对...
    ala2008
        23
    ala2008  
       2019-05-23 08:58:19 +08:00
    ioc 了解一下
    linyinma
        24
    linyinma  
       2019-05-23 09:17:31 +08:00
    小哥拉屎拉不出来乖茅坑没设计好~~
    Yuicon
        25
    Yuicon  
       2019-05-23 09:26:22 +08:00
    学习理论的重要性
    liujan
        26
    liujan  
       2019-05-23 09:53:52 +08:00
    spring 注入的话需要保证被注入的类和注入的类都在 spring 的 bean 容器了。可以加 @Component
    rffan
        27
    rffan  
       2019-05-23 09:55:47 +08:00
    你这个是基本不了解 Spring 啊不是坑啊。
    hailiang88
        28
    hailiang88  
       2019-05-23 09:58:02 +08:00
    先尝试下手撸个 ioc 吧
    Ahaochan
        29
    Ahaochan  
       2019-05-23 10:40:12 +08:00
    在非 Spring 管理的类下, 使用 SpringContextHolder 解决. 注意初始化顺序.

    https://github.com/Ahaochan/project/blob/master/ahao-utils/src/main/java/com/ahao/util/spring/SpringContextHolder.java
    gramyang
        30
    gramyang  
    OP
       2019-05-23 10:53:07 +08:00
    @Ahaochan 我就是这么解决的,这个是正解
    zcating
        31
    zcating  
       2019-05-23 10:54:00 +08:00
    兄 dei,要么你就为这个类添加注解 @Component,要么就写个 config,为 NettyHandler 写个工厂方法 ,在工厂方法上添加注解 @Bean
    gabon
        32
    gabon  
       2019-05-23 12:06:40 +08:00 via Android
    kangzai50136
        33
    kangzai50136  
       2019-05-23 13:05:50 +08:00 via Android
    多了解 Spring 吧。
    brust
        34
    brust  
       2019-05-23 13:42:56 +08:00
    @tedzhou1221 我 idea 怎么没绿色豆子,可以截图标志 发链接看看嘛,或者邮箱 YnJ1c3RAYnJ1c3QuY24=
    arthas2234
        35
    arthas2234  
       2019-05-23 14:03:46 +08:00
    handle 类上面加 @Component 注解
    @ComponentScan 的配置也要确保你的 handle 被扫描到
    Chinsung
        36
    Chinsung  
       2019-05-23 15:54:16 +08:00
    Spring 只管理你所配合的类,通过注解、javaconfig、xml 这 3 个配置的类。通过这 3 者配置起来的类互相之间才能由 spring 管理依赖关系。
    你这个 handler 要加上 @Compoment 注解,然后再启动类上加上 CompomentScan 或者在 xml 里配置 CompomentScan,这个类才能应用 Autowire 等注解注入依赖
    EastLord
        37
    EastLord  
       2019-05-26 14:16:39 +08:00
    其实现在不用 @Autowired 也行,直接构造注入
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5410 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 05:56 · PVG 13:56 · LAX 21:56 · JFK 00:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.