Spring 소스 코드 - 감청 이벤트 ApplicationListener 와 ApplicationEvent 소스 코드 분석

Spring 소스 코드 - 감청 이벤트 ApplicationListener 와 ApplicationEvent 소스 코드 분석
Spring 에서 ApplicationListener 와 ApplicationEvent 는 전형 적 인 이벤트 구동 모델 이다. 즉, 우리 가 흔히 말 하 는 발표 - 구독 모델 이다.사실 저 희 는 개발 과정 에서 이런 발표 - 구독 모델 모델 을 자주 사용 합 니 다. 구독 모델 을 발표 하 는 것 은 보통 한 쌍 의 대상 관계 에 사 용 됩 니 다. 예 를 들 어 다음 과 같은 사례 에서 저 희 는 이런 발표 - 구독 모델 을 사용 할 수 있 습 니 다.
사례: 사용자 등록 이 성공 한 후에 종종 다른 일 을 해 야 한다.
1. 포인트 추가
2. 확인 메 일 보 내기
3. 게임 계 정 이 라면 게임 선물 을 증정 할 수 있 습 니 다.
4. 색인 사용자 데이터
상기 사례 에서 만약 에 우리 가 업 무량 이 많 지 않 을 때 스프링 의 발표 - 구독 모드 를 직접 사용 하면 해결 할 수 있다. 각각 네 개의 감청 기 를 등록 하고 각각 네 가지 절 차 를 감청 하 며 모든 감청 기 는 독립 적 으로 한 가지 일 을 할 수 있다.이런 모델 을 사용 하면 코드 를 결합 시 킬 수 있 고 다 중 스 레 드 의 장점 과 결합 하여 성능 을 제공 할 수 있다.
1.  우선, 다음 Spring 의 게시 - 구독 모드 를 초보 적 으로 사용 합 니 다. 다음은 테스트 코드 입 니 다.
먼저 설정 파일 에 MyListen 과 MyListen 2 모니터 의 Bean 을 설정 합 니 다.


MyListen.java
package cn.edu.his.pay.listen;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;

public class MyListen implements ApplicationListener {

	public void onApplicationEvent(ApplicationEvent arg0) {
		
		if(arg0 instanceof MyEvent) {
			MyEvent event = (MyEvent)arg0;
			
			System.out.println(this.getClass().getName() + event.getParam1());
			System.out.println(this.getClass().getName() + event.getParam2());
			System.out.println(this.getClass().getName() + event.getSource());
			
		}
	}
	
}

 MyListen2.java
package cn.edu.his.pay.listen;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;

public class MyListen2 implements ApplicationListener {

	public void onApplicationEvent(ApplicationEvent arg0) {
		
		if(arg0 instanceof MyEvent) {
			MyEvent event = (MyEvent)arg0;
			
			System.out.println(this.getClass().getName() + event.getParam1());
			System.out.println(this.getClass().getName() + event.getParam2());
			System.out.println(this.getClass().getName() + event.getSource());
			
		}
	}
	
}

MyEvent.java
package cn.edu.his.pay.listen;

import org.springframework.context.ApplicationEvent;

public class MyEvent extends ApplicationEvent {
	
	public String param1;
	
	public String param2;
	
	public MyEvent(Object source,String param1,String param2) {
		super(source);
		this.param1 = param1;
		this.param2 = param2;
	}

	public Object getSource() {
		return super.getSource();
	}

	public String getParam1() {
		return param1;
	}

	public void setParam1(String param1) {
		this.param1 = param1;
	}

	public String getParam2() {
		return param2;
	}

	public void setParam2(String param2) {
		this.param2 = param2;
	}
	
}

Test.java
@Test
public void test() {
	//     context     
	MyEvent event = new MyEvent("source","param1","param2");
	context.publishEvent(event);
}

출력 결과
cn.edu.his.pay.listen.MyListenparam1
cn.edu.his.pay.listen.MyListenparam2
cn.edu.his.pay.listen.MyListensource
cn.edu.his.pay.listen.MyListen2param1
cn.edu.his.pay.listen.MyListen2param2
cn.edu.his.pay.listen.MyListen2source

위 테스트 코드 결 과 를 보면 마 이 이벤트 (테마) 를 사용자 정의 하여 컨 텍스트 에 게시 할 수 있 습 니 다. 이 럴 때 모니터 구독 (관찰자) 만 있 으 면 테마 정 보 를 받 아 자신의 업 무 를 완성 할 수 있 습 니 다.
2.  그리고 스프링 이 어떻게 구독 을 했 는 지 생각해 볼 필요 가 있 습 니 다.지금 우 리 는 Spring 소스 코드 를 결합 하여 분석 할 것 이다.
스프링 이 초기 화 할 때 뭐 했 는 지 볼 까요?입구: AbstractApplication Context \ # registerListeners.
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 lisName : listenerBeanNames) {
		getApplicationEventMulticaster().addApplicationListenerBean(lisName);
	}
}

위의 코드 를 통 해 알 수 있 듯 이 용기 가 초기 화 될 때 모든 애플 리 케 이 션 Listener 인터페이스 클래스 beanName 을 애플 리 케 이 션 Listener Beans 집합 에 먼저 등록 합 니 다. 모든 모니터 를 등록 한 셈 입 니 다.
그 다음 에 테 마 를 발표 할 때 context. publishEvent (event) 는 무엇 을 했 는 지 다시 한 번 살 펴 보 겠 습 니 다.입구: AbstractApplicationContext \ # publishEvent (ApplicationEvent event).
@Override
public void publishEvent(ApplicationEvent event) {
	Assert.notNull(event, "Event must not be null");
	if (logger.isTraceEnabled()) {
		logger.trace("Publishing event in " + getDisplayName() + ": " + event);
	}
	getApplicationEventMulticaster().multicastEvent(event);
	if (this.parent != null) {
		this.parent.publishEvent(event);
	}
}
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public void multicastEvent(final ApplicationEvent event) {
	for (final ApplicationListener listener : getApplicationListeners(event)) {
		Executor executor = getTaskExecutor();
		if (executor != null) {
			executor.execute(new Runnable() {
				@Override
				public void run() {
					listener.onApplicationEvent(event);
				}
			});
		}
		else {
			listener.onApplicationEvent(event);
		}
	}
}

위의 코드 를 통 해 알 수 있 듯 이 이벤트 (테마) 를 발표 할 때 getapplicationListeners (이벤트) 를 통 해 모든 모니터 (관찰자) 를 가 져 왔 습 니 다. 사실은 이전 Spring 시작 때 applicationListener Beans 집합 에 등록 하면 됩 니 다.모든 감청 기 (관찰자) 를 꺼 내 서 감청 기 (관찰자) onApplicationEvent 방법 을 반복 해서 호출 합 니 다.

좋은 웹페이지 즐겨찾기