Your understanding is correct I guess. But let me give you a simplified explanation of the process so you can compare it to your current understanding.
When you issue a command that creates new aggregate (one that is handled by the Aggregate’s constructor) there is no need for identifier. The reason is you are creating a new instance, not loading an existing one. In that case the framework only needs the FQCN of the aggregate in order to create an instance of it. It can easily find the FQCN because it knows (from inspection during aggregate registration) which aggregate can handle such create command. That’s why create commands without @TargetAggregateIdentifier
work just fine.
Once the create command is processed the aggregate’s state needs to be stored somewhere.
- for event sourced aggregates all state changing events are stored in a event store
- for state stored aggregates the entire state is stored in a repository
In both cases the framework needs to know how to identify this data. That’s what @AggregateIdentifier
is for. It tells the framework to store the data in way that it is identifiable by specific identifier. You can think of it as primary key in DB terms.
When you send a command to an existing instance of an aggregate you need to tell which instance that is. You do so by providing a @TargetAggregateIdentifier
. The framework will then create a new empty instance of the respective aggregate and then try to load the data into it
- for event sourced aggregates by reading all the past events related to that instance
- for state stored aggregates by reading current state from a repository
In both cases the framework will search for data that’s identifiable by the value of @TargetAggregateIdentifier
. Once the aggregate data is loaded it will proceed with handling the command.