编程语言中的反射(Refection)指的是可以在程序运行期动态加载一个类。与之相关的是自省(Introspection),这个指的是程序自己可以获取一个类型的描述信息,例如获取一个类的所有接口定义、一个接口的所有形参。当编程语言有了这些语言特性之后,可以在很大程度上解决代码耦合问题,所以在Java的世界里,可以看到很多库/框架使用了反射技术。
类似Spring的Bean容器实现就是大量运用了反射机制。Bean容器维护了一些Bean对象,简单来说就是一些普通对象。Bean容器可以根据配置创建这些对象,创建时如果这些对象依赖了其他对象,Bean容器还会负责将依赖的对象注入到目标对象中,也就是所谓的依赖注入(dependence injection)。放在模块设计中,又衍生出控制反转(IoC, Inverse of Control)概念,用于描述应用程序在使用一个框架时,不是框架来控制/限制应用程序的架构模式,而是由应用程序来控制框架。
本文就简单描述下Bean容器是如何使用反射来实现的,最终代码参考github ioc-sample
类的动态加载
可以简单地使用Class.forName
,传入某个class的完整名:
public Class<?> loadClass(String fullName) throws ClassNotFoundException {
return Class.forName(fullName);
}
类的加载涉及到class loader,这块内容是可以进一步深化的。加载了类之后就可以创建出类的实例,但还没有完成依赖注入的功能:
Class<?> c = loadClass("com.codemacro.bean.test.Test1");
Object o = c.newInstance();
通过set接口注入
我们的类可以包含set
接口,用于设置某个成员: