[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를 등록할 수 있습니다.
'Spring Data > Spring Data JPA' 카테고리의 다른 글
[Spring JPA #19] 스프링 데이터 HATEOAS (0) | 2021.03.26 |
---|---|
[Spring JPA #18] 스프링 데이터 Pageable과 Sort (0) | 2021.03.26 |
[Spring JPA #17] 스프링 데이터 DomainClassConverter (0) | 2021.03.26 |
[Spring JPA #16] 스프링 데이터 QueryDsl (0) | 2021.03.25 |
[Spring JPA #14] 스프링 데이터 커스텀 리포지터리 만들기 (0) | 2021.03.25 |
[Spring JPA #13] 스프링 데이터 쿼리 만들기 (0) | 2021.03.25 |
[Spring JPA #12] 스프링 데이터 Null 체크 (0) | 2021.03.25 |
[Spring JPA #11] 스프링 데이터 리포지터리 인터페이스 정의하기(Spring Repository Interface) (0) | 2021.03.25 |