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
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().
精彩评论