spring如何实现运行时的依赖注入? [英] How does spring achieve dependency injection at runtime?
问题描述
有谁知道spring在运行时使用什么技术来实现依赖注入?它是简单地使用方面 (AOP) 还是更复杂的东西?
Does anyone know what technique spring uses to achieve dependency injection at runtime? Does it simply use aspects (AOP) or is it something more complicated?
推荐答案
Spring 做了很多事情,但依赖注入本身实际上是一种非常简单的机制.
Spring does a lot of things, but dependency injection itself is actually a surprisingly simple mechanism.
首先要有一个可用于注入的类的注册表.添加到此注册表的类使用反射进行检查.DI 框架将寻找相关的注解和构造函数,以确定如何构造类的实例以及这些类可能需要哪些其他依赖项.
It starts with having a registry for classes that are available for injection. Classes that are added to this registry are examined using reflection. A DI framework will look for relevant annotations and constructors to determine how to construct instances of the classes and also what other dependencies these classes may need.
注册表还跟踪已创建的实例,以便它们可以重复使用.重用实例涉及范围界定,它确定何时可以重用实例.使用单例(Spring 的默认设置)实例可以不受限制地重复使用.
The registry also keeps track of already created instances so they can be re-used. Re-using instances involves scoping, which determines when an instance can be re-used. With singletons (the default for Spring) instances can be re-used without restriction.
要创建具有依赖项的类的实例,使用反射来创建实例.如果需要任何依赖项,则首先创建这些依赖项(如果尚未创建)可能会触发大量递归创建实例.如果无法创建任何依赖项或存在多个可能的候选项,则框架会抛出异常以指示您的配置存在问题.
To create an instance of class with dependencies, reflection is used to create an instance. If there are any dependencies required, those are created first (if not already created) potentially triggering a lot of recursive creation of instances. If any of the dependencies cannot be created or there are multiple possible candidates, the framework can throw an exception to indicate a problem in your configuration.
一个简单的例子,假设我们有一个 Injector
类,它既充当类的注册表,又充当创建新实例的手段.
A simple example, let's say we have an Injector
class that acts as both registry of classes and as a means to create new instances.
我们注册了一些课程:
injector.register(Database.class);
injector.register(EmployeeDao.class);
假设 Database 类没有进一步的依赖,EmployeeDao 依赖于 Database:
Let's assume the Database class has no further dependencies, and EmployeeDao has a dependency on Database:
class EmployeeDao {
@Inject Database db;
}
injector
,通过反射,知道EmployeeDao
依赖于Database
.当我们向 injector
请求 EmployeeDao
的实例时,会发生以下情况:
The injector
, by means of reflection, knows that EmployeeDao
has a dependency on Database
. When we ask the injector
for an instance of EmployeeDao
the following happens:
EmployeeDao employeeDao = injector.getInstance(EmployeeDao.class);
1) 检查是否已经存在 EmployeeDao
的实例,如果存在则返回.
1) A check is done if there already exists an instance of EmployeeDao
, if so it is returned.
2) 如果没有,则进行检查以查看构建EmployeeDao
所需的内容,在这种情况下,它需要一个Database
.injector
递归调用自身:
2) If not, a check is done to see what is needed to construct EmployeeDao
, in this case it needs a Database
. The injector
calls itself recursively with:
Database database = injector.getInstance(Database.class);
2a) 再次检查 Database
的实例是否已经可用.
2a) Again a check is done if an instance of Database
is already available.
2b) 构建Database
不需要进一步的依赖,所以injector
调用Database.class.newInstance()
并保持跟踪它.
2b) There are no further dependencies required in order to construct Database
so the injector
calls Database.class.newInstance()
and keeps track of it.
2c) 返回一个 Database
实例.
2c) A Database
instance is returned.
3) 随着 Database
实例可用,injector
现在可以构造 EmployeeDao
:EmployeeDao.class.newInstance()
-- 在反射的帮助下,字段database
被注入Database
实例.
3) With the Database
instance available, the injector
can now construct the EmployeeDao
: EmployeeDao.class.newInstance()
-- with the help of reflection, the field database
is injected with the Database
instance.
4) 返回已完全注入的 EmployeeDao
实例.
4) The EmployeeDao
instance, now fully injected, is returned.
这是获取类实例的相当直接的方式,但是这是像 Spring 这样的 DI 框架的核心工作方式.更高级的功能需要创建动态代理和使用 AOP,但 DI 本身归结为使用反射自动构造实例.
This is fairly direct way of obtaining an instance of a class, however this is at the core how DI frameworks like Spring work. More advanced features require creation of dynamic proxies and the use of AOP, but DI itself boils down to using reflection to construct instances automatically.
这篇关于spring如何实现运行时的依赖注入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!