도메인 이벤트
- Entity 의 변화를 이벤트로 간주
- ApplicationContext 의 EventPublisher 의 기능을 이용하여 EventListener 로 받아줌
- 이벤트 기반 프로그래밍 에 사용
이벤트 작성 방법.(Spring Frame Work ApplicationContext 의 EventPublisher 에 기술 되어 있음)
- ApplicationEvent 구현클래스 작성
public class PostPublishedEvent extends ApplicationEvent {
private final Post post;
public PostPublishedEvent(Object source) {
super(source);
this.post = (Post)source;
}
public Post getPost() {
return post;
}
}
이벤트 리스너 작성.(Spring Frame Work ApplicationContext 의 EventPublisher 에 기술되어 있음)
- ApplicationListener<T> 구현 클래스 작성
- @EventListener 메서드를 가진 클래스 작성
@Component
public class PostListener implements ApplicationListener<PostPublishedEvent> {
@Override
public void onApplicationEvent(PostPublishedEvent postPublishedEvent) {
System.out.println("=======================");
System.out.println(postPublishedEvent.getPost()+ " is published!");
System.out.println("=======================");
}
}
@Component
public class AnnotationPostListener {
@EventListener
public void onApplicationEvent(PostPublishedEvent event){
System.out.println("=======================");
System.out.println(event.getPost()+ " is published!");
System.out.println("=======================");
}
}
이벤트 퍼블리케이션(Spring Data , 이외는 ApplicationContext 의 EventPublisher 에 기술되어 있음)
- Spring Data 의 경우 Entity 클래스에 AbstractAggregateRoot<E> 상속 후 registerEvent() 를 사용하는 메서드 기술
- 이외는 ApplicationContext에서 EventPublisher 를 가져와 이벤트 퍼블리싱
@Entity
public class Post extends AbstractAggregateRoot<Post> {
@Id
@GeneratedValue
private Long id;
private String title;
@Lob
private String content;
@Temporal(TemporalType.TIMESTAMP)
private Date created;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
//
public Post publish() {
this.registerEvent(new PostPublishedEvent(this));
return this;
}
}
슬라이싱 테스트 진행
@RunWith(SpringRunner.class)
@DataJpaTest
@Import(PostListener.class)
public class DomainEventTest {
@Autowired
private PostRepository postRepository;
@Autowired
private ApplicationContext applicationContext;
// @Test
public void testEventPublisher(){
Post post = new Post();
post.setTitle("Event");
PostPublishedEvent publishedEvent = new PostPublishedEvent(post);
applicationContext.publishEvent(publishedEvent);
}
@Test
public void testSpringDataEventPublication(){
Post post = new Post();
post.setTitle("Domain Event");
postRepository.save(post.publish());
}
}
=======================
me.soomin.jpa.post.Post@79ecc507 is published!
=======================
AbstractAggregateRoot<E> 와 @DomainEvent, @AfterDomainEventPublication
Spring Data 는 save 될때 이벤트를 자동으로 퍼블리싱해준다.
- Entity 에 쌓여있던 Event 를 save() 하는 순간 전부 퍼블리싱 해준다.
- 이벤트를 모아 저장하는 메서드가 @DomainEvent 를 가진 메서드이다.
- 메모리 누수 방지를 위해 컬렉션을 비워주는 메서드가 @AfterDomainEventPublication 을 가진 메서드이다.
public class AbstractAggregateRoot<A extends AbstractAggregateRoot<A>> {
@Transient
private final transient List<Object> domainEvents = new ArrayList();
public AbstractAggregateRoot() {
}
protected <T> T registerEvent(T event) {
Assert.notNull(event, "Domain event must not be null!");
this.domainEvents.add(event);
return event;
}
@AfterDomainEventPublication
protected void clearDomainEvents() {
this.domainEvents.clear();
}
@DomainEvents
protected Collection<Object> domainEvents() {
return Collections.unmodifiableList(this.domainEvents);
}
...
'springframework > Spring Data JPA' 카테고리의 다른 글
Spring Datat Common : QueryDSL 변경사항 (0) | 2020.11.17 |
---|---|
Spring Data Common : QueryDSL (0) | 2020.11.17 |
Spring Data Common : 공통 리포지토리 커스터마이징 (0) | 2020.11.16 |
Spring Data Common : 커스텀 리포지토리 생성 (0) | 2020.11.16 |
Spring Data Common : Async Query Method (0) | 2020.11.16 |