프로젝트 내에서 Game기능을 구현하였다. 이를 테스트 하던 중 두명의 사용자가 로그인 후 커플을 맺으면 세션 내에
coupleId
가 들어가지 않는 현상을 발견하였다. 이를 팀원들 중 한분이 해결해주셨는데 Security는 아직 잘 모르겠고 EventListener를 사용하여 해결하였길래 이 참에 EventListener를 공부했다.
@Transactional
public void updateMemberProfile(List<MultipartFile> profileImages, MemberProfileEditServiceRequest serviceRequest, Long memberId) {
Member findMember = validateMemberId(memberId);
String oldProfileImageUrl = findMember.getImageUrl();
String profileImageUrl = updateProfileImage(profileImages, oldProfileImageUrl);
updateMemberProfile(profileImageUrl, serviceRequest, findMember);
eventPublisher.publishEvent(new MemberupdatedEvent(findMember));
}
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void updateSessionAfterMemberUpdatedEvent(MemberupdatedEvent event) {
Member member = event.member();
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && authentication.isAuthenticated()) {
MyOAuth2Member principal = (MyOAuth2Member) authentication.getPrincipal();
OAuth2AuthenticationToken oAuth2AuthenticationToken =
new OAuth2AuthenticationToken(
principal.update(
member.getCoupleId(),
member.getNickname(),
member.getImageUrl()
),
authentication.getAuthorities(),
principal.getNameAttributeKey()
);
SecurityContextHolder.getContext().setAuthentication(oAuth2AuthenticationToken);
SecurityContext securityContext = SecurityContextHolder.getContext();
httpSession.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, securityContext);
}
}
이벤트를 발행하는데 사용되는 인터페이스이다.
이벤트는 어플리케이션의 상태 변화나 특정 작업이 발생했음을 나타내는 메시지이다.
Spring에서 제공하는 package org.springframework.context;
인터페이스이기 때문에 생성자 주입이나 @Autowired 등을 통하여 쉽게 Bean을 주입 받을 수 있다.
동기, 비동기 공부 해야함.
여기서 든 나의 의문점) 이벤트 리스너는 여러개가 등록이 되어있을 것이다. 따라서 이벤트를 발행하면 어떤 이벤트 리스너가 발행된 이벤트를 듣고 처리할 수 있는가?
-> 이벤트 클래스 타입에 의존한다.
eventPublisher.publishEvent(new MemberupdatedEvent(findMember));
위 이벤트를 발행하는 코드의 클래스 타입은 MemberupdatedEvent
이다.
따라서
public void updateSessionAfterMemberUpdatedEvent(MemberupdatedEvent event)
가 이벤트를 듣고 처리할 수 있다.
phase
속성을 통해 트랜잭션의 단계에 따라 실행한다.AFTER_COMMIT
AFTER_ROLLBACK
AFTER_COMPLETION
BEFORE_COMMIT