개발강의정리/Spring

[스프링 프레임워크 핵심 기술] 2-8. IoC컨테이너-ApplicationEventPublisher

nineDeveloper 2019. 10. 6.
728x90

스프링 프레임워크 핵심 기술

포스팅 참조 정보

GitHub

공부한 내용은 GitHub에 공부용 Organizations에 정리 하고 있습니다

해당 포스팅에 대한 내용의 GitHub 주소

실습 내용이나 자세한 소스코드는 GitHub에 있습니다
포스팅 내용은 간략하게 추린 핵심 내용만 포스팅되어 있습니다

https://github.com/freespringlecture/spring-core-tech/tree/chap02-08-applicationeventpublisher

 

freespringlecture/spring-core-tech

백기선님의 스프링 프레임워크 핵심 기술 강의 내용 정리. Contribute to freespringlecture/spring-core-tech development by creating an account on GitHub.

github.com

해당 포스팅 참고 인프런 강의

https://www.inflearn.com/course/spring-framework_core/dashboard

 

스프링 프레임워크 핵심 기술 - 인프런

이번 강좌는 스프링 부트를 사용하며 스프링 핵심 기술을 학습합니다 따라서 스프링 부트 기반의 프로젝트를 사용하고 있는 개발자 또는 학생에게 유용한 스프링 강좌입니다. 초급 웹 개발 Java Spring 온라인 강의

www.inflearn.com

실습 환경

  • Java Version: Java 11
  • SpringBoot Version: 2.1.2.RELEASE

2-8. IoC 컨테이너 8부: ApplicationEventPublisher

이벤트 프로그래밍에 필요한 인터페이스 제공 ​옵저버 패턴​ 구현체

ApplicationContext extends ​ApplicationEventPublisher
publishEvent(ApplicationEvent event)

이벤트 만들기

  • ApplicationEvent 상송
  • 스프링 4.2 부터는 이 클래스를 상속받지 않아도 이벤트로 사용할 수 있다.

이벤트 발생 시키는 방법

  • ApplicationEventPublisher.publishEvent();

이벤트 처리하는 방법

  • ApplicationListener<이벤트> 구현한 클래스 만들어서 빈으로 등록하기.
  • 스프링 4.2 부터는 ​@EventListener​를 사용해서 빈의 메소드에 사용할 수 있다.
  • 기본적으로는 synchronized.
  • 순서를 정하고 싶다면 @Order와 함께 사용.
  • 비동기적으로 실행하고 싶다면 @Async와 함께 사용.

스프링이 제공하는 기본 이벤트

  • ContextRefreshedEvent: ApplicationContext를 초기화 했더나 리프래시 했을 때 발생
  • ContextStartedEvent: ApplicationContext를 start()하여 라이프사이클 빈들이 시작
    • 신호를 받은 시점에 발생
  • ContextStoppedEvent: ApplicationContext를 stop()하여 라이프사이클 빈들이 정지
    • 신호를 받은 시점에 발생.
  • ContextClosedEvent: ApplicationContext를 close()하여 싱글톤 빈 소멸되는 시점에 발생
  • RequestHandledEvent: HTTP 요청을 처리했을 때 발생

스프링 4.2 부터는 ApplicationEvent 클래스를 상속받지 않아도 이벤트로 사용할 수 있다

4.2이전 상속을 받아 Event를 정의하는 로직

public class MyEvent extends ApplicationEvent {

    private int data;
    /**
     * Create a new ContextStartedEvent.
     *
     * @param source the {@code ApplicationContext} that the event is raised for
     *               (must not be {@code null})
     */
    public MyEvent(Object source) {
        super(source);
    }

    public MyEvent(Object source, int data) {
        super(source);
        this.data = data;
    }

    public int getData() {
        return data;
    }

}

4.2 이후 Event 정의 로직

스프링이 추구하는 스프링 프레임웍 코드가 전혀 들어가지 않은 POJO 기반의 프로그래밍의 비침투성 로직

  • 더 편하고 더 코드를 유지보수하기 쉬워짐

  • 이벤트는 빈이 아님

    public class MyEvent {
    
      private int data;
      private Object source;
    
      public MyEvent(Object source, int data) {
          this.source = source;
          this.data = data;
      }
    
      public Object getSource() {
          return source;
      }
    
      public int getData() {
          return data;
      }
    

}



### ApplicationEventPublisher
> Event를 발생시키는 로직
```java
@Component
public class AppRunner implements ApplicationRunner {

    @Autowired
    ApplicationEventPublisher publisherEvent;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        publisherEvent.publishEvent(new MyEvent(this, 100));
    }
}

ApplicationListener

Event를 받아서 처리하는 Handler 구현

4.2 이전 로직

@Component
public class MyEventHandler implements ApplicationListener<MyEvent> {

    @Override
    public void onApplicationEvent(MyEvent event) {
        System.out.println("이벤트 받았다. 데이터는 " + event.getData());
    }
}

4.2 이후 로직

@Component
public class MyEventHandler {

    @EventListener
    public void handle(MyEvent event) {
        System.out.println("이벤트 받았다. 데이터는 " + event.getData());
    }
}

Order

Event 실행 순서 지정
@Order(Ordered.HIGHEST_PRECEDENCE) 라고 설정하면 가장 먼저 실행됨
@Order(Ordered.HIGHEST_PRECEDENCE + 2) 라고 설정하면 조금 더 늦게 실행됨

@Component
public class MyEventHandler {

    @EventListener
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public void handle(MyEvent event) {
        System.out.println(Thread.currentThread().toString());
        System.out.println("이벤트 받았다. 데이터는 " + event.getData());
    }
}

@EnableAsync

비동기 설정 @EnableAsync 를 설정하면 메인 Thread 가 아닌 별도의 Thread를 생성하여 수행

@SpringBootApplication
@EnableAsync
public class Ioccontainer8Application {

    public static void main(String[] args) {
        SpringApplication.run(Ioccontainer8Application.class, args);
    }

}

Handler 로직에 @Async 설정

@Component
public class MyEventHandler {

    @EventListener
//    @Order(Ordered.HIGHEST_PRECEDENCE)
    @Async
    public void handle(MyEvent event) {
        System.out.println(Thread.currentThread().toString());
        System.out.println("이벤트 받았다. 데이터는 " + event.getData());
    }
}

LifeCycle Event

  • ContextRefreshedEvent: ApplicationContext를 초기화 했거나 리프래시 했을 때 발생.
  • ContextStartedEvent: ApplicationContext를 start()하여 라이프사이클 빈 들이 시작신호를 받은시점에 발생.
  • ContextStoppedEvent: ApplicationContext를 stop()하여 라이프사이클 빈 들이 정지신호를 받은시점에 발생.
  • ContextClosedEvent: ApplicationContext를 close()하여 싱글톤 빈 소멸 되는시점에 발생.
  • RequestHandledEvent: HTTP 요청을 처리 했을 때 발생.
728x90

댓글

💲 추천 글