Table of Contents
ApplicationEventPublisher 를 이용한 이벤트 처리
이벤트 수신을 다수의 클래스에서 받을 수 있으므로,
이벤트 처리를 한곳에 모으지 않아도 되서 좋다.
이벤트 수신은 기본적으로 동기식으로 작동한다.
비동기로 처리하기 위해서는 @Async
를 붙여주어야 한다.
Event 생성
@Getter
@RequiredArgsConstructor
public class StockIpgoEvent {
private final Object data;
}
Listener 생성
@Component
public class StockIpgoListener {
@Autowired
private ApplicationEventPublisher eventPublisher;
@PostLoad
void postLoad(Object o) {
if (o instanceof IpgoMaster) {
System.out.println("11111 PostLoad" + ((IpgoMaster) o).getIpgoDate());
eventPublisher.publishEvent(new StockIpgoEvent("after select"));
}
}
@PostUpdate
void postUpdate(Object o) {
if (o instanceof IpgoMaster) {
System.out.println("11111 PostUpdate" + ((IpgoMaster) o).getIpgoDate());
eventPublisher.publishEvent(new StockIpgoEvent("after update"));
}
}
}
Entity 에 Listener 추가
Listener 또한 여러개 추가할 수 있다.
@Entity
@EntityListeners(value = {StockIpgoListener.class})
public class IpgoMaster {
// ......
}
EventHandler 추가
JPA CRUD 가 필요한 경우 반드시 @Async
가 되어야 한다.
모든 동작은 동기로 이루어진다.
즉, @PostUpdate
에서 호출하는 @EventListener
가 동기로 작동하게 되면,
JPA CRUD 가 호출될 때 업데이트해야할 데이타가 남아 있는 것으로 인식되고,
@PostUpdate
가 호출되고 이 상태가 무한루프로 반복된다.
따라서 JPA CRUD 는 비동기로 트렌젝션을 벗어나서 이루어져야 한다.
@Component
public class StockIpgoEventHandler {
@EventListener
public void onStockIpgoEventBefore(StockIpgoEvent event) {
// @PostLoad 이벤트만 수신하도록 설정 필요
// after select
// JPA Query 가능
}
@EventListener
public void onStockIpgoEventAfter(StockIpgoEvent event) {
// @PostUpdate 이벤트만 수신하도록 설정 필요
// 동기 작동중
// after update
// JPA Query 불가능(트렌젝션 진행중)
// @Transient 수정 가능
}
@Async
@EventListener
public void onStockIpgoEventAsync(StockIpgoEvent event) {
// @PostUpdate 이벤트만 수신하도록 설정 필요
// 비동기 작동중
// after update
// JPA Query 가능(트렌젝션 벗어남)
// @Transient 수정 가능
}
}