Spring如何在运行时实现依赖注入?

10

有人知道Spring在运行时实现依赖注入的技术是什么吗?它只是使用了切面(AOP),还是有更复杂的东西?


请查看此链接(https://www.javatpoint.com/dependency-injection-in-spring)和此链接(https://www.quora.com/How-does-dependency-injection-work-in-Spring)。 - ahoxha
1个回答

14

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注入器使用递归调用自身:

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实例被返回。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接