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

win*_*ama 5 java aop spring dependency-injection

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

joh*_*384 10

Spring做了很多事情,但依赖注入本身实际上是一个非常简单的机制.

它首先为可用于注入的类提供注册表.使用反射检查添加到此注册表的类.DI框架将查找相关的注释和构造函数,以确定如何构造类的实例以及这些类可能需要的其他依赖项.

注册表还会跟踪已创建的实例,以便可以重复使用它们.重用实例涉及范围确定,确定何时可以重用实例.使用单例(Spring的默认值)实例可以不受限制地重复使用.

要创建具有依赖项的类实例,请使用反射来创建实例.如果需要任何依赖项,则首先创建这些依赖项(如果尚未创建),可能会触发大量递归创建的实例.如果无法创建任何依赖项或者存在多个可能的候选项,则框架可以抛出异常以指示配置中存在问题.

一个简单的例子,假设我们有一个Injector类,它既可以作为类的注册表,也可以作为创建新实例的手段.

我们注册了几个课程:

injector.register(Database.class);
injector.register(EmployeeDao.class);
Run Code Online (Sandbox Code Playgroud)

假设Database类没有进一步的依赖关系,EmployeeDao依赖于Database:

class EmployeeDao {
   @Inject Database db;
} 
Run Code Online (Sandbox Code Playgroud)

injector,通过反射的方式,知道EmployeeDao有依赖Database.当我们要求以下injector实例EmployeeDao发生时:

EmployeeDao employeeDao = injector.getInstance(EmployeeDao.class);
Run Code Online (Sandbox Code Playgroud)

1)如果已存在实例EmployeeDao,则进行检查,如果存在,则返回.

2)如果没有,则进行检查以查看构造需要什么EmployeeDao,在这种情况下需要a Database.该injector递归调用自己有:

Database database = injector.getInstance(Database.class);
Run Code Online (Sandbox Code Playgroud)

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

2B)有以构建不需要进一步的依赖关系Database,因此injector呼吁Database.class.newInstance()并跟踪它.

2c)Database返回一个实例.

3)在Database实例可用的情况下,injector现在可以构造EmployeeDao:EmployeeDao.class.newInstance()- 在反射的帮助下,字段database被注入Database实例.

4)EmployeeDao返回现在完全注入的实例.

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