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

时间:2017-04-20 08:53:38

标签: java spring dependency-injection aop

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

1 个答案:

答案 0 :(得分:9)

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所需的内容,在这种情况下需要Databaseinjector以递归方式调用自身:

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

2a)如果Database的实例已经可用,则再次进行检查。

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

2c)返回Database个实例。

3)在Database实例可用的情况下,injector现在可以构建EmployeeDaoEmployeeDao.class.newInstance() - 借助于反射,字段{{1}注入了database实例。

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

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