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

如何在CorDapp项目中注入Spring对象?@Autowired注入为空求助

在CorDapp中整合Spring并实现依赖注入的解决方案

我之前在CorDapp项目里尝试过整合Spring框架,刚好碰到过和你一样的@Autowired注入失败的问题。核心原因是CorDapp默认的REST API由Corda自带的Jersey容器管理,而非Spring容器——你标记了@Component的ExampleApi其实是由Jersey手动实例化的,Spring根本没机会为它注入依赖。

下面是具体的解决步骤,结合你的代码来调整:

1. 手动初始化Spring上下文

Corda节点不会自动加载Spring上下文,我们需要借助CordaService在节点启动时触发Spring Boot的初始化:

@CordaService
public class SpringBootInitializer extends SingletonSerializeAsToken {
    private final AppServiceHub serviceHub;
    private ConfigurableApplicationContext springContext;

    public SpringBootInitializer(AppServiceHub serviceHub) {
        super(serviceHub);
        this.serviceHub = serviceHub;
    }

    @PostConstruct
    public void initSpringContext() {
        if (springContext == null) {
            // 禁用Spring自带的Web服务器,避免和Corda内置Jetty端口冲突
            SpringApplication app = new SpringApplication(JerseyConfig.class);
            app.setWebApplicationType(WebApplicationType.NONE);
            springContext = app.run();
            // 将Spring上下文存入Corda服务中心,方便后续获取
            serviceHub.registerAttachment(springContext);
        }
    }

    public ConfigurableApplicationContext getSpringContext() {
        return springContext;
    }
}

2. 让Jersey与Spring容器整合

修改你的JerseyConfig,让Jersey使用Spring的Bean工厂来获取REST资源,而不是手动注册类:

@Configuration
@Component
public class JerseyConfig extends ResourceConfig {
    // 通过构造方法注入Spring上下文
    public JerseyConfig(ApplicationContext context) {
        // 注册Spring组件提供者,让Jersey能从Spring上下文获取Bean
        register(SpringComponentProvider.class);
        // 扫描指定包下的REST资源和Spring组件
        packages("com.example");
    }

    @Bean
    public ServletRegistrationBean jerseyServlet(ApplicationContext context) {
        ServletContainer servletContainer = new ServletContainer(new JerseyConfig(context));
        ServletRegistrationBean registration = new ServletRegistrationBean(servletContainer, "/rest/*");
        registration.addInitParameter(
                ServletProperties.JAXRS_APPLICATION_CLASS,
                JerseyConfig.class.getName());
        return registration;
    }
}

3. 调整REST API的实例化方式

现在ExampleApi需要由Spring来管理,所以它的CordaRPCOps依赖也要通过Spring注入。先创建一个配置类来提供CordaRPCOps的Bean:

@Configuration
public class CordaBeanConfig {
    @Autowired
    private SpringBootInitializer springInitializer;

    @Bean
    public CordaRPCOps cordaRPCOps() {
        // 从Corda的AppServiceHub获取RPC操作实例
        return springInitializer.getServiceHub().getCordaRPCOps();
    }
}

然后修改ExampleApi的构造方法,让Spring注入CordaRPCOps:

@Path("example")
@Component
public class ExampleApi {
    private final CordaRPCOps rpcOps;
    private final CordaX500Name myLegalName;
    @Autowired
    TestComp testComp;

    // 新增@Autowired注解,让Spring注入CordaRPCOps
    @Autowired
    public ExampleApi(CordaRPCOps rpcOps) {
        this.rpcOps = rpcOps;
        this.myLegalName = rpcOps.nodeInfo().getLegalIdentities().get(0).getName();
    }

    @GET
    @Path("metoo")
    @Produces(MediaType.APPLICATION_JSON)
    public String whoamitest() {
        return testComp.getMyName();
    }
}

4. 排查依赖冲突

Corda本身依赖部分Spring组件,确保你使用的Spring Boot版本(1.5.9.RELEASE)和你的Corda版本兼容(比如Corda 4.x系列适配Spring Boot 1.5.x)。如果出现依赖冲突,可以在build.gradle中排除重复的Spring模块:

compile (group: 'org.springframework.boot', name: 'spring-boot-starter-jersey', version: '1.5.9.RELEASE'){
    exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
    exclude group: 'org.springframework', module: 'spring-core' // 如果Corda已包含该模块
}

关键注意点

  • 禁止Spring Boot启动独立Web服务器:必须设置WebApplicationType.NONE,否则会和Corda的内置Jetty服务器抢占端口。
  • 确保所有需要Spring管理的类都在扫描包范围内:JerseyConfig的packages("com.example")要覆盖到ExampleApi、TestComp等类的所在包。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:52:59