如何通过应用程序上下文获取注释为服务的接口实例
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
SpringApplicationor
SpringApplicationBuilderto create the application context, not creating an
AnnotationConfigApplicationContext`。
我使用 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
SpringApplicationor
SpringApplicationBuilderto create the application context, not creating an
AnnotationConfigApplicationContext`。