애플리케이션 시작 이벤트인 ApplicationStartingEvent를 예로 들어 설명하겠습니다.
시작 클래스의 SpringApplication.run 메서드를 진입점으로 사용하고 SpringApplication에서 동일한 이름의 두 메서드를 따른 후 기본 실행을 볼 수 있습니다. , 리스너와 밀접하게 관련된 주요 부분만 여기에 게시됩니다:
SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting();
우리는 이 시작 메소드에 대한 후속 조치이며, 메소드의 내용은 다음과 같습니다:
void starting() { for (SpringApplicationRunListener listener : this.listeners) { listener.starting(); } }
여기 리스너가 로드되었습니다. getRunListeners 메소드에서 로딩 원리는 시스템 이니셜라이저와 유사합니다. 시스템 이니셜라이저의 로딩에 대해서는 SpringBoot의 이니셜라이저 심층 분석을 참조할 수 있습니다. 시작 메소드의 논리는 시작을 호출하는 것입니다. SpringApplicationRunListener의 메소드. 계속해서 이 시작 메소드를 분석해 보겠습니다.
EventPublishingRunListener 클래스(SpringApplicationRunListener의 구현 클래스)의 시작 메소드를 입력합니다.
@Override public void starting() { this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args)); }
여기서 브로드캐스터는 새로운 ApplicationStartingEvent 이벤트를 브로드캐스팅하는 데 사용됩니다.
다음 multicastEvent 메서드를 추적합니다.
@Override public void multicastEvent(ApplicationEvent event) { multicastEvent(event, resolveDefaultEventType(event)); }
계속해서 같은 이름의 multicastEvent 메서드를 살펴보세요.
@Override public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); Executor executor = getTaskExecutor(); for (ApplicationListener<?> listener : getApplicationListeners(event, type)) { if (executor != null) { executor.execute(() -> invokeListener(listener, event)); } else { invokeListener(listener, event); } } }
여기서 ResolvableType은 이벤트를 래핑하므로 주의를 기울이지 않습니다. 스레드 풀, 실행기가 비어 있습니다. 우리는 두 부분에 중점을 둡니다:
이 이벤트를 수신하는 모든 애플리케이션 리스너 가져오기
2.invokeListener --> 리스너 활성화
getApplicationListeners(AbstractApplicationEventMulticaster 클래스에 있음) 메소드, 코드는 다음과 같습니다.
protected Collection<ApplicationListener<?>> getApplicationListeners( ApplicationEvent event, ResolvableType eventType) { Object source = event.getSource(); Class<?> sourceType = (source != null ? source.getClass() : null); ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType); // Quick check for existing entry on ConcurrentHashMap... ListenerRetriever retriever = this.retrieverCache.get(cacheKey); if (retriever != null) { return retriever.getApplicationListeners(); } if (this.beanClassLoader == null || (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) { // Fully synchronized building and caching of a ListenerRetriever synchronized (this.retrievalMutex) { retriever = this.retrieverCache.get(cacheKey); if (retriever != null) { return retriever.getApplicationListeners(); } retriever = new ListenerRetriever(true); Collection<ApplicationListener<?>> listeners = retrieveApplicationListeners(eventType, sourceType, retriever); this.retrieverCache.put(cacheKey, retriever); return listeners; } } else { // No ListenerRetriever caching -> no synchronization necessary return retrieveApplicationListeners(eventType, sourceType, null); } }
매개변수의 이벤트는 ApplicationStartingEvent이고 sourceType은 org.springframework.boot.SpringApplication 클래스입니다. 저는 ListenerRetriever 유형을 리스너를 저장하는 컨테이너로 생각합니다.
프로그램이 먼저 캐시에서 ListenerRetriever 유형의 검색자를 찾는 것을 볼 수 있습니다. 검색자가 없으면 잠그고 캐시에서 다시 검색합니다. 여기 캐시에는 콘텐츠가 없으므로 반환되지 않습니다.
그런 다음retrieveApplicationListeners 메서드를 사용하여 리스너를 순회합니다. retrieveApplicationListeners 메소드는 상대적으로 길며, 이 메소드는 이 리스너가 이벤트에 주의를 기울이는지 여부를 결정하는 데 사용됩니다. 이 메소드는 주로 이 유형이 GenericApplicationListener 유형인지 결정합니다. 아니, 프록시를 구성하는 것은 일반 구문 분석을 통해 리스너가 관심 있는 이벤트를 최종적으로 얻는 것입니다.
청자가 해당 이벤트에 관심이 있다고 판단되면 해당 청취자가 청취자 목록에 추가됩니다.
protected boolean supportsEvent( ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) { GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ? (GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener)); return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType)); }
이벤트에 대한 모든 리스너가 수집되면 multicastEvent(SimpleApplicationEventMulticaster 클래스) 메서드가 이벤트를 전파합니다. 즉, 리스너의 일반 트리거 인터페이스 메소드를 호출합니다.listener.onApplicationEvent(event); 이렇게 하면 이 이벤트의 전파가 완료됩니다.
위 내용은 SpringBoot 리스너 모드를 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!