ApplicationEventPublisher 를 이용한 이벤트 처리

By | 2022년 11월 18일
Table of Content

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 수정 가능
    }
}

답글 남기기