[Spring JPA #15] 스프링 데이터 도메인 이벤트

스프링 데이터 도메인 이벤트


  • 스프링 프레임워크에서는 주로 IoC 컨테이너에 접근하기 위한 ApplicationContext 인터페이스를 제공합니다. 
  • 이 ApplicationContext는 ApplicationEventPublisher를 상속받기 때문에 사용자가 정의한 이벤트나 스프링 프레임워크에서 미리 정의한 이벤트를 publish하는 기능도 제공하고 있습니다.
  • 사용자가 정의한 이벤트를 수신하기 위해서는 리스너를 정의하여 해당 클래스에 맞는 이벤트를 받아 처리하면 됩니다.


| 스프링 데이터 도메인 이벤트 예제


프로젝트 구조

├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │   └── tutorial
│   │   │   └── springdatarepository
│   │   │   ├── AppRunner.java
│   │   │   ├── Post.java
│   │   │   ├── PostListener.java
│   │   │   ├── PostPublishedEvent.java
│   │   │   └── SpringDataRepositoryApplication.java
│   │   └── resources
│   │   └── application.properties

의존성 관리

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

소스 코드

@SpringBootApplication
public class SpringEventApplication {

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

}
@Entity
@Data
public class Post {

@Id
@GeneratedValue
private Long id;

private String title;

@Lob
private String content;

@Temporal(TemporalType.TIMESTAMP)
private Date created;
}
public class PostPublishedEvent extends ApplicationEvent {

private final Post post;

public PostPublishedEvent(Object source) {
super(source);
this.post = (Post) source;
}

public Post getPost() {
return post;
}
}
  • ApplicationEvent를 상속하여 Custom Event를 작성하였습니다. Post 객체를 받는 생성자와 저장된 Post 객체의 Getter만을 작성하였습니다.
@Component
public class PostListener implements ApplicationListener<PostPublishedEvent> {

@Override
public void onApplicationEvent(PostPublishedEvent event) {
System.out.println("------------------------");
System.out.println(event.getPost().getTitle() + " is published");
System.out.println("------------------------");
}
}
  • PostListener 는 PostPublishedEvent가 publish될 때 그 이벤트를 수신하여 출력하는 Event Listener입니다.


@Component
public class AppRunner implements ApplicationRunner {

@Autowired
ApplicationContext applicationContext;

@Override
public void run(ApplicationArguments args) throws Exception {
Post post = new Post();
post.setTitle("POST EVENT");
PostPublishedEvent event = new PostPublishedEvent(post);

applicationContext.publishEvent(event);
}
}
  • ApplicationContext의 구현체는 이벤트를 publish할 수 있는 기능을 제공합니다. 따라서 PostPublishedEvent를 ApplicationContext 인터페이스를 통하여 publish하면 그 이벤트가 위에서 작성한 PostListener에게 수신되는 것을 알 수 있습니다.


결과화면

------------------------
POST EVENT is published
------------------------


| 도메인 이벤트를 구현하기 위한 다양한 예제들


위 AppRunner에서 

Post post = new Post();
post.setTitle("POST EVENT");
PostPublishedEvent event = new PostPublishedEvent(post);

applicationContext.publishEvent(event);

PostPublishedEvent를 등록하고 publish하기 위한 구문을 다음과 같이 Post에 AbstractAggregateRoot 클래스를 확장하여 이 클래스에서 상속받은 registerEvent 메서드를 통해 이벤트를 등록하게 되면 위 구문을 더 간략하게 만들 수 있습니다.


소스 코드

@Entity
@Data
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 Post publish() {
this.registerEvent(new PostPublishedEvent(this));
return this;
}
}
  • AbstractAggregateRoot 클래스는 도메인 이벤트를 등록하고 publish 하는 기능을 제공합니다. 
  • 위 코드처럼 이벤트를 등록시키면 Repository 인터페이스에서 save 메서드를 호출할 시, AbstractAggregateRoot 안의 domainEvents을 통해 모아놓은 이벤트를 발생시킵니다.


@Component
public class PostListener {

@EventListener
public void onApplicationEvent(PostPublishedEvent event) {
System.out.println("------------------------");
System.out.println(event.getPost().getTitle() + " is published");
System.out.println("------------------------");
}
}
  • ApplicationListener를 상속받지 않고도 @EventListener 어노테이션을 통해 Event Listener를 등록할 수 있습니다.


https://www.inflearn.com/course/스프링-데이터-jpa


이 글을 공유하기

댓글(0)

Designed by JB FACTORY