在我的SpringBoot创建的项目中,
我在@SpringBootApplication中添加了2个主要类。
因为如果我使用STS,我可以在开始调试时选择一个主应用程序。
但是我发现当SpringDemoApplication启动时,RabbitMQApplication也在运行。
这是规格吗?工作得当吗?
这是重现的样本 https://github.com/MariMurotani/SpringDemo/tree/6_rabbitMQ
SpringDemoApplication
package demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class SpringDemoApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(SpringDemoApplication.class);
ApplicationContext context = application.run(args);
}
}
RabbitMQApplication
package demo;
import java.util.Date;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import demo.configs.Const;
import demo.dto.Mail;
@SpringBootApplication
public class RabbitMQApplication implements CommandLineRunner {
@Autowired
ApplicationContext context;
@Autowired
RabbitTemplate rabbitTemplate;
@Bean
Queue queue() {
return new Queue(Const.RabbitMQMessageQue, false);
}
@Bean
TopicExchange exchange() {
return new TopicExchange("spring-boot-exchange");
}
@Bean
Binding binding(Queue queue, TopicExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(Const.RabbitMQMessageQue);
}
@Bean
SimpleMessageListenerContainer container(ConnectionFactory connectionFactory) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames(Const.RabbitMQMessageQue);
//container.setMessageListener(listenerAdapter);
return container;
}
/*
For asyncronized receiving
@Bean
Receiver receiver() {
return new Receiver();
}
@Bean
MessageListenerAdapter listenerAdapter(Receiver receiver) {
return new MessageListenerAdapter(receiver, "receiveMessage");
}*/
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(RabbitMQApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
System.out.println("Waiting five seconds...");
while(0 < 1){
for(int i = 0 ; i < 5 ; i++){
String object = (String)rabbitTemplate.receiveAndConvert(Const.RabbitMQMessageQue);
if(object != null){
try{
System.out.println(new Date().toGMTString() + ": " + object);
ObjectMapper mapper = new ObjectMapper();
Mail mail = mapper.readValue(object, Mail.class);
System.out.println(mail.getToAddress() + " , " + mail.getStrContent());
}catch(Exception e){
System.out.println(e.getMessage());
}
}
}
Thread.sleep(10000);
}
}
}
答案 0 :(得分:13)
@SpringBootApplication
注释是@Configuration
,@EnableAutoConfiguration
和@ComponentScan
的快捷方式注释。
@ComponentScan
的默认行为是查找同一个包中的@Configuration
和@Component
类以及带注释的类的所有子包。由于你的所有类都在同一个包中,当你启动其中任何一个时,Spring会找到其他类,并将它们视为@Configuration
类,并注册它们的bean等。
所以是的,这是项目设置的预期行为。如果您不希望在本地测试中发生这种情况,请将每个@SpringBootApplication
类放在单独的子包中。如果这在某个时刻超出了演示,你可能想要提出一个更好的设置(也许每个@SpringBootApplication
的子项目。)
答案 1 :(得分:0)
我最近在这里也遇到了同样的情况,我用一个简单的解决方案解决了。
我的项目使用Maven并配置有以下子模块:
my-parent
|__ my-main (depends on my-other module)
|__ my-other
每个模块都有自己的主App类,并用@SpringBootApplication注释。问题在于,即使两个类位于不同的模块中,它们也位于同一包中。
一旦启动MyMainApp,它也会启动MyOtherApp。为了避免这种情况,我只需要执行以下操作即可。
在我的主模块中,我有:
@SpringBootApplication
public class MyMainApp ... { ... }
在我的另一个模块中,我有:
@SpringBootApplication
@ConditionalOnProperty(name = "my.other.active", havingValue = "true", matchIfMissing = false)
public class MyOtherApp ... { ... }
with application.properties具有:
my.other.active=true
它按预期工作。