Oie Armando, tudo bem contigo?
Na prática, quando colocamos em código, a agregação e a composição funcionam da mesma forma, sendo usadas para reutilização de código. Mas quando pensamos no mundo "UML", ambas acabam tendo diferenças mais visíveis, segue uma comparação entre elas abaixo:
Composição: nessa relação o "objeto pai" (todo) é responsável por criar e destruir suas partes. O "objeto filho" (parte) compõe o "objeto pai" (todo), e caso ele for destruído o "objeto filho" (parte) também será. Um exemplo dessa relação é o de "edição - revista", a edição só existe por conta da revista, se a revista for destruída a edição também será.
Agregação: nessa relação o "objeto pai" (todo) irá usar algumas informações contidas no "objeto filho" (parte), e caso o "objeto pai" for destruído o "objeto filho" continuará existindo. Um exemplo seria o de "jogador - time", caso o time seja destruído o jogador ainda continuará existindo.
Segue alguns artigos que tratam sobre esses temas de maneira mais profunda:
Importante ressaltar, o "mundo UML" não necessariamente é aplicado 100% no código, tanto que não existe diferença clara na aplicação de uma composição ou agregação no Java, podendo ser facilmente confundidas na hora de implementar.
Espero que eu tenha ajudado, se tiver qualquer outra dúvida fico a disposição :)
Bons estudos!