modify Readme

This commit is contained in:
Daniel Kang
2018-04-17 14:25:57 +09:00
parent 02b2f7895b
commit 33c3a44f08

191
README.md
View File

@@ -50,23 +50,204 @@ Axon framework을 이용하기 위해서는 Maven dependency를 추가하면 된
첫번째 예제애서는 은행 계좌에 예금을 입출금하는 예제를 이용하여 Axon Framework의 기본적인 작동 원리를 이해한다.
### Scenairio
### Scenairio
계죄를 개설하고, 입금, 출금을 한다.
### Aggregate
Collection of Entity (Entity 집합체)
### Aggregate
Collection of Entity (Entity 집합체)
DDD에서 약간 내용 추가 필요
``` java
#### BankAccount 클래스
``` java
public class BankAccount {
@AggregateIdentifier
private AccountId accountId;
private String accountName;
private BigDecimal balance;
}
```
```
@Aggregate을 이용해서 Aggregate Class를 선언할 수 있는데, 각각의 Aggregate은 식별자인 GUID를 가져야 하며, @AggregateIdentifier로 구분한다.
AggregateIdentifier는
- 비교를 위해서 equal 과 hashCode 메소드를 구현하며
- Serializable 인터페이스를 상속한다.
``` java
public class AccountId implements Serializable {
private static final long serialVersionUID = 7119961474083133148L;
private final String identifier;
private final int hashCode;
public AccountId() {
this.identifier = IdentifierFactory.getInstance().generateIdentifier();
this.hashCode = identifier.hashCode();
}
public AccountId(String identifier) {
Assert.notNull(identifier, ()->"Identifier may not be null");
this.identifier = identifier;
this.hashCode = identifier.hashCode();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AccountId accountId = (AccountId) o;
return identifier.equals(accountId.identifier);
}
@Override
public int hashCode() {
return hashCode;
}
@Override
public String toString() {
return identifier;
}
}
```
#### Command
CQRS에서 모든 Write(CUD)는 Command Class에서 처리한다. Axon에서는 모든 Command는 POJO를 구성한다.
Axon은 Event-Driven Architecture를 기반으로 만들어져 있기 때문에, 내부적으로는 "CommandMessage"로 encapsulation된다.
```java
public class CreateAccountCommand {
private AccountId accountId;
private String accountName;
private long amount;
public CreateAccountCommand(AccountId accountId, String accountName, long amount) {
this.accountId = accountId;
this.accountName = accountName;
this.amount = amount;
}
//getter & setter
...
}
public class WithdrawMoneyCommand {
@TargetAggregateIdentifier
private AccountId accountId;
private long amount;
public WithdrawMoneyCommand(AccountId accountId, long amount) {
this.accountId = accountId;
this.amount = amount;
}
//getter & setter
...
}
```
#### Event
Event는 시스템의 변화를 발생할때 생성되는 Event Classs이며, 기본적으로 Aggregate에 변경이 가해질때 발생하며, Command와 마찬가지고 POJO이다.
Event는 EventMessage로 encapsulation된다.
```java
public class AccountCreatedEvent {
private AccountId accountId;
private String accountName;
private long amount;
public AccountCreatedEvent(AccountId accountId, String accountName, long amount) {
this.accountId = accountId;
this.accountName = accountName;
this.amount = amount;
}
//getter & setter
...
}
public class MoneyWithdrawnEvent {
private AccountId accountId;
private long amount;
public MoneyWithdrawnEvent(AccountId accountId, long amount) {
this.accountId = accountId;
this.amount = amount;
}
//getter & setter
...
}
```
#### CommandHandler
Axon에서는 Command Handler를 지정하기 위해서 @CommandHandler를 사용한다.
아래와 같이 설정하면, Command가 발생할때 Command-CommandHanlder쌍(key-value)으로 작동한다.
```java
@CommandHandler
public BankAccount(CreateAccountCommand command){
apply(new AccountCreatedEvent(command.getAccountId(), command.getAccountName(), command.getAmount()));
}
@CommandHandler
public void handle(WithdrawMoneyCommand command){
apply(new MoneyWithdrawnEvent(command.getAccountId(), command.getAmount()));
}
```
위의 예제는 단순이 Event를 생성하고, static method인 apply를 호출해서 event를 발생시킨다.
#### EventHandler
@EventHanldere는 event 처리기 역할를 하는 메소드를 지정한다.
```java
@EventHandler
public void on(AccountCreatedEvent event){
this.accountId = event.getAccountId();
this.accountName = event.getAccountName();
this.balance = new BigDecimal(event.getAmount());
LOGGER.info("Account {} is created with balance {}", accountId, this.balance);
}
@EventHandler
public void on(MoneyWithdrawnEvent event){
BigDecimal result = this.balance.subtract(new BigDecimal(event.getAmount()));
if(result.compareTo(BigDecimal.ZERO)<0)
LOGGER.error("Cannot withdraw more money than the balance!");
else {
this.balance = result;
LOGGER.info("Withdraw {} from account {}, balance result: {}", event.getAmount(), accountId, balance);
}
}
```
```java
public class Application {
private static final Logger LOGGER = getLogger(Application.class);
public static void main(String args[]){
Configuration config = DefaultConfigurer.defaultConfiguration()
.configureAggregate(BankAccount.class)
.configureEmbeddedEventStore(c -> new InMemoryEventStorageEngine())
.buildConfiguration();
config.start();
AccountId id = new AccountId();
config.commandGateway().send(new CreateAccountCommand(id, "MyAccount",1000));
config.commandGateway().send(new WithdrawMoneyCommand(id, 500));
config.commandGateway().send(new WithdrawMoneyCommand(id, 500));
}
}
```
## Example 2