✍️ 서론
이벤트의 콜백 메서드를 인터페이스의 추상 메서드로 정의하고, 이벤트에 관심 있는 클래스는 콜백 인터페이스를 구현함으로써 간단한 Listener를 만들 수 있다. 예제 코드로 이해해 보자.
여기 Member의 가입 로직이 포함된 MemberService가 있고,
@Service
public class MemberServiceImpl implements MemberService {
@Autowired
private MemberDao memberDao;
@Override
public void join(int memberId, String name) {
Member exist = memberDao.get(memberId);
if (exist != null)
throw new RuntimeException("Exist id");
memberDao.insert(new Member(memberId, name));
}
}
모든 Member에게 알림을 전송하는 NotificationService가 있다.
@Service
public class NotificationServiceImpl implements NotificationService {
@Override
public void notify(int memberId, String name) {
// 모든 멤버에게 알림이라고 가정하자
System.out.println("NEW MEMBER : " + memberId + " " + name);
}
}
🍊 Interface 기반의 Listener
만약 MemberService의 join이 정상적으로 이루어졌을 때, 새로 가입한 멤버를 모든 멤버에게 알리고 싶다면 콜백 메서드를 활용할 수 있다. 앞서 언급했던 것처럼 콜백 메서드의 형태는 인터페이스의 추상 메서드로 정의할 수 있다.
아래는 join 이벤트의 콜백 메서드를 추상화한 인터페이스
public interface MemberJoinListener {
void onMemberJoin(int memberId, String name);
}
NotificationService를 MemberJoinListener의 구현체로 만들어 콜백 메서드를 정의하고,
@Service
public class NotificationServiceImpl implements NotificationService, MemberJoinListener {
@Override
public void notify(int memberId, String name) {
System.out.println("NEW MEMBER : " + memberId + " " + name);
}
@Override
public void onMemberJoin(int memberId, String name) {
notify(memberId, name);
}
}
MemberService에선 MemberJoinListener의 구현체를 찾아서
@Autowired(required = false)
private List<MemberJoinListener> listeners;
아래와 같이 join의 마지막에 콜백 메서드를 호출하면 간단한 Listener를 구현할 수 있다.
@Service
public class MemberServiceImpl implements MemberService {
@Autowired(required = false)
private List<MemberJoinListener> listeners;
@Autowired
private MemberDao memberDao;
@Override
public void join(int memberId, String name) {
Member exist = memberDao.get(memberId);
if (exist != null)
throw new RuntimeException("Exist id");
memberDao.insert(new Member(memberId, name));
// 리스너 호출
if (listeners != null)
listeners.forEach(l -> l.onMemberJoin(memberId, name));
}
}
🤔 언제 사용해야 할까?
사실 위 예제는 리스너를 사용하지 않고 join에서 바로 notify를 호출해도 된다.
@Override
public void join(int memberId, String name) {
Member exist = memberDao.get(memberId);
if (exist != null)
throw new RuntimeException("Exist id");
memberDao.insert(new Member(memberId, name));
notificationService.notify(memberId, name);
}
그럼 언제 사용해야 할까?
만약 join이 완료됐을 때 여러 클래스에 콜백을 받길 원한다면 위 코드처럼 한 줄 한 줄 호출하는 것보다 리스너를 정의해서 리스트 기반으로 호출하는 것이 유지 보수에 유리하지 않을까 한다.
'Spring > Spring' 카테고리의 다른 글
[Spring] Proxy를 적용하는 다양한 방법 : ProxyFactory (1) (0) | 2024.02.02 |
---|---|
[Spring] Bean을 stateless하게 설계해야하는 이유 (1) | 2023.12.03 |
[Spring] Argument Resolver란 (HandlerMethodArgumentResolver, WebMvcConfigurer) (0) | 2022.10.11 |
[Spring] Interceptor란 (HandlerInterceptor, WebMvcConfigurer) (0) | 2022.10.03 |