Effective Java, written by Joshua Bloch, and first published in 2001, had a very influential section called Favor composition over inheritance:
https://books.google.co.nz/books?id=Ra9QAAAAMAAJ&q=inheritan...
Why do you think DI is so prevalent in Java codebases? It's a great way of simplifying composition.