spring如何实现运行时的依赖注入?

How does spring achieve dependency injection at runtime?

有谁知道技术 spring使用什么来实现运行时的依赖注入?它是简单地使用方面 (AOP) 还是更复杂的东西?

Spring 做了很多事情,但依赖注入本身实际上是一个非常简单的机制。

首先要有一个可用于注入的 classes 的注册表。 类 使用反射检查添加到此注册表中的内容。 DI 框架将寻找相关的注释和构造函数来确定如何构造 classes 的实例以及这些 classes 可能需要的其他依赖项。

注册表还会跟踪已创建的实例,以便可以重复使用它们。重用实例涉及范围界定,它确定何时可以重用实例。使用单例(Spring 的默认值)实例可以不受限制地重复使用。

创建具有依赖关系的class实例,使用反射创建实例。如果需要任何依赖项,则首先创建这些依赖项(如果尚未创建)可能会触发大量实例的递归创建。如果无法创建任何依赖项或有多个可能的候选者,框架会抛出异常以指示您的配置存在问题。

一个简单的例子,假设我们有一个 Injector class,它既充当 classes 的注册表,又充当创建新实例的手段。

我们注册了几个classes:

injector.register(Database.class);
injector.register(EmployeeDao.class);

让我们假设数据库 class 没有进一步的依赖关系,而 EmployeeDao 对数据库有依赖关系:

class EmployeeDao {
   @Inject Database db;
} 

injector通过反射知道EmployeeDaoDatabase有依赖。当我们向 injector 询问 EmployeeDao 的实例时,会发生以下情况:

EmployeeDao employeeDao = injector.getInstance(EmployeeDao.class);

1) 检查是否已经存在 EmployeeDao 的实例,如果存在则返回。

2) 如果不是,则进行检查以查看构建 EmployeeDao 所需的内容,在本例中它需要一个 Databaseinjector 递归调用自身:

Database database = injector.getInstance(Database.class);

2a) 再次检查 Database 的实例是否已经可用。

2b) 构造 Database 不需要进一步的依赖关系,因此 injector 调用 Database.class.newInstance() 并跟踪它。

2c) 返回一个 Database 实例。

3) Database 实例可用后,injector 现在可以构造 EmployeeDaoEmployeeDao.class.newInstance() -- 在反射的帮助下,字段 database 注入了 Database 实例。

4) 现在完全注入的 EmployeeDao 实例被返回。

这是获取 class 实例的相当直接的方法,然而这是像 Spring 这样的 DI 框架工作的核心。更高级的功能需要创建动态代理和使用 AOP,但 DI 本身归结为使用反射自动构造实例。