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

Spring中@Autowired注入为空但ApplicationContextAware可用问题排查

排查Spring单例Bean依赖注入失败问题

让我们一步步拆解你遇到的问题——明明两个单例Bean单独运行正常,但三种注入方式都失败,只能靠ApplicationContextAware临时解决,大概率是上下文范围、组件扫描或者Hessian服务配置的问题,下面是具体的排查和解决步骤:

1. 先确认组件扫描是否覆盖了所有目标Bean

你的XML配置和SpringBoot启动类都指定了扫描hu.bme.sch.qpa包,但要确保:

  • PersistenceBean和HelloWorldBean的实际包路径都在hu.bme.sch.qpa或者它的子包下
  • 如果其中一个Bean在这个范围之外,Spring的组件扫描会直接忽略它,自然无法注入。

可以通过打印容器内的所有Bean名称来验证:在PersistenceBean的setApplicationContext方法里添加这段代码,查看目标Bean是否存在:

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.context = applicationContext;
    // 打印所有注册的Bean名称
    for (String beanName : applicationContext.getBeanDefinitionNames()) {
        System.out.println("Registered Bean: " + beanName);
    }
}

如果输出里找不到HelloWorld.NAME对应的Bean,就需要调整component-scan的base-package,把目标Bean所在的包加进去。

2. 检查Hessian服务的上下文归属

因为你的Bean是作为HessianServiceExporter的基础,很容易出现跨上下文注入的问题:

  • Web应用中常存在两个Spring上下文:根上下文(由ContextLoaderListener或SpringBoot启动类加载)和Servlet上下文(比如DispatcherServlet或Hessian的专属Servlet加载)
  • 如果Hessian的ServiceExporter配置在Servlet上下文里,而你的业务Bean(PersistenceBean、HelloWorldBean)在根上下文,虽然Servlet上下文可以访问根上下文的Bean,但如果注入逻辑写反了,或者上下文没有正确设置父子关系,就会导致注入失败。

解决办法:

  • 确保所有相关Bean(包括Hessian的Exporter)都在同一个ApplicationContext里
  • 如果必须分上下文,要把业务Bean放在根上下文,Hessian Exporter放在Servlet上下文(子上下文可以自动访问父上下文的Bean)

3. 验证注入代码的正确性

你提到三种注入方式都失败,先确认你的注入代码是否符合Spring的规范:

字段注入

@Service(Persistence.NAME)
public class PersistenceBean implements Persistence {
    // 如果HelloWorld有多个实现,必须加@Qualifier指定Bean名称
    @Autowired
    @Qualifier(HelloWorld.NAME)
    private HelloWorld helloWorld;

    @Override
    public User getUser() {
        User user = new User();
        user.setEmail(helloWorld.getText());
        return user;
    }
}

构造器注入(推荐方式)

@Service(Persistence.NAME)
public class PersistenceBean implements Persistence {
    private final HelloWorld helloWorld;

    // 构造器注入不需要@Autowired(Spring 4.3+),如果有多个实现同样加@Qualifier
    public PersistenceBean(@Qualifier(HelloWorld.NAME) HelloWorld helloWorld) {
        this.helloWorld = helloWorld;
    }

    @Override
    public User getUser() {
        User user = new User();
        user.setEmail(helloWorld.getText());
        return user;
    }
}

方法注入

@Service(Persistence.NAME)
public class PersistenceBean implements Persistence {
    private HelloWorld helloWorld;

    @Autowired
    @Qualifier(HelloWorld.NAME)
    public void setHelloWorld(HelloWorld helloWorld) {
        this.helloWorld = helloWorld;
    }

    @Override
    public User getUser() {
        User user = new User();
        user.setEmail(helloWorld.getText());
        return user;
    }
}

重点:如果HelloWorld接口有多个实现类,必须用@Qualifier指定你要注入的Bean名称(也就是HelloWorld.NAME),否则Spring会因为歧义无法完成注入。

4. 排查上下文重复加载问题

你的CoreStarter是SpringBootServletInitializer,它已经负责加载Spring上下文,如果你的web.xml里还配置了ContextLoaderListener,会导致两个独立的ApplicationContext被创建:

  • 你的Bean会被实例化两次,注入的可能是另一个上下文里未完成依赖注入的实例,导致字段为空。

解决办法:

  • 检查web.xml(如果存在),移除ContextLoaderListener的配置,统一用SpringBoot的方式加载上下文。

5. 排除自定义BeanPostProcessor的干扰

虽然你的配置里只有Spring官方的persistenceExceptionTranslationPostProcessor,但如果有其他自定义的BeanPostProcessor,可能干扰了依赖注入的流程。可以暂时移除自定义的BeanPostProcessor,测试是否能正常注入。

按照上面的步骤逐一排查,应该能找到问题所在。

内容的提问来源于stack exchange,提问作者László Stahorszki

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:23:23