도메인의 변화. 즉, 도메인의 entity의 변화를 이벤트로 발생시키는 것.
그 이벤트를 리스닝하는 이벤트 리스너가 domain entity 클래스의 변화를 감지하고, 어떠한 이벤트 기반의 프로그래밍을 할 수 있게 하는 것.
Post라는 글이 draft 상태로 기본적으로 저장된다고 가정하고, 사용자가 발행버튼을 눌렀을 때만 publishing된다고 가정한다. 그러한 publishing이 일어났을 때, 별도의 이벤트 기반의 프로그래밍을 해야한다고 하자
'posting이 publish 되었다' 라는 이벤트를 만들어서 관리할 수 있다.
PostPublishedEvent를 만들어서 ApplicationEvent를 상속받는다.
Post 정보가 필요하므로 Post를 선언해준다.
이벤트를 발생시키는 곳이 Post라고 가정한다.
이벤트를 받는 리스너 쪽에서 어떤 Post에 대한 이벤트였는지 참조할 수 있도록 getter를 만들어준다.
이벤트 리스너도 하나 만들어준다.
ApplicationListener를 상속받아 리스너가 받을 이벤트 타입을 알려준다.
그 후, 이벤트가 발생했을 때 해야할 일을 구현해준다.
스프링 데이터는 repository를 save 할 때, 이벤트 자동 퍼블리싱 기능을 제공해준다.
어떤 Entity에 쌓여있던 이벤트들을 save 하는 순간 다 보내준다.
@DomainEvents 라는 애노테이션이 붙어있는 메서드에서 이벤트를 모아놓는다.
@AfterDomainEventPublication은 모아놨던 이벤트를 지우는 기능을 한다.
AbstractAggregateRoot를 상속받으면 안에 이미 @DomainEvents, @AfterDomainEventPublication가 구현되어있다.
따라서 이벤트를 보내는 방법은 save를 할 때, 이벤트를 만들어서 넣어주기만 하면 된다.
예를 들어 publish라는 도메인 메서드(퍼블리싱을 하는 일)를 만든다.
퍼블리싱을 할 때 여기서 이벤트를 만들어주면 된다.
registerEvent()라는 메서드가 기본적으로 제공된다.(AbstractAggregateRoot를 상속받았기 때문)
이렇게 해주면, 이벤트 리스너가 빈으로 등록되어 있으면, save 할 때 자동으로 AbstractAggregateRoot 안의 모아져있는 이벤트를 발생시킨다.
이벤트리스너를 애노테이션을 이용해서 만들수도 있다.
위와 같은 코드를 아래처럼 바꿀 수 있다.
두 방법 모두 Bean으로 등록되어있어야 한다.
재밌게 잘 읽었습니다! ;)