问题描述
有人知道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)再次检查数据库
的实例是否可用.
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如何在运行时实现依赖注入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!