Sha*_*mad -2 java spring mqtt spring-boot
我正在使用spring-integration-mqtt
依赖项编写 Spring Boot 应用程序,其中我使用CommandLineRunner
beanMQTTSubscriber
在应用程序启动时启动。
但是,当我运行该应用程序时,出现以下错误:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2019-01-26 01:48:40.386 ERROR 59171 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Field MessageListener in im.sma.mqtt.mqttclient.DemoApplication required a single bean, but 2 were found:
- messageListener: defined in file [/Users/sma/sandbox/slidecab/mqtt/mqtt-client/target/classes/im/sma/mqtt/mqttclient/config/MessageListener.class]
- integrationHeaderChannelRegistry: defined in null
Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
Run Code Online (Sandbox Code Playgroud)
我注意到当我从代码中删除以下部分时错误消失了:
@Autowired
Runnable MessageListener;
@Bean
public CommandLineRunner schedulingRunner(TaskExecutor executor) {
return new CommandLineRunner() {
public void run(String... args) throws Exception {
executor.execute(MessageListener);
}
};
}
Run Code Online (Sandbox Code Playgroud)
这是我DemoApplication
发生错误的班级:
@SpringBootApplication
public class DemoApplication extends SpringBootServletInitializer {
@Autowired
Runnable MessageListener;
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(DemoApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
public CommandLineRunner schedulingRunner(TaskExecutor executor) {
return new CommandLineRunner() {
public void run(String... args) throws Exception {
executor.execute(MessageListener);
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
此外,我还有以下AppConfig
课程来设置TaskExecutor
:
@Component
public class AppConfig {
@Bean
@Primary
public TaskExecutor taskExecutor() {
return new SimpleAsyncTaskExecutor();
}
}
Run Code Online (Sandbox Code Playgroud)
这是MessageListener
它无法自动装配的 bean:
@Component
public class MessageListener implements Runnable {
@Autowired
MQTTSubscriberBase subscriber;
@Override
public void run() {
while(true) {
subscriber.subscribeMessage("demoTopic2019");
}
}
}
Run Code Online (Sandbox Code Playgroud)
另外,我有以下配置来设置MQTTSubscriber
:
public abstract class MQTTConfig {
protected final String broker = "localhost";
protected final int qos = 2;
protected Boolean hasSSL = false; /* By default SSL is disabled */
protected Integer port = 1883; /* Default port */
protected final String userName = "guest" ;//"testUserName";
protected final String password = "guest";//"demoPassword";
protected final String TCP = "tcp://";
protected final String SSL = "ssl://";
protected abstract void config(String broker, Integer port, Boolean ssl, Boolean withUserNamePass);
protected abstract void config();
}
Run Code Online (Sandbox Code Playgroud)
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2019-01-26 01:48:40.386 ERROR 59171 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Field MessageListener in im.sma.mqtt.mqttclient.DemoApplication required a single bean, but 2 were found:
- messageListener: defined in file [/Users/sma/sandbox/slidecab/mqtt/mqtt-client/target/classes/im/sma/mqtt/mqttclient/config/MessageListener.class]
- integrationHeaderChannelRegistry: defined in null
Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
Run Code Online (Sandbox Code Playgroud)
@Autowired
Runnable MessageListener;
@Bean
public CommandLineRunner schedulingRunner(TaskExecutor executor) {
return new CommandLineRunner() {
public void run(String... args) throws Exception {
executor.execute(MessageListener);
}
};
}
Run Code Online (Sandbox Code Playgroud)
这些是我正在使用的依赖项:
@SpringBootApplication
public class DemoApplication extends SpringBootServletInitializer {
@Autowired
Runnable MessageListener;
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(DemoApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
public CommandLineRunner schedulingRunner(TaskExecutor executor) {
return new CommandLineRunner() {
public void run(String... args) throws Exception {
executor.execute(MessageListener);
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
为什么我不能注入bean,我应该采取什么行动?
问题是您正在使用一个非常通用的接口来进行自动装配,即Runnable
.
因此,似乎存在两个与Runnable
接口匹配的 bean :
MessageListener
你自己创建的类DefaultHeaderChannelRegistry
称为integrationHeaderChannelRegistry
. 大概它被公开是因为您的类路径上有 Spring 集成。问题是由于这个原因,Spring IoC 容器无法弄清楚它应该注入什么 bean,它提供了一些解决方案。
@Primary
这可以用于 99% 的场景中将使用这些 bean 之一的场景。通过将MessageListener
类标记为@Primary
,它会在尝试注入时优先,例如:
@Primary // Add this
@Component
public class MessageListener implements Runnable {
// ...
}
Run Code Online (Sandbox Code Playgroud)
当您想要引用所有Runnable
bean时,此方案很有用。就您而言,这可能不是解决方案,但在某些情况下,您可能希望获取某种类型的所有 bean。要做到这一点,你可以这样做:
@Autowired
private List<Runnable> runnables; // Change the type to List<Runnable>
Run Code Online (Sandbox Code Playgroud)
@Qualifier
识别豆另一种可能性是用于@Qualifier
指定要注入的 bean 的确切名称。在您的情况下,您可以在messageListener
或之间进行选择integrationHeaderChannelRegistry
。例如:
@Autowired
@Qualifier("messageListener")
private Runnable mesageListener;
Run Code Online (Sandbox Code Playgroud)
在您提出的案例中,这可能是最佳解决方案。
我还想提供一些其他解决方案。
如果您将自动装配字段的类型更改为MessageListener
,则不会混淆应该注入哪个 bean,因为只有一个类型为 的 bean MessageListener
:
@Autowired
private MessageListener mesageListener;
Run Code Online (Sandbox Code Playgroud)
到目前为止,您显示的代码与 Spring 集成无关。如果您的唯一目标是设置 MQTT 客户端,您可能需要考虑放弃该spring-integration-mqtt
包并使用简单的 MQTT 客户端实现,如Eclipse Paho。
由于您添加了spring-integration-mqtt
库,其他 bean 正在自动创建,删除它会停止导致 bean 被创建,这也将解决问题。
归档时间: |
|
查看次数: |
5515 次 |
最近记录: |