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

如何排查配置类中@Autowired注入XDDeliveryCallback接口为空问题

XDDeliveryCore中callback为null的排查与解决

问题背景

我有如下配置类:

@Configuration
public class XDDeliveryConfig {

    @Value("${direct.gateway.xd.endpointUrl: http://localhost:8080/xd/services/DocumentRepository_Service}")
    protected String endpointURL;

    @Autowired
    protected RoutingResolver resolver;

    @Autowired
    protected XDDeliveryCallback xdDeliveryCallback;

    @Bean
    @ConditionalOnMissingBean
    public XDDeliveryCore xdDeliveryCore() {
        final ReliableDispatchedNotificationProducer notificationProducer =
            new ReliableDispatchedNotificationProducer(
                new NotificationSettings(true, "Direct XD Delivery Agent",
                        "Your message was successfully dispatched."));

        return new XDDeliveryCore(
                resolver, xdDeliveryCallback, new DefaultTxDetailParser(),
                new DefaultMimeXdsTransformer(), new DocumentRepository(), 
                notificationProducer, endpointURL);
    }
}

XDDeliveryCallback接口定义:

public interface XDDeliveryCallback {
    void sendNotificationMessage(NotificationMessage message) throws MessagingException;
}

XDDeliveryCore构造方法:

public class XDDeliveryCore {
    protected final RoutingResolver resolver;
    protected final XDDeliveryCallback callback;
    protected final TxDetailParser txParser;
    protected final MimeXdsTransformer mimeXDSTransformer;
    protected final DocumentRepository documentRepository;
    protected final NotificationProducer notificationProducer;
    protected final String endpointUrl;

    public XDDeliveryCore(RoutingResolver resolver, XDDeliveryCallback callback,
                          TxDetailParser txParser,
                          MimeXdsTransformer mimeXDSTransformer, DocumentRepository documentRepository,
                          NotificationProducer notificationProducer, String endpointUrl) {
        this.resolver = resolver;
        this.callback = callback;
        this.txParser = txParser;
        this.mimeXDSTransformer = mimeXDSTransformer;
        this.endpointUrl = endpointUrl;
        this.documentRepository = documentRepository;
        this.notificationProducer = notificationProducer;
    }

}

接口实现类:

@Configuration
public class XDRemoteDeliveryProcessor implements XDDeliveryCallback {

    @Autowired
    protected XDDeliveryCore deliveryCore;

    @Autowired
    protected SmtpGatewayMessageSource smtpMessageSource;

    @Autowired
    protected DSNCreator dsnCreator;

    @Bean
    public Consumer<Message<?>> directXDDeliveryInput() {
        return streamMsg -> {
            try {
                final SMTPMailMessage smtpMessage = SMTPMailMessageConverter.fromStreamMessage(streamMsg);

                log.debug("XDRemoteDeliveryProcessor processing message from " + smtpMessage.getMailFrom().toString());
                deliveryCore.processAndDeliverXDMessage(smtpMessage);
            } catch (MessagingException e) {
                throw new RuntimeException(e);
            }
        };
    }

    public void sendNotificationMessage(NotificationMessage message) throws MessagingException {
        smtpMessageSource.sendMimeMessage(message);
    }
}

目前发现XDDeliveryCore中的callback字段为null,需要排查并解决该问题。


核心原因:循环依赖导致注入失败

XDDeliveryConfig创建XDDeliveryCoreBean时,需要注入XDDeliveryCallback(即XDRemoteDeliveryProcessor);而XDRemoteDeliveryProcessor又通过@Autowired注入XDDeliveryCore,形成了循环依赖。Spring处理这种场景时,字段注入+工厂方法创建Bean的组合会导致初始化顺序混乱,XDDeliveryCallback还未完成Bean初始化就被注入到XDDeliveryCore,最终出现null值。


排查步骤

  1. 查看Spring上下文日志

    • 开启Spring DEBUG级别日志,搜索XDDeliveryCore和XDRemoteDeliveryProcessor的初始化日志,检查是否存在Circular reference detected相关警告或错误,直接确认循环依赖问题。
  2. 验证组件扫描范围

    • 确认XDRemoteDeliveryProcessor所在的包被@ComponentScan覆盖,确保Spring能扫描到该类并创建对应的Bean。
  3. 检查@ConditionalOnMissingBean的影响

    • 确认没有其他地方提前创建了XDDeliveryCore的Bean,导致XDDeliveryConfig中的xdDeliveryCore()方法未执行,而其他创建方式未正确注入XDDeliveryCallback。

解决方案

方案1:延迟加载打破循环依赖

将XDRemoteDeliveryProcessor中的字段注入改为构造器注入,并通过@Lazy延迟加载XDDeliveryCore,让Spring先完成XDRemoteDeliveryProcessor的初始化:

@Configuration
public class XDRemoteDeliveryProcessor implements XDDeliveryCallback {

    protected final XDDeliveryCore deliveryCore;
    protected final SmtpGatewayMessageSource smtpMessageSource;
    protected final DSNCreator dsnCreator;

    public XDRemoteDeliveryProcessor(@Lazy XDDeliveryCore deliveryCore,
                                     SmtpGatewayMessageSource smtpMessageSource,
                                     DSNCreator dsnCreator) {
        this.deliveryCore = deliveryCore;
        this.smtpMessageSource = smtpMessageSource;
        this.dsnCreator = dsnCreator;
    }

    // 其余代码保持不变
}

方案2:指定Bean初始化顺序

在XDDeliveryConfig的xdDeliveryCore()方法上添加@DependsOn,强制Spring先初始化XDRemoteDeliveryProcessor:

@Configuration
public class XDDeliveryConfig {

    // ... 其他字段

    @Bean
    @ConditionalOnMissingBean
    @DependsOn("xDRemoteDeliveryProcessor") // 默认Bean名称为类名首字母小写
    public XDDeliveryCore xdDeliveryCore() {
        // ... 原有代码不变
    }
}

如果XDRemoteDeliveryProcessor自定义了Bean名称,需要修改@DependsOn中的对应值。

方案3:重构代码消除循环依赖

最彻底的方式是调整业务逻辑,比如将XDRemoteDeliveryProcessor中调用deliveryCore.processAndDeliverXDMessage()的逻辑,改为通过Spring事件发布、中间层代理等方式,避免直接依赖XDDeliveryCore,从根源上消除循环依赖。


内容的提问来源于stack exchange,提问作者JackTheKnife

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 03:25:16