Spring ApplicationEvent

Spring Application Event


Spring ApplicationContext클래스는 Evnet처리 기능을 지원한다. Spring이 관리하는 Bean에서 ApplicationEventListener<SomeEvent> Interface를 구현해 주면 ApplicationContext.publishEvent(new SomeEvent()); 와 같이 메소드 호출 한 번으로 등록된 모든 리스너에게 이벤트를 전달하여 준다. 리스너는 이때 각자 Event에 맞는 처리를 진행하면 된다.


구현방법

  • 이벤트 발신자 : 실제 이벤트 발신은 ApplicationContext.publishEvent()에서 수행하기 때문에 Bean은 ApplicationContext객체에 접근 할 수 있으면 된다. 
    • 웹어플리케이션인 : 대부분의 클래스에서 기본으로 ApplicationContext에 기본 접근이 가능하다.
    • 단독 실행형 어플리케이션 : ApplicationContextAware interface를 구현하여 ApplicationContext에 접근한다.

  • 이벤트 수신자 : 이벤트 수신자는 ApplicationListener<T> 인터페이스를 구현하면 된다.
    • Implements ApplicationListener Interface and Override onApplicationEvent Method
    • ApplicationListener<T> 에서 T는 이벤트를 처리할 클래스 이벤트 Type을 의미 한다.

  • 이벤트 : 사용자가 직접 정의하는 Event는 org.springframework.context.ApplicationEvent를 상속받아 구현한다.
    • 이벤트 생성 시 추가 정보를 전달 한다면 ApplicationEvent구현체에서 대상 객체를 정의하고 setter와 getter를 생성해주자.

 




Example

 

[MessageEvent Class] : 이벤트

ApplicationEvent를 상속받으면 Spring에서 Event클래스로 처리.

ApplicationEvent는 java.util.EventObejct를 상속받으며 Timestamp를 찍어주는 것 말고는 별다른 기능은 없다.

대신 super(source)는 반드시 호출하여야 한다. 그래야 이벤트 발신자를 수신자 측에서 인식 하는게 가능하다.

Event는 기능보다는 Type이 중요하다. Type으로 이벤트를 구분하기 때문에 어떤 Class의 이벤트인지가 더욱 중요하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.javaking.event;
 
import org.springframework.context.ApplicationEvent;
 
public class MessageEvent extends ApplicationEvent {
    
    private String msg;
    
    public MessageEvent(Object source, String msg) {
        super(source);
        this.msg = msg;
    }
    
    public String getMessage(){
        return msg;
    }
 
}
cs

 


[SimplePublishBean Class] : 이벤트 발신자

Main에서 직접 ApplicationContext에서 이벤트를 발생해도 되지만, 현실적으로 그렇게 쓰이는 경우는 거의 없기 때문에 정의된 Bean에서 이벤트를 발생시키는 패턴으로 구현 하였다. 

ApplicationContext에 접근하기 위해서 ApplicationContextAware interface를 구현하였으며, setApplicationContext는 이를 위한 처리일 뿐이다.

실제 이벤트 발행은 publish()에서 처리 하고 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.javaking.bean;
 
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import com.javaking.event.MessageEvent;
 
public class SimplePublishBean implements ApplicationContextAware{
 
    /**
     * ApplicationContext
     */
    private ApplicationContext appCtx;
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.appCtx = applicationContext;
    }
    
    public void publish(String msg){
        appCtx.publishEvent(new MessageEvent(this, msg));
    }
    
}
cs


[SimpleListenerBean Class] : 이벤트 수신자
ApplicationListener<T>를 구현하여 onApplicationEvent() Method를 Override 하고 있다.
실제 이벤트 발생시 onApplicationEvnet 메소드가 수행되니 처리 내용을 작성.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
package com.javaking.bean;
 
import org.springframework.context.ApplicationListener;
 
import com.javaking.event.MessageEvent;
 
public class SimpleListenerBean implements ApplicationListener<MessageEvent>{
    @Override
    public void onApplicationEvent(MessageEvent event) {
        System.out.println("이벤트를 통해 전달된 내용 : " + event.getMessage());
        System.out.println("이벤트가 발생 된 객체 Class : " + event.getSource().getClass());
        
    }
}
cs


[app-context.xml]
일반적인 bean정의 외에는 작업할 게 없다.
이미 정의된 bean에 이벤트를 처리하는 경우는 위에 에제들 처럼 Event관련 interface만 구현하여 주면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:c="http://www.springframework.org/schema/c"    xmlns:context="http://www.springframework.org/schema/context"
       xmlns:p="http://www.springframework.org/schema/p"    xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
    
    <!-- 이벤트 발신자 applicationContext에 접근하여 event 발송 -->
    <bean name="messagePublisher" class="com.javaking.bean.SimplePublishBean"/>
    
    <!-- 이벤트 수신자 ApplicationListener의 구현체는 이벤트를 수신-->
    <bean name="messageListener"  class="com.javaking.bean.SimpleListenerBean"/>
    
</beans>
cs


[MainApplication Class]
예제를 정리하며 아래 과정을 거친다.
SimplePublishBean.publish() -> ApplicationContext.publishEvent() -> (Spring 이벤트 수신자 호출) -> SimpleListenerBean.onApplicationEvent()
흐름만 잘 이해한다면 구현도 쉽고 이해하기도 쉬운 패턴이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import org.springframework.context.support.GenericXmlApplicationContext;
 
import com.javaking.bean.SimpleListenerBean;
import com.javaking.bean.SimplePublishBean;
 
public class MainApplication {
 
    public static void main(String[] args) {
        // ApplicationContext 부트스트랩
        GenericXmlApplicationContext appCtx = new GenericXmlApplicationContext();
        appCtx.load("classpath:META-INF/spring/app-context.xml");
        appCtx.registerShutdownHook();
        appCtx.refresh();
        
        SimplePublishBean  eventPublisher = (SimplePublishBean) appCtx.getBean("messagePublisher");
        
        eventPublisher.publish("이벤트 메시지 발송!");
                
    }
}
 
cs


수행결과

이벤트를 통해 전달된 내용 : 이벤트 메시지 발송!!!얍!!!

이벤트가 발생 된 객체 Class : class com.javaking.bean.SimplePublishBean



다운로드

SpringApplicationEvent.zip



함께보기

ApplicationContextAware Interface 링크

'프로그래밍 > Spring FWK' 카테고리의 다른 글

Spring Resource  (1) 2016.01.10
Spring MessageSource 국제화  (0) 2016.01.08
Spring CustomPropertyEditor  (2) 2016.01.05
Spring PropertyEditor  (0) 2016.01.05
Spring facoty-bean, factory-method  (0) 2015.12.30
Spring FactoryBean Interface  (0) 2015.12.29
Spring ApplicationContextAware Interface  (0) 2015.12.28
Spring BeanNameAware Interface  (1) 2015.12.28

이 글을 공유하기

댓글

Email by JB FACTORY