You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Atmosphere ManagedService中MyDAO始终为null的问题求助

解决Dropwizard + Atmosphere ManagedService中DAO注入为null的问题

这个问题的核心原因是:Atmosphere默认会自己实例化@ManagedService标注的类,不会让Dropwizard的HK2依赖注入容器参与创建过程,所以你的MyDAO无法被自动注入,始终为null。下面是两种可行的解决方案:

方案一:让Dropwizard的DI容器托管ManagedService实例

这种方法是最优解,能让你正常使用构造注入或者字段注入:

  1. 确保MyDAO已注册到HK2容器
    在你的Dropwizard Application类的run方法中,把MyDAO绑定到HK2容器:

    @Override
    public void run(YourConfiguration config, Environment environment) {
        // 绑定MyDAO为单例
        environment.jersey().register(new AbstractBinder() {
            @Override
            protected void configure() {
                bind(MyDAO.class).to(MyDAO.class).in(Singleton.class);
            }
        });
        // 其他初始化逻辑...
    }
    
  2. 配置Atmosphere使用HK2的实例工厂
    在Application的initialize方法中,添加AtmosphereBundle时,指定用HK2的Injector来创建ManagedService实例:

    @Override
    public void initialize(Bootstrap<YourConfiguration> bootstrap) {
        bootstrap.addBundle(new AtmosphereBundle() {
            @Override
            public void configureAtmosphere(AtmosphereConfig config) {
                // 获取Dropwizard的HK2 Injector
                Injector injector = environment.jersey().getResourceConfig().getApplicationHandler().getInjector();
                // 设置Atmosphere使用HK2的实例工厂
                config.setClassInstanceFactory(new HK2ClassInstanceFactory(injector));
            }
        });
    }
    
  3. 在ChatRoom中使用构造注入
    修改你的ChatRoom类,添加带@Inject注解的构造方法,注入MyDAO:

    @Singleton 
    @ManagedService(path = "/chat/{rooms: [a-zA-Z][a-zA-Z_0-9]*}") 
    public class ChatRoom{
        private final Logger logger = LoggerFactory.getLogger(ChatRoom.class); // 注意:你原来写的GameService应该是笔误,改成ChatRoom
        private final ConcurrentHashMap<String, String> users = new ConcurrentHashMap<>();
        private final static String CHAR= "/chat/";
        
        private final MyDAO myDAO;
    
        // 构造注入MyDAO
        @Inject
        public ChatRoom(MyDAO myDAO) {
            this.myDAO = myDAO;
        }
    
        @Ready(encoders = {InitialMessageEncoder.class})
        @DeliverTo(DeliverTo.DELIVER_TO.ALL)
        public InitialMessage onReady(final AtmosphereResource r) {
            logger.info("MyDAO instance: {}", myDAO); // 现在myDAO应该不为null了
            // 返回你的InitialMessage实例
            return new InitialMessage("Ready to chat!");
        }
    }
    

方案二:手动从ServletContext获取Injector(快速临时方案)

如果不想修改Atmosphere的全局配置,可以在onReady方法中手动获取Dropwizard的Injector,然后实例化MyDAO:

@Ready(encoders = {InitialMessageEncoder.class})
@DeliverTo(DeliverTo.DELIVER_TO.ALL)
public InitialMessage onReady(final AtmosphereResource r) {
    // 从ServletContext获取HK2 Injector
    ServletContext servletContext = r.getAtmosphereConfig().getServletContext();
    Injector injector = (Injector) servletContext.getAttribute(Injector.class.getName());
    
    if (injector != null) {
        myDAO = injector.getInstance(MyDAO.class);
    }
    
    logger.info("MyDAO instance: {}", myDAO);
    // 返回InitialMessage
    return new InitialMessage(...);
}

额外注意点

  • 确保你的MyDAO类上添加了@Injectable注解(或者在HK2绑定中明确声明),这样HK2才能识别它。
  • 你原来代码中的LoggerFactory.getLogger(GameService.class)应该是ChatRoom.class的笔误,记得修正,避免日志输出到错误的Logger。

内容的提问来源于stack exchange,提问作者hruday kumar reddy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 09:04:09