如何通过应用程序上下文获取注释为服务的接口实例

How to get instance of Interface annotated as Service via Application Context

我使用 spring 编写了一个库,用于非 spring 和 Spring 基于启动的应用程序。

我使用消息传递网关将集成流公开为普通的旧 java 接口,供其他 classes

使用
import org.springframework.messaging.Message;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public interface SwiftalkKafkaGateway {

    @Async
    void publish(Message<?> message);
}

我在通过 Spring 上下文获取此网关 class 的实例时遇到了麻烦;使用该库的其中一个应用程序在 JavaEE 8 CDI 环境中运行;我为此编写了一个加载器

@Singleton
@ApplicationScoped
public class SwiftalkAnnotatedSpringContextLoader {

    private final AnnotationConfigApplicationContext springContext;

    SwiftalkAnnotatedSpringContextLoader(String propertiesFile) throws IOException {
        springContext = new AnnotationConfigApplicationContext();
        ConfigurableEnvironment environment = new StandardEnvironment();
        MutablePropertySources propertySources = environment.getPropertySources();
        Properties appProps = new Properties();
        appProps.load(this.getClass().getClassLoader().getResourceAsStream(propertiesFile));
        propertySources.addFirst(new PropertySource<Properties>("spring-properties", appProps) {
            @Override
            public Object getProperty(String name) {
                return appProps.getProperty(name);
            }
        });
        springContext.setEnvironment(environment);
        springContext.scan("com.foo.cloud.swiftalk");
        springContext.refresh();
    }

    ApplicationContext getSwiftalkKafkaClientContext() {
        return this.springContext;
    }

}

但是获取 bean 实例失败

    SwiftalkKafkaGateway kafkaGateway = loader.getSwiftalkKafkaClientContext().getBean(
            SwiftalkKafkaGateway.class);
    assertNotNull(kafkaGateway);

有错误

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.foo.cloud.swiftalk.SwiftalkKafkaGateway' available

这是由于

21:37:42.003 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Ignored because not a concrete top-level class: URL [jar:file:/Users/anadimishra/.m2/repository/com/foo/cloud/swiftalk-kafka-client/1.0.0-SNAPSHOT/swiftalk-kafka-client-1.0.0-SNAPSHOT-jar-with-dependencies.jar!/com/foo/cloud/swiftalk/SwiftalkKafkaGateway.class]

如何获取此服务的实例以在非 spring 环境中使用?

更新

我使用这个的集成流程

@Bean
public IntegrationFlow kafkaPublisherFlow(KafkaProducerMessageHandler<String, String> kafkaProducerMessageHandler,
                                          RequestHandlerRetryAdvice retryAdvice,
                                          ExecutorChannel kafkaPublishChannel) {
    return IntegrationFlows.from(SwiftalkKafkaGateway.class)
            .channel(kafkaPublishChannel)
            .handle(kafkaProducerMessageHandler, e -> e.advice(retryAdvice))
            .get();
}

我们的想法是能够在 spring 启动和非 spring 启动应用程序中重用这个带有错误处理和幂等操作代码的 kafka 发布者。

如果你想使用 Sprint Boot 的 @EnableAutoConfiguration, you should be using SpringApplicationorSpringApplicationBuilderto create the application context, not creating anAnnotationConfigApplicationContext`。