spring - 使用 Spring Cloud 函数 AWS Adapter 运行 AWS lambda 函数时,spring 不会注入(自动装配)组件 bean
问题描述
我正在使用 Spring Cloud 函数 AWS Adapter SpringBootRequestHandler 实现 AWS lambda 函数创建处理程序。在 GenericApplicationContext 中注册的功能 bean 被调用,但组件类的自动装配给出了 NullPointer 异常。
我在 Spring Application 中尝试过 @ComponentScan 的基本包。
应用类:
@Slf4j
@SpringBootApplication
@ComponentScan({ "com.poc.evthub" })
@EnableConfigurationProperties(EventHubProperties.class)
public class EventHubServerlessApplication implements ApplicationContextInitializer<GenericApplicationContext> {
public EventHubServerlessApplication() {
}
public static void main(String[] args) throws Exception {
FunctionalSpringApplication.run(EventHubServerlessApplication.class, args);
}
@Bean
public KinesisEventFunction ingestEvents() {
return new KinesisEventFunction();
}
@Override
public void initialize(GenericApplicationContext context) {
log.debug("======== initialize ========");
context.registerBean("ingestEvents", FunctionRegistration.class,
() -> new FunctionRegistration<Function<KinesisEvent, ApiResponse>>(ingestEvents())
.type(FunctionType.from(KinesisEvent.class).to(ApiResponse.class).getType()));
}
}
处理程序:
public class KinesisEventHandler extends SpringBootRequestHandler<KinesisEvent, ApiResponse> {
}
功能豆:
package com.poc.evthub.function;
import com.amazonaws.services.lambda.runtime.events.KinesisEvent;
import com.poc.evthub.beans.ApiResponse;
import com.poc.evthub.constant.Constants;
import com.poc.evthub.service.IngestionServiceFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.function.Function;
@Slf4j
@Component
public class KinesisEventFunction implements Function<KinesisEvent, ApiResponse> {
private Context context = null;
@Autowired
private IngestionServiceFactory ingestionServiceFactory;
@Autowired
@Qualifier("targetExecutionContext")
public void setContext(Context context) {
log.info("Context: {}", context);
this.context = context;
}
@Override
public ApiResponse apply(final KinesisEvent kinesisEvent) {
log.info("KinesisEventFunction apply called...");
String sourceDomain = System.getenv(Constants.SYSENV.SOURCE_DOMAIN);
log.info("Source Domain = {}", sourceDomain);
if(null == kinesisEvent || null == kinesisEvent.getRecords()) {
log.error("Event contains no data. {}", System.lineSeparator());
//TODO build response NOT FOUND
return null;
}
else
log.info("Received {} records from {}. {}",
kinesisEvent.getRecords().size(),
kinesisEvent.getRecords().get(0).getEventSourceARN(),
System.lineSeparator());
log.info("ingestionServiceFactory = {}",ingestionServiceFactory);
ingestionServiceFactory.ingest();
return null;
}
}
完整的代码和 pom 上传到: https ://github.com/rjavaria/eventhub-serverless
KinesisEventFunction apply 调用... 还能够从 lambda 读取环境值(source_domain),并接收 Kinesis 事件记录。
但是@Autowired ingestionServiceFactory 为空。我正在注入这个组件 bean 来委派业务逻辑。
这里遗漏了什么,所以spring不能注入这个组件bean?
提前致谢!
解决方案
您可以尝试IngestionServiceFactory
通过构造函数或 setter 注入手动将 bean 注入函数类。
在您的函数类中,添加一个构造函数并@Autowired
从您的IngestionServiceFactory
字段中删除,例如:
...
public class KinesisEventFunction implements Function<KinesisEvent, ApiResponse> {
...
// No @Autowired here...
private final IngestionServiceFactory ingestionServiceFactory;
...
// The new constructor here...
public KinesisEventFunction(final IngestionServiceFactory pIngestionServiceFactory) {
this.ingestionServiceFactory = pIngestionServiceFactory;
}
...
}
然后在您的主类(实现的那个ApplicationContextInitializer<GenericApplicationContext>
)中,在注册函数 bean 时将引用传递给工厂,例如:
...
public class EventHubServerlessApplication implements ApplicationContextInitializer<GenericApplicationContext> {
...
@Autowired
private IngestionServiceFactory ingestionServiceFactory;
...
@Bean
public KinesisEventFunction ingestEvents() {
return new KinesisEventFunction(this.ingestionServiceFactory);
}
@Override
public void initialize(GenericApplicationContext context) {
log.debug("======== initialize ========");
context.registerBean("ingestEvents", FunctionRegistration.class,
() -> new FunctionRegistration<>(ingestEvents())
.type(FunctionType.from(KinesisEvent.class).to(ApiResponse.class).getType()));
}
}
或者,由于您已经手动注册了函数 bean context.registerBean()
,您可以:
...
public class EventHubServerlessApplication implements ApplicationContextInitializer<GenericApplicationContext> {
...
@Autowired
private IngestionServiceFactory ingestionServiceFactory;
...
@Override
public void initialize(GenericApplicationContext context) {
log.debug("======== initialize ========");
context.registerBean("ingestEvents", FunctionRegistration.class,
() -> new FunctionRegistration<>(new KinesisEventFunction(this.ingestionServiceFactory))
.type(FunctionType.from(KinesisEvent.class).to(ApiResponse.class).getType()));
}
}
请让我知道它是否有效!
推荐阅读
- kubernetes - 在 minikube 中以详细模式运行 Kubernetes api 服务器
- python - 遍历 panda 列以分配事件
- c# - ASP.NET Identity UserID 主键是自定义表中的外键和主键
- sql - SQL 用 ntile 将列值分成相等的组
- java - 当我发送大于1M的json字符串时,如何解决Spring MVC中的org.springframework.web.bind.MissingServletRequestParameterException?
- python - 为什么辐射校正后波段 5、6 和 7 会出现负值?
- r - 在 Mac 上将 R 升级到 3.6.0 后无法加载库
- php - Laravel Collection 按来自另一个集合的值过滤集合
- python - 如何在 Python 中合并两个不同维度的 numpy 数组?
- r - 我在哪里可以找到 R 的随机森林使用的 dotcall64 相关参数?