Spring 의 사건 감청 메커니즘 예시 상세 설명

머리말
최근 에 회 사 는 광고 시스템 을 재 구성 하고 있 는데 그 중에서 핵심 적 인 포장 공 은 광고 시스템 에서 호출 된다.즉,apk 포장 에 대한 호출 과 포장 이 완 료 된 후의 리 셋 은 해당 하 는 인 터 페 이 스 를 광고 시스템 에 제공 해 야 한다.따라서 apk 패키지 의 핵심 프로 세 스 와 도 킹 광고 시스템 의 업무 디 결합 을 위해 spring 의 이벤트 감청 특성 을 이용 하여 수 요 를 만족 시 켰 습 니 다.다음은 spring 의 이벤트 메커니즘 에 관 한 내용 을 설명 합 니 다.
우선 스프링 사건 은 이벤트 발표 자(EventPublisher),이벤트 감청 자(EventListener)로 나 뉘 며,이벤트 방송 자(이것 은 스프링 실현 과 관련 된 것 이 며,이 절 은 토론 하지 않 음)도 포함 된다.spring 이벤트 체 제 를 사용 하려 면 이벤트 발표 자 와 감청 자 를 사용자 정의 해 야 합 니 다.
1.관찰자 모드
Spring 의 이벤트 감청(이벤트 구동 이 라 고도 함)은 관찰자 모델 의 실현 으로 비교적 흔히 볼 수 있 는 게시-구독 모델 이 있다.일반적으로 저 희 는 메시지 큐 를 이용 하여 서로 다른 시스템 간 의 디 결합 을 실현 합 니 다.예 를 들 어 사용자 등록 이 완료 되면 메시지 큐 에 메 시 지 를 발표 한 다음 에 이 topic 의 서브 시스템(예 를 들 어 메 일 서비스,포인트 서비스)을 구독 하여 발표 한 메 시 지 를 받 은 후에 해당 하 는 처 리 를 할 수 있 습 니 다.이렇게 하 는 장점 은 등록 서비스 에서 다른 서비스의 코드 를 결합 시 키 는 것 을 피 하 는 것 이 고 서브 시스템 의 업 무 를 수행 하 는 것 은 비동기 적 으로 실행 되 고 서로 영향 을 주지 않 는 다 는 것 이다.아래 그림 은 전형 적 인 관찰자 모델 의 구조 이다.

다음은 상기 관찰자 모드 의 자바 간단 한 실현:
(1)Subject.java

package observerPattern;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by jy on 2018/11/28.
 */
public abstract class Subject {

 //           
 private List<Observer> list = new ArrayList<>();

 //        
 public void attach(Observer observer){
 list.add(observer);
 System.out.println("        ");
 }

 //           
 public void detach(Observer observer){
 list.remove(observer);
 System.out.println("           ");
 }


 //            
 public void notifyObservers(String state){
 for (int i = 0; i < list.size(); i++) {
 list.get(i).update(state);
 }
 }
}
(2)Observer.java

package observerPattern;

/**
 * Created by jy on 2018/11/28.
 */
public interface Observer {

 //         
 public void update(String state);
}
(3)ConcreteSubject.java

package observerPattern;

/**
 * Created by jy on 2018/11/28.
 */
public class ConcreteSubject extends Subject{

 //           
 private String state;

 public String getState() {
 return state;
 }

 public void change(String state){
 this.state = state;
 System.out.println("         :"+state);
 this.notifyObservers(state);
 }
}
(4)ConcreteObserver.java

package observerPattern;

/**
 * Created by jy on 2018/11/28.
 */
public class ConcreteObserver implements Observer {

 //        
 private String observerState;

 @Override
 public void update(String state) {
 //                       
 observerState = state;
 System.out.println("           :"+observerState);
 }
}
(5)Main.java

package observerPattern;

/**
 * Created by jy on 2018/11/28.
 */
public class Main {
 public static void main(String[] args) {
 //    
 ConcreteSubject concreteSubject = new ConcreteSubject();
 //     
 ConcreteObserver concreteObserver = new ConcreteObserver();
 //      
 concreteSubject.attach(concreteObserver);

 //        
 concreteSubject.change("2");

 }
}
결과:main 방법 을 실행 한 후에 우 리 는 콘 솔 출력 결 과 를 볼 수 있 습 니 다.이 는 실제 관찰자 의 상 태 는 실제 주제 의 상태 변화 에 따라 달라 집 니 다.

2.스프링 사건 감청
spring 도 이벤트 구동 모델 에 지원 을 제공 합 니 다.이 모델 은 주로 세 부분 으로 구성 되 어 있 습 니 다.
(1)  이벤트(ApplicationEvent):jdk 의 EventObject 를 계승 하여 spring 프로젝트 에서 ApplicationEvent 를 계승 하여 자신의 이 벤트 를 정의 할 수 있 습 니 다.
spring 용기 내부 에 서 는 applicationEvent 에 대해 다음 과 같은 몇 가지 실현 이 있 으 며,이름 을 통 해 사건 이 묘사 한 행 위 를 잘 알 수 있 습 니 다.
 
(2)발표 자(ApplicationEventPublisher):이 인 터 페 이 스 를 실현 하면 spring 구성 요소 가 사건 을 발표 하 는 능력 을 가 질 수 있 습 니 다.
응용 프로그램 Context 가 이 인 터 페 이 스 를 실현 한 것 을 볼 수 있 습 니 다.따라서 spring 구성 요 소 는 응용 프로그램 ContextAware 인 터 페 이 스 를 실현 하고 응용 프로그램 Context 를 주입 한 다음 에 응용 프로그램 Context 의 PublishEvent()방법 으로 사건 전 파 를 실현 할 수 있 습 니 다.
물론 ApplicationEventPublisher 인 터 페 이 스 를 직접 실현 하고 PublisheEvent()방법 을 다시 쓰 면 사건 전 파 를 실현 할 수 있다.
 
원본 코드 를 읽 은 결과 AbstractApplication Context 류 에서 관찰자 의 증가,get,등록 등 방법 을 정의 했다.다음 코드 의 addapplicationListener()는 applicationEvent Multicaster 클래스 에서 유지 하 는 set 에 listener 를 추가 합 니 다.이 set 는 게시 자의 모든 관찰자(listener)를 저장 합 니 다.

@Override
 public void addApplicationListener(ApplicationListener<?> listener) {
 Assert.notNull(listener, "ApplicationListener must not be null");
 //listener        applicationEventMulticaster  
 if (this.applicationEventMulticaster != null) {
 this.applicationEventMulticaster.addApplicationListener(listener);
 }
 this.applicationListeners.add(listener);
 }

//      

protected void registerListeners() {
 // Register statically specified listeners first.
 for (ApplicationListener<?> listener : getApplicationListeners()) {
 getApplicationEventMulticaster().addApplicationListener(listener);
 }

 // Do not initialize FactoryBeans here: We need to leave all regular beans
 // uninitialized to let post-processors apply to them!
 String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
 for (String listenerBeanName : listenerBeanNames) {
 getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
 }

 // Publish early application events now that we finally have a multicaster...
 Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
 this.earlyApplicationEvents = null;
 if (earlyEventsToProcess != null) {
 for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
 getApplicationEventMulticaster().multicastEvent(earlyEvent);
 }
 }
 }
AbstractApplication Context 에서 PublishEvent:

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
 //.....
 // Multicast right now if possible - or lazily once the multicaster is initialized
 if (this.earlyApplicationEvents != null) {
 this.earlyApplicationEvents.add(applicationEvent);
 }
 else {
 getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); //    
 //....
 }
구체 적 으로 이 벤트 를 발표 하 는 방법 은 위 에서 언급 한 ApplicationEvent Multicaster 라 는 유형의 클래스 에서 이 루어 집 니 다.AbstractApplicationContext 에 서 는 ConfigurableListableBeanFactory 에서 이 종 류 를 불 러 오 려 고 합 니 다.존재 하지 않 으 면 new Simple ApplicationEvent Multicaster 를 기본 으로 합 니 다.

protected void initApplicationEventMulticaster() {
 ConfigurableListableBeanFactory beanFactory = getBeanFactory();
 if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { //    
 this.applicationEventMulticaster =
  beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
 if (logger.isTraceEnabled()) {
 logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
 }
 }
 else {
 this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); //        SimpleApplicationEventMulticaster
 beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
Simple Application Event Multicaster 가 어떻게 사건 을 방송 하 는 지 보 세 요.코드 를 통 해 알 수 있 듯 이 온라인 풀 이 비어 있 지 않 은 상황 에서 특정한 유형의 사건 을 비동기 적 으로 발표 합 니 다.

@Override
 public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
 ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
 for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
 Executor executor = getTaskExecutor();
 if (executor != null) {
 executor.execute(() -> invokeListener(listener, event));
 }
 else {
 invokeListener(listener, event);
 }
 }
 //....
invokeListener 방법 을 마지막 으로 클릭 하면 listener 의 onApplicationEvent()를 호출 하여 이벤트 발 표를 실현 한 것 을 발견 합 니 다.

private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
 try {
 listener.onApplicationEvent(event);
 }
 catch (ClassCastException ex) {
 //....
 }
 }
(3)이벤트 구독 자(ApplicationListener):이 인 터 페 이 스 를 실현 하면 ApplicationListener 가 발표 한 특정한 이 벤트 를 감청 할 수 있 습 니 다.

ApplicationListener 라 는 인 터 페 이 스 를 실현 하고 onApplicationEvent()방법 을 다시 써 서 들 은 ApplicationEvent 를 처리 합 니 다.여 기 는 특정한 유형의 사건 을 감청 할 수 있 습 니 다.
3.주 해 를 바탕 으로 하 는 사건 감청    
spring 도 발표 자 와 감청 자 에 게 해당 하 는 주석 지원 을 제공 합 니 다.해당 하 는 관찰자 류 의 대응 방법 에@EventListener 를 추가 하면 됩 니 다.

게시 자 에 대해 서 는 service 에서@Autowired 를 통 해 applicationEventPublisher 를 직접 주입 할 수 있 습 니 다.
4.소결
글 은 주로 spring 에서 이벤트 구동 모델 을 소개 했다.주로 관찰자 모델 의 사상 을 활용 한 다음 에 spring 에서 사건 발표 체 제 를 소개 했다.
총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

좋은 웹페이지 즐겨찾기