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
通过反射知道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()
-- 在反射的帮助下,字段 database
注入了 Database
实例。
4) 现在完全注入的 EmployeeDao
实例被返回。
这是获取 class 实例的相当直接的方法,然而这是像 Spring 这样的 DI 框架工作的核心。更高级的功能需要创建动态代理和使用 AOP,但 DI 本身归结为使用反射自动构造实例。
有谁知道技术 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
通过反射知道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()
-- 在反射的帮助下,字段 database
注入了 Database
实例。
4) 现在完全注入的 EmployeeDao
实例被返回。
这是获取 class 实例的相当直接的方法,然而这是像 Spring 这样的 DI 框架工作的核心。更高级的功能需要创建动态代理和使用 AOP,但 DI 本身归结为使用反射自动构造实例。