我正在开发一个具有可重用逻辑的通用java库,以与一些AWS服务交互,这些服务将被几个消费者应用程序使用。由于这里概述的原因,以及Spring Boot似乎为SQS集成等提供了许多无样板的代码,我决定将这个公共库实现为具有自动配置的自定义Spring Boot启动器。
我对Spring框架也完全陌生,因此遇到了一个问题,即我的自动配置类的实例变量没有通过AutoWired注释进行初始化。
为了更好地解释这一点,这里是我的常见依赖项的一个非常简化的版本。
CommonCore.java
@Component
public class CommonCore {
@AutoWired
ReadProperties readProperties;
@AutoWired
SqsListener sqsListener; // this will be based on spring-cloud-starter-aws-messaging
public CommonCore() {
Properties props = readProperties.loadCoreProperties();
//initialize stuff
}
processEvents(){
// starts processing events from a kinesis stream.
}
}
ReadProperties.java
@Component
public class ReadProperties {
@Value("${some.property.from.application.properties}")
private String someProperty;
public Properties loadCoreProperties() {
Properties properties = new Properties();
properties.setProperty("some.property", someProperty);
return properties;
}
}
CoreAutoConfiguration.java
@Configuration
public class CommonCoreAutoConfiguration {
@Bean
public CommonCore getCommonCore() {
return new CommonCore();
}
}
常见的依赖关系将被其他应用程序使用,如
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class SampleConsumerApp implements ApplicationRunner {
@Autowired
CommonCore commonCore;
public SampleConsumerApp() {
}
public static void main(String[] args) {
SpringApplication.run(SampleConsumerApp.class, args);
}
@Override
public void run(ApplicationArguments args) {
try {
commonCore.processEvents();
} catch (Exception e) {
e.printStackTrace();
}
}
}
正如我提到的,我遇到的主要问题是CommonCore
实例中的AutoWired
对象没有按预期进行初始化。然而,我认为实际问题的根源更为深刻;但由于我对Spring框架缺乏了解,我发现自己很难调试它。
我希望能在这几点上提供一些建议
- 这种开发自定义启动器的方法对我的用例有意义吗
- AutoWired依赖项没有用这种方法初始化的原因是什么
猜测,但我认为这是因为事物的构造顺序。我说的是这门课:
@Component
public class CommonCore {
@AutoWired
ReadProperties readProperties;
@AutoWired
SqsListener sqsListener; // this will be based on spring-cloud-starter-aws-messaging
public CommonCore() {
Properties props = readProperties.loadCoreProperties();
//initialize stuff
}
processEvents(){
// starts processing events from a kinesis stream.
}
}
您正试图在构造函数中使用Spring注入的组件,但在Spring执行其@Autowire魔术之前,构造函数已被调用。
因此,一种选择是自动连线作为构造函数参数
类似的东西(未经测试(:
@Component
public class CommonCore {
private final ReadProperties readProperties;
private final SqsListener sqsListener; // this will be based on spring-cloud-starter-aws-messaging
@AutoWired
public CommonCore(SqsListener sqsListener, ReadProperties readProperties) {
this.readProperties = readPropertis;
this.sqsListener = sqsListener;
Properties props = readProperties.loadCoreProperties();
//initialize stuff
}
processEvents(){
// starts processing events from a kinesis stream.
}
}
旁注:我更喜欢通过构造函数参数始终使用依赖项注入,只要可能。这也使得单元测试在没有任何Spring特定测试库的情况下变得更加容易。