反思+弹簧依赖注入
我试图了解是否可以将反射与 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 为 null。 如果我使用 newInstance() 创建对象,spring 是否关心注入依赖项? 除了实际使用之外,还在于了解理论上是否可以使该代码正常工作。 提前致谢
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
回答这个问题:
我会回答“否”,默认情况下不会。 Spring 只会注入对 Spring 控制的对象的依赖关系,如果您使用反射来实例化它,或者使用
new
运算符,那么您但是,希望还是有的。当使用
new
运算符时,甚至当使用Class.newInstance()
时,您可以使用 AspectJ 进行字节码编织。看看这个 Spring 文档 了解有关此方法的更多信息。
To answer this question:
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 whenClass.newInstance()
is used.Take a look at this Spring documentation for more on this approach.
由于您是自己创建对象,Spring 不会对该对象进行依赖注入。如果配置为这样做,它也不会为其添加任何 AOP 代理。
您可以使用 AspectJ 通过添加在实例上执行依赖项注入所需的逻辑来检测您的代码。这是完全透明地完成的。
或者您可以使用 AutowireCapableBeanFactory 自己完成。它是一个您可以使用的半内部接口,其目的就是为了这个目的。它有一组方法可以完成创建和注入的各个部分,您可能需要 createBean() 方法。
您可以通过在 ApplicationContext 上调用 getAutowireCapableBeanFactory 来获取 AutowireCapableBeanFactory。
在您的情况下,创建一个 CommandFactory 、使其实现 ApplicationContextAware 并使用像 createCommand() 这样调用 createBean() 的方法可能是个好主意。
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().