Springboot에서 Quartz 및 RabbitMQ를 통합하면 자동으로 실행되지 않도록 설정
코드를 보면 이러한 자동 실행 프레임워크는 스프링의 SmartLifecycle 인터페이스를 실현하는 것을 발견했습니다. 자세히 보면:Spring SmartLifecycle은 용기의 모든 bean에서 불러오고 초기화되어 실행됩니다.
/**
* start 。
* true start , false 。
*/
public boolean isAutoStartup() {
// false
return true;
}
이 방법이 관건이다.설명에 따르면 이 방법은false를 되돌릴 때 start () 방법을 자동으로 실행하지 않습니다.
1. Quartz를 먼저 봅니다.Quartz하면 핵심 클래스부터 볼 수 있다.우리는 작업의 시작과 정지가 모두 Quartz Scheduler와 관련이 있다는 것을 알고 있기 때문에 Quartz Scheduler의 start () 방법부터 살펴보자.debug를 통해 Scheduler Factory Bean을 위로 계속 찾습니다.
//---------------------------------------------------------------------
// Implementation of SmartLifecycle interface
//---------------------------------------------------------------------
@Override
public void start() throws SchedulingException {
if (this.scheduler != null) {
try {
startScheduler(this.scheduler, this.startupDelay);
}
catch (SchedulerException ex) {
throw new SchedulingException("Could not start Quartz Scheduler", ex);
}
}
}
SmartLifecycle 인터페이스를 구현한 것으로 보입니다.그러면 간단합니다. isAutoStartup 방법을 직접 찾아보세요. autoStartup 필드로 되돌아온 것을 보았습니다.
@Override
public boolean isAutoStartup() {
return this.autoStartup;
}
마침 봤어요.
public void setAutoStartup(boolean autoStartup) {
this.autoStartup = autoStartup;
}
대성공은 Scheduler Factory Bean을 찾아서 set Auto Startup 방법을 사용하면 된다.
다음은 springboot2 통합quartz의 SchedulerFactoryBean 구성 코드입니다.
/**
* @Description SchedulerFactoryBean 。
* @Author yangpeng
* @Date 2018/9/18
**/
@Component
public class SchedulerConfig implements SchedulerFactoryBeanCustomizer {
@Value("${mongcent.init.task}")
private boolean runTask = false;
@Override
public void customize(SchedulerFactoryBean schedulerFactoryBean) {
// quartz ,
if (!runTask) {
schedulerFactoryBean.setAutoStartup(false);
}
schedulerFactoryBean.setStartupDelay(10);
schedulerFactoryBean.setOverwriteExistingJobs(true);
}
}
2. RabbitMQ를 봅니다.먼저 RabbitMQ의 시작 방법을 찾아서 자료를 찾아보면 RabbitListener Endpoint Registry임을 알 수 있습니다.start() 메서드는 MQ, RabbitListenerEndpointRegistry를 시작합니다.stop() 메서드는 MQ를 닫습니다.
@Override
public void start() {
for (MessageListenerContainer listenerContainer : getListenerContainers()) {
startIfNecessary(listenerContainer);
}
}
/**
* Start the specified {@link MessageListenerContainer} if it should be started
* on startup or when start is called explicitly after startup.
* @param listenerContainer the container.
* @see MessageListenerContainer#isAutoStartup()
*/
private void startIfNecessary(MessageListenerContainer listenerContainer) {
if (this.contextRefreshed || listenerContainer.isAutoStartup()) {
listenerContainer.start();
}
}
보시다시피 MessageListenerContainer 클래스의 isAutoStartup 방법으로 MQ,listenerContainer를 실행할지 여부를 결정합니다.isAutoStartup () 의 값은 어디에서 나오는 것입니까?MessageListenerContainer의 초기화를 살펴보겠습니다. start () 방법에서 getListenerContainers () 방법에서 보십시오.
/**
* @return the managed {@link MessageListenerContainer} instance(s).
*/
public Collection getListenerContainers() {
return Collections.unmodifiableCollection(this.listenerContainers.values());
}
이것을 다시 찾습니다.listener Containers는 어디서 왔나요?
/**
* Create a message listener container for the given {@link RabbitListenerEndpoint}.
* This create the necessary infrastructure to honor that endpoint
* with regards to its configuration.
*
The {@code startImmediately} flag determines if the container should be
* started immediately.
* @param endpoint the endpoint to add.
* @param factory the {@link RabbitListenerContainerFactory} to use.
* @param startImmediately start the container immediately if necessary
* @see #getListenerContainers()
* @see #getListenerContainer(String)
*/
@SuppressWarnings("unchecked")
public void registerListenerContainer(RabbitListenerEndpoint endpoint, RabbitListenerContainerFactory> factory,
boolean startImmediately) {
Assert.notNull(endpoint, "Endpoint must not be null");
Assert.notNull(factory, "Factory must not be null");
String id = endpoint.getId();
Assert.hasText(id, "Endpoint id must not be empty");
synchronized (this.listenerContainers) {
Assert.state(!this.listenerContainers.containsKey(id),
"Another endpoint is already registered with id '" + id + "'");
MessageListenerContainer container = createListenerContainer(endpoint, factory);
this.listenerContainers.put(id, container);
if (StringUtils.hasText(endpoint.getGroup()) && this.applicationContext != null) {
List containerGroup;
if (this.applicationContext.containsBean(endpoint.getGroup())) {
containerGroup = this.applicationContext.getBean(endpoint.getGroup(), List.class);
}
else {
containerGroup = new ArrayList();
this.applicationContext.getBeanFactory().registerSingleton(endpoint.getGroup(), containerGroup);
}
containerGroup.add(container);
}
if (startImmediately) {
startIfNecessary(container);
}
}
}
아래 두 줄 코드 보셨어요?
MessageListenerContainer container = createListenerContainer(endpoint, factory);
this.listenerContainers.put(id, container);
createListenerContainer 방법에서 본 것은 RabbitListenerContainerFactory입니다.createListenerContainer 방법으로 생성되었습니다.
MessageListenerContainer listenerContainer = factory.createListenerContainer(endpoint);
실현 클래스를 보십시오. Abstract Rabbit Listener Container Factory에서 많은 속성이 설정된 것을 보았습니다. 그 중에서 우리가 관심을 가지는 auto Startup이 있습니다. 되돌아오는 것은this입니다.autoStartup
else if (this.autoStartup != null) {
instance.setAutoStartup(this.autoStartup);
}
자연스럽게 set 방법을 찾았어요.
/**
* @param autoStartup true for auto startup.
* @see AbstractMessageListenerContainer#setAutoStartup(boolean)
*/
public void setAutoStartup(Boolean autoStartup) {
this.autoStartup = autoStartup;
}
그렇다면 어떻게 해야만 Abstract Rabbit Listener Container Factory의 setAutoStartup 방법을 호출할 수 있습니까?이 유형의 이름이 좀 낯익다고 생각하십니까? 이것은 추상적인 유형입니다. 우리는 어떤 유형이 있는지 보러 갑시다.보시면 Simple Rabbit Listener Container Factory를 보실 수 있습니다. 이것이 바로 저희가 소비자 속성을 설정한 그 설정 클래스 아닙니까, 완벽합니다!setAutoStartup 메서드를 직접 호출하면 해결됩니다.
마지막으로 설정을 제공합니다.
@Bean(name = "myRabbitListenerContainer")
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
//
if (!runMq) {
//
factory.setAutoStartup(false);
}
return factory;
}
결어: 한 바퀴 크게 돌았지만 설정에 두 줄의 코드를 넣었을 뿐, 아무 소용이 없는 것 같다.그러나 이 한 바퀴를 보면 저는 스프링의 시작 과정에 대해 더 많은 인식을 가지게 되었고 우수한 프레임워크의 디자인 사고방식을 배웠습니다. 이것은 매우 할 만한 일입니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Fragmenta의 각서라고 할까, 그것 밖에 발견되지 않았기 때문에 시도해보기로 했습니다. 다만, 내용을 보면 어플리케이션을 만드는 프레임워크로서 사용되는 것도 의식하고 있는 것 같습니다. 하지만, 지금은 정확하지 않은 것 같기 때문에,...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.