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

Springboot 用 @Autowired 的坑

  •  
  •   gramyang 2019-05-22 21:25:42 +08:00 11197 次点击
    这是一个创建于 2335 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我想很多老铁可能都碰到过,就是在 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 &nbp;
       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     Solana     3161 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 12:18 PVG 20:18 LAX 05:18 JFK 08:18
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86