在使用Spring框架时,我们经常会用到@Autowired注解,也就是自动装配的意思。
当在一个类中需要另一个类时,可是在Spring中使用@Autowired注解。
类B
package otherexperiment.createautowired;
public class B {
public String name = "defuli";
}
类A
package otherexperiment.createautowired;
public class A {
@Autowired
public B b;
public void printBName() {
System.out.println(b.name);
}
}
类Test
package otherexperiment.createautowired;
public class Test {
public static void main(String[] args) {
A a = new A();
a.printBName(); // 可以正常打印出 defuli
}
}
看到这,有没有觉得很奇怪,在类A中,我们并没有创建B对象,仅仅是创建了B的一个引用而已,为什么在类Test中可以正常的打印出"defuli"字符串?
原因在@Autowired注解这里,使用了该注解,Spring框架会自动创建B的对象然后装配给类A中的b引用。
手写@Autowired注解
首先创建一个名为Autowired的注解,创建注解和创建接口很像,就是在接口的前面加@。
package otherexperiment.createautowired;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}
类Main
package otherexperiment.createautowired;
import java.lang.reflect.Field;
public class Main {
public static void main(String[] args) throws IllegalAccessException, InstantiationException {
// 自动装配的过程
A a = new A();
Class<? extends A> clazz = a.getClass();
Field[] fields = clazz.getFields();
for (Field field : fields) {
Autowired autowired = field.getAnnotation(Autowired.class);
if (autowired != null) {
Class fieldClass = field.getType(); // 在这里就是B.class
B b = (B) fieldClass.newInstance();
field.set(a, b);
}
}
// 测试 打印输出
a.printBName(); // defuli
}
}
在类Main中,运行的结果就是正常的打印出了“defuli”字符串。
总结
之所以我们能实现@Autowired注解的功能,是利用了Java反射的原理。在程序运行时,可以在Jvm中动态的创建出B的对象,然后赋值给对象a的b属性。