我想知道我是否可以将反射与spring依赖注入相结合,如下所示:
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();
}
}
}
这将基于getClientCommand中传递的名称创建命令类的实例。这是一个类扩展ClientCommand的例子:
public class LoginCommand implements ClientCommand {
@Autowired
private UserRepository userRepository;
public void setUserRepository(@Qualifier("userRepository")UserRepository userRepository) {
this.userRepository = userRepository;
}
public void execute(...) {
...
}
}
存储库是这样的:
@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository {
....
}
当执行LoginCommand.execute()方法时,UserRepository为空。如果我使用newInstance()来创建对象,spring关心注入依赖关系吗?不仅仅是为了实际使用,更重要的是理解在理论上是否有可能使这些代码工作。提前感谢
回答这个问题:
如果我使用newInstance()来创建对象,spring关心注入依赖关系吗?
我将回答no,不是默认的。Spring只会在Spring控制的对象上注入依赖,如果你使用反射来实例化它,或者new
操作符,那么你是控制对象,而不是Spring。
但是
还是有希望的。当使用new
操作符时,甚至当使用Class.newInstance()
操作符时,您可以使用AspectJ来进行字节码编织。
查看Spring文档,了解更多关于此方法的信息。
由于您是在自己的对象上创建对象,所以Spring不会对该对象进行依赖注入。如果它被配置为这样做,它也不会为它添加任何AOP代理。
您可以使用AspectJ通过添加对实例进行依赖注入所需的逻辑来检测您的代码。这是完全透明的。
或者你可以自己使用AutowireCapableBeanFactory。它是一个半内部接口,你可以使用它,它的目的就是为了这个目的。它有一组方法来完成创建和注入的各个部分,您可能需要createBean()方法。
你可以通过在ApplicationContext中调用getAutowireCapableBeanFactory来获取AutowireCapableBeanFactory。
在您的情况下,它可能是一个好主意,创建一个CommandFactory,使实现ApplicationContextAware,并有一个方法像createCommand()调用createBean()。