That's right - the server just looks if there is a class whose name is equivalent to the string sent by the client. Well, dependency injection violation?
Nope. Thats fine. It's basically what spring does. They just do it with a xml file.
But please don't confuse framework dependency injection with pure dependency injection.
Framework DI helps you keep construction separate from usekeep construction separate from use by making you construct in a different language. In springs case this other language is often XML. In your case it's simple strings.
Pure DI lets you stick with your main general purpose language. You just have to learn how to keep use and construction separate on your own.
That means breaking the habit of constructing, or going and finding something, the moment you realize you need it. Instead you announce that you depend on it by asking it to be passed to you. This makes your needs explicit. It makes them easier to spot since no one has to crawl the code to learn what it needs.
Construct objects as high up the call stack as you can. That doesn't mean everything is built in main. Just everything that lives as long as main. That isn't everything. For example, it is ok to construct now timestamps when they are needed because they need info that didn't exist until just now.
Notice I said nothing about when the timestamp is used. All I care about is whether I have what I need to know to construct it. Don't let use drive construction. Let the availability of info that construction depends on drive construction.