본문 바로가기
Back-End/Spring Boot

Spring Event Publisher/Listener

by 코젼 2024. 8. 9.
728x90
반응형
// 이벤트 객체
public class PaymentSuccessEvent {
    private final String orderKey;
    private final String paymentKey;

    public PaymentSuccessEvent(String orderKey, String paymentKey) {
        this.orderKey = orderKey;
        this.paymentKey = paymentKey;
    }

    public String getOrderKey() {
        return orderKey;
    }

    public String getPaymentKey() {
        return paymentKey;
    }
}
// 이벤트 발행서비스
@Component
public class PaymentEventPublisher {
    private final ApplicationEventPublisher applicationEventPublisher;

    public PaymentEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }

    public void success(PaymentSuccessEvent event) {
        applicationEventPublisher.publishEvent(event);
    }
}
// 이벤트 구독서비스
@Component
public class PaymentEventListener {
    private final DataPlatformSendService sendService;

    public PaymentEventListener(DataPlatformSendService sendService) {
        this.sendService = sendService;
    }
		// 비동기로 이벤트 발행주체의 트랜잭션이 커밋된 후에 수행한다.
    @Async
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void paymentSuccessHandler(PaymentSuccessEvent event) {
        // (4) 주문 정보 전달
        PaymentSuccessPayload payload = new PaymentSuccessPayload(event);
        sendService.send(payload);
    }
}
// 비즈니스 로직
@Service
public class PaymentService {
    private final RequestValidator requestValidator;
    private final UserService userService;
    private final OrderService orderService;
    private final PaymentRepository paymentRepository;
    private final PaymentEventPublisher eventPublisher;

    public PaymentService(RequestValidator requestValidator, UserService userService, OrderService orderService, PaymentRepository paymentRepository, PaymentEventPublisher eventPublisher) {
        this.requestValidator = requestValidator;
        this.userService = userService;
        this.orderService = orderService;
        this.paymentRepository = paymentRepository;
        this.eventPublisher = eventPublisher;
    }

    @Transactional
    public void pay(PaymentRequest request) {
        // (1) 결제 요청 검증
        requestValidator.validate(request);
        // (2) 유저 포인트 차감
        User user = userService.getWithLock(request.getUserId());
        orderService.check(request.getOrderKey(), user.getId());
        user.usePoint(request.getAmount());
        // (3) 결제 정보 저장
        Payment payment = paymentRepository.save(new Payment(request));
        // 결제 성공 이벤트 발행
        eventPublisher.success(new PaymentSuccessEvent(payment.getOrderKey(), payment.getKey()));
    }
}
728x90
반응형

댓글