有谁知道spring在运行时实现依赖注入的技术是什么?它只是简单地使用方面(AOP)还是更复杂的东西?
答案 0 :(得分:9)
Spring做了很多事情,但依赖注入本身实际上是一个非常简单的机制。
首先为可注入的类提供注册表。 使用反射检查添加到此注册表的类。 DI框架将查找相关的注释和构造函数,以确定如何构造类的实例以及这些类可能需要的其他依赖项。
注册表还会跟踪已创建的实例,以便可以重复使用它们。重用实例涉及范围确定,确定何时可以重用实例。使用单例(Spring的默认值)实例可以不受限制地重复使用。
要创建具有依赖关系的类的实例,请使用反射来创建实例。如果需要任何依赖项,则首先创建这些依赖项(如果尚未创建),可能会触发大量递归创建的实例。如果无法创建任何依赖项或者存在多个可能的候选项,则框架可以抛出异常以指示配置中存在问题。
一个简单的例子,假设我们有一个Injector
类,它既可以作为类的注册表,也可以作为创建新实例的方法。
我们注册了几个课程:
injector.register(Database.class);
injector.register(EmployeeDao.class);
假设Database类没有进一步的依赖关系,EmployeeDao依赖于Database:
class EmployeeDao {
@Inject Database db;
}
injector
通过反思知道EmployeeDao
依赖于Database
。当我们向injector
询问EmployeeDao
的实例时,会发生以下情况:
EmployeeDao employeeDao = injector.getInstance(EmployeeDao.class);
1)如果已经存在EmployeeDao
的实例,则进行检查,如果是,则返回。
2)如果没有,则进行检查以查看构建EmployeeDao
所需的内容,在这种情况下需要Database
。 injector
以递归方式调用自身:
Database database = injector.getInstance(Database.class);
2a)如果Database
的实例已经可用,则再次进行检查。
2b)构建Database
不需要进一步的依赖关系,以便injector
调用Database.class.newInstance()
并跟踪它。
2c)返回Database
个实例。
3)在Database
实例可用的情况下,injector
现在可以构建EmployeeDao
:EmployeeDao.class.newInstance()
- 借助于反射,字段{{1}注入了database
实例。
4)返回现在完全注入的Database
实例。
这是获取类实例的相当直接的方法,但这是DI框架像Spring一样工作的核心。更高级的功能需要创建动态代理和AOP的使用,但DI本身归结为使用反射自动构造实例。