I'm trying to understand if I can combine reflection with spring dependency injection as the following:
public interface ClientCommand {
public void execute(...);
public static enum Command {
SomeCommand(SomeCommand.class);
private Class<? extends ClientCommand> clazz;
private Command(Class<? extends ClientCommand> clazz) {
this.clazz = clazz;
}
public Class<? extends ClientCommand> getClazz() {
return clazz;
}
public static ClientCommand getClientCommand(String name) {
Command command = Enum.valueOf(Command.class, name);
return command.getClazz().newInstance();
}
}
}
This will create an instance of a command class based on the name passed in getClientCommand. This is an example of class extending ClientCommand:
public class LoginCommand implements ClientCommand {
@Autowired
private UserRepository userRepository;
public void setUserRepository(@Qualifier("userRepository")UserRepository userRepository) {
this.userRepository = userRepository;
}
public void execute(...) {
...
}
}
And the repository is something like:
@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository {
....
}
When the LoginCommand.execute() method is executed, the UserRepository is null. If I use the newInstance() to create the object, does spring care at all to inject the dependencies? More than for practical use, is to understand if is theoretically possible to get this code working. Thanks in advance
The Spring Framework does allow you to autowire private fields. You do see people doing this. And Spring will perform some reflection magic to perform dependency injection.
Dependency Injection with Reflection Abathur deploys another strategy that allows the dependency injection to be hidden away from the user of the framework. Abathur can not predict the class name of the user implementation but it can cheat and look it up in the assembly.
Spring IoC container uses reflection internally to create instances and to do most of the stuff. And reflection API provides newInstance() methods to create objects.
Reflection is an API that is used to examine or modify the behavior of methods, classes, and interfaces at runtime.
To answer this question:
If I use the newInstance() to create the object, does spring care at all to inject the dependencies?
I will answer with no, not by default. Spring will only inject dependencies on objects that Spring is in control of, and if you are using reflection to instantiate it, or the new
operator, then you are the one in control, not Spring.
But, there is hope. You can use AspectJ to do bytecode weaving when the new
operator is used, or even when Class.newInstance()
is used.
Take a look at this Spring documentation for more on this approach.
Since you're creating the object on your own Spring will not do dependency injection on the object. It will also not add any AOP proxies for it if its configured to do that.
You can either use AspectJ to instrument your code by adding the logic necessary to do dependency injection on the instance. This is done completely transparently.
Or you can do it yourself by using AutowireCapableBeanFactory. It's a semi-internal interface that you can use and its intended for just this purpose. It has a set of methods that do various parts of creating and injecting, you'll probably need the createBean() method.
You can get an AutowireCapableBeanFactory by calling getAutowireCapableBeanFactory on your ApplicationContext.
In your case it would probably be a good idea to create a CommandFactory, make that implement ApplicationContextAware and have a method like createCommand() that calls createBean().
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With