Guava EventBus 외 Spring의 ApplicationEventPublisher도 사용 가능
<pom.xml>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
TaskExecutor - 실제 이벤트를 전달하는 일을 하는 객체
AsyncEventBus - Guava EventBus
-> 이 이벤트버스에 등록, 구독 작업이 수행되는 설정
<EventConfigure.java>
@Configuration
public class EventConfigure {
@Value("${eventBus.asyncPool.core}")
private int eventBusAsyncPoolCore;
@Value("${eventBus.asyncPool.max}")
private int eventBusAsyncPoolMax;
@Value("${eventBus.asyncPool.queue}")
private int eventBusAsyncPoolQueue;
@Bean
public TaskExecutor eventTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setThreadNamePrefix("EventBus-");
executor.setCorePoolSize(eventBusAsyncPoolCore);
executor.setMaxPoolSize(eventBusAsyncPoolMax);
executor.setQueueCapacity(eventBusAsyncPoolQueue);
executor.afterPropertiesSet();
return executor;
} // TaskExecutor 작업
@Bean
public EventExceptionHandler eventExceptionHandler() {
return new EventExceptionHandler();
}
@Bean
public EventBus eventBus(TaskExecutor eventTaskExecutor, EventExceptionHandler eventExceptionHandler) {
return new AsyncEventBus(eventTaskExecutor, eventExceptionHandler); // EventBus 등록
}
@Bean(destroyMethod = "close")
public JoinEventListener joinEventListener(EventBus eventBus, NotificationService notificationService) {
return new JoinEventListener(eventBus, notificationService);
}
}
@Service
public class UserService {
private final EventBus eventBus;
public UserService(S3Client s3Client, PasswordEncoder passwordEncoder, UserRepository userRepository, EventBus eventBus) {
// ...
this.eventBus = eventBus;
@Transactional
public User join(String name, Email email, String password, AttachedFile profileFile) {
String profileImageUrl = uploadProfileImage(profileFile);
// 이미지 업로드 성공/실패 결과에 관계없이 join 트랜잭션을 처리한다.
User user = new User(name, email, passwordEncoder.encode(password), profileImageUrl);
User saved = save(user);
// raise event
eventBus.post(new JoinEvent(saved));
return saved;
}
public class JoinEventListener implements AutoCloseable {
private Logger log = LoggerFactory.getLogger(JoinEventListener.class);
private EventBus eventBus;
public JoinEventListener(EventBus eventBus, NotificationService notificationService) {
this.eventBus = eventBus;
eventBus.register(this);
}
@Subscribe
public void handleJoinEvent(JoinEvent event) {
String name = event.getName();
Id<User, Long> userId = event.getUserId();
log.info("user {}, userId {} joined!", name, userId);
}
@Override
public void close() throws Exception {
eventBus.unregister(this);
}
}
@Configuration
public class EventConfigure {
//...
@Bean(destroyMethod = "close")
public JoinEventListener joinEventListener(EventBus eventBus, NotificationService notificationService) {
return new JoinEventListener(eventBus, notificationService);
}
}