因此,这是与this one相关的新问题>
我创建了一个情况,即使ListenerContainer
的相位为@Bean
,它实际上仍在Integer.MAX_INT
的相位为0的情况下运行。这是代码:
import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.springframework.amqp.core.QueueBuilder; import org.springframework.amqp.rabbit.annotation.Exchange; import org.springframework.amqp.rabbit.annotation.Queue; import org.springframework.amqp.rabbit.annotation.QueueBinding; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.amqp.rabbit.config.DirectRabbitListenerContainerFactory; import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.amqp.rabbit.core.RabbitAdmin; import org.springframework.amqp.rabbit.listener.DirectMessageListenerContainer; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.SmartLifecycle; import org.springframework.context.annotation.Bean; import org.springframework.context.support.GenericApplicationContext; @SpringBootApplication public class RuntimeRegisterApp { public static void main(String[] args) { SpringApplication.run(RuntimeRegisterApp.class, args); } @Bean public CachingConnectionFactory cachingConnectionFactory(){ CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory(); cachingConnectionFactory.setAddresses("10.10.121.199:35682"); cachingConnectionFactory.setUsername("guest"); cachingConnectionFactory.setPassword("guest"); return cachingConnectionFactory; } @Bean public DirectRabbitListenerContainerFactory directFactory(ConnectionFactory cachingConnectionFactory) { DirectRabbitListenerContainerFactory factory = new DirectRabbitListenerContainerFactory(); factory.setConnectionFactory(cachingConnectionFactory); return factory; } @RabbitListener(bindings = { @QueueBinding(value = @Queue(value = "SomeQueue", durable = "false", autoDelete = "true"), exchange = @Exchange(value = "SomeEX", ignoreDeclarationExceptions = "true"), key = "SomeKey") }, containerFactory = "directFactory" ) public void onMessage(String msg){ System.out.println("Received " + msg); } public void onMessage2(String msg){ System.out.println("Received 2 " + msg); } @Bean public org.springframework.amqp.core.Queue someQueue(){ return QueueBuilder.nonDurable("some1").build(); } @Bean public DirectMessageListenerContainer container(DirectRabbitListenerContainerFactory directFactory){ DirectMessageListenerContainer container = directFactory.createListenerContainer(); container.setConsumersPerQueue(2); container.setMessageListener( message -> System.out.println("BEAN CONTAINER " + message.toString())); container.setQueues(someQueue()); return container; } @Bean public RabbitAdmin rabbitAdmin(){ return new RabbitAdmin(cachingConnectionFactory()); } @Bean SmartLifecycle dynamicRegister(GenericApplicationContext applicationContext, DirectMessageListenerContainer container, DirectRabbitListenerContainerFactory directFactory, RabbitAdmin rabbitAdmin){ return new SmartLifecycle() { private boolean running; private void dynamicallySetQueues(){ org.springframework.amqp.core.Queue q1 = QueueBuilder .nonDurable("mySomeQueue") .build(); rabbitAdmin.declareQueue(q1); applicationContext.registerBean(org.springframework.amqp.core.Queue.class, () -> q1); List<String> queues = new ArrayList<>(Arrays.asList(container.getQueueNames())); queues.add(q1.getName()); //THIS ONE WORKS SINCE WE USE FACTORY AND SET QUEUES BEFORE START DirectMessageListenerContainer container1 = directFactory.createListenerContainer(); container1.setQueueNames(queues.toArray(new String[0])); container1.setMessageListener(message -> System.out.println("INNER CONTAINER" + message.toString())); container1.start(); //THIS ONE WORKS SINCE WE ONLY ADD QUEUES container.addQueueNames(q1.getName()); //SETTING QUEUES HERE FAILS, SINCE CONTAINER ALREADY RUNNING //BUT IT SHOULD NOT RUN, SINCE THIS IS PHASE 0 ? //I GUESS SINCE IT IS NEEDED HERE IT RUNS ANYWAY ? container.setQueueNames(queues.toArray(new String[0])); } @Override public void start() { dynamicallySetQueues(); running = true; } @Override public void stop() { running = false; } @Override public int getPhase() { return 0; //return 0 so we add queues before ListenerContainer starts } @Override public boolean isRunning() { return running; } }; } }
我猜它正在运行,因为它实际上是对
SmartLifecycle
bean的依赖。我在这里只能看到的解决方法是在Container上单击setAutostart(false
),然后在设置队列名称后在SmartLifecycle
bean内部调用container.start()
。
因此,这是与此相关的新问题,我创建了一个案例,其中ListenerContainer实际上在阶段0的@Bean之前运行,即使它具有阶段Integer.MAX_INT。这是代码:...
您是正确的;生命周期处理器会在启动当前bean之前启动所有从属bean ...
好,所以这似乎是我到目前为止最好的实现: