Spring如何在类只有一个参数的构造函数时,使用反射来创建对象?
我刚接触Spring,还在学习中,看到有一篇帖子说,当我在一个类里使用 @Autowired时,但这篇帖子没有说明注解到底在哪儿,Spring会使用反射来创建bean,然后注入依赖,我在想我的理解可能并不完全,但我知道它会调用无参构造函数来创建这个bean,然后再注入—— 但如果
@Component
public class A {
}
@Component
public class B{
private A a;
@Autowired
public B( A a){
this.a = a;
}
}
反射如何在只有一个可用构造函数的情况下创建类B 的这个bean?
解决方案
正如Sina Soheili的回答所指出,Spring除了字段注入外,还支持构造注入和setter注入。实际上,避免字段注入才是最佳实践。但它们都使用了 反射。反射可用于调用构造函数和方法。它不仅仅是关于字段。
对于一个直接的示例(不使用Spring),你可以通过反射自己创建 A 和 B 的实例,如下所示:
public static class A {}
public static class B {
private final A a;
public B(A a) {
this.a = a;
}
public A getA() {
return a;
}
}
void main() throws ReflectiveOperationException {
A a = A.class.getConstructor().newInstance();
B b = B.class.getConstructor(A.class).newInstance(a);
IO.println("b = " + b);
IO.println("b.a = " + b.getA());
}
– 参阅 java.lang.reflect.Constructor 及相关文档以了解更多信息。
将这段代码复制到名为 Example.java 的源文件中并执行它1。你将看到类似如下的输出:
> java Example.java
b = Example$B@62e136d3
b.a = Example$A@6279cee3
现在,Spring要复杂得多,因为它需要考虑注解、上下文、作用域、生命周期、生产者、多种实现、任意代码等诸多因素。但从本质上讲,上面的示例已经演示了Spring如何通过反射创建一个类的实例,即使该类没有无参构造函数。
顺便说一句,如果一个类只有一个构造函数,那么就不需要用 @Autowired 来标注它。Spring会假设那一个构造函数就是要被调用的那个,显然没有其他选择。
1. 该示例使用了在Java 25中新增的 java.lang.IO 类。执行它也涉及 JEP 330: Launch Single-File Source-Code Programs 和 JEP 512: Compact Source Files and Instance Main Methods,分别在Java 11和 Java 25中引入。因此,该示例要按原样运行需要Java 25及以上版本。不过,反射代码在Java 1.1(1997年发布)中也应可适用。