JPA
JPA save() Domain Event 추가하기
du.study
2020. 12. 13. 21:22
728x90
JPA 를 사용하면서 save동작시, event를 등록하는 방법에 대해 기록하려합니다.
특정 entity가 저장이 될때, event호출을 통하여 특정 동작을 수행하게 할 수 있습니다.
코드로 간략하게 보면 다음과 같습니다.
Event 코드
public class AccountEvent extends ApplicationEvent {
private final Account account;
public AccountEvent(Object source) {
super(source);
this.account = (Account) source;
}
public Account getAccount() {
return account;
}
}
Listener 코드
@Component
public class AccountSaveListener implements ApplicationListener<AccountEvent> {
@Override
public void onApplicationEvent(AccountEvent accountEvent) {
System.out.println("event occurred");
Account account = accountEvent.getAccount();
System.out.println(account.getUsername() +","+account.getPassword());
}
}
Entity 코드
@Entity
public class Account extends AbstractAggregateRoot<Account> {
@Id
@GeneratedValue
private Long id;
private String username;
private String password;
.... 생략
public Account publish(){
this.registerEvent(new AccountEvent(this));
return this;
}
}
테스트를 위한 Runner코드
@Component
public class JpaRunner implements ApplicationRunner {
@Autowired
private AccountRepository accountRepository;
@Override
public void run(ApplicationArguments args) throws Exception {
Account account = new Account();
account.setUsername("DUSANG");
account.setPassword("PWD");
accountRepository.save(account.publish());
}
}
간단하게 정리하면 동작 순서는 다음과 같게됩니다.
1. 사전세팅을 진행한다.
- Event 작성
- Event를 받는 Listener 작성 ( bean으로 등록)
- Entity에 AbstractAggregateRoot<{Entity name}> 상속.
- save() 시 registerEvent 코드가 같이 등록될 함수 어딘가에 저장.
2. save를 하면서 특정 registerEvent 를 같이 등록하는 함수 호출
3. 이벤트 리스너 호출.
다음과 같이 동작하게됩니다.
추가)
save과정에서 코드를 따라가다 보면 다음 EventPublishingRepositoryProxyPostProcessor 클레스에서 해당 함수가 호출되게 됩니다.
public void publishEventsFrom(@Nullable Object object, ApplicationEventPublisher publisher) {
if (object == null) {
return;
}
for (Object aggregateRoot : asCollection(object)) {
for (Object event : asCollection(ReflectionUtils.invokeMethod(publishingMethod, aggregateRoot))) {
publisher.publishEvent(event);
}
if (clearingMethod != null) {
ReflectionUtils.invokeMethod(clearingMethod, aggregateRoot);
}
}
}
해당 코드에서 publisher.publishEvent(event); 를 보고 여러 event를 등록할 수있다는것을 알 수있습니다.
한코드에 모든것을 때려박는 짓을 피할 수 있습니다.
728x90