Spring 系列 - 注册对象和依赖管理
Last updated: Oct 219, 21029
问
IoC 框架中的各对象是如何创建的,由谁管理的?如何管理依赖关系的?
答
Ioc Service Provider
背景
在 IoC 场景中,业务对象虽然可以通过某种方式声明相应的依赖,
但最终仍需要通过 某种角色 或 服务 将这些相互依赖的对象绑定到一起,
这一角色 称为 IoC Service Provider
职责
业务对象的构建管理
业务对象间的依赖绑定
业务对象的构建管理
虽然业务对象无需关心所依赖的对象如何构建如何取得,
但这部分工作始终需要人做,交给 IoC Service Provider
业务对象间的依赖绑定
这是 IoC Service Provider 最重要最艰巨的职责,
IoC Service Provider 构建完对象后,识别它们的依赖关系,实现依赖绑定,
保证在使用到每个业务对象时,处于就绪状态
管理实现
IoC Service Provider 需要知道 被注入对象 和 依赖对象 间的关系
这种关系需要以某种方式记录下来,如:
- 通过基本的 文本方式 记录
- 通过 XML 文件记录
- 通过 编码方式 记录
以下是实际情况下,IoC Container 记录这种关系的几种方式:
直接编码方式
通过 程序编码 的方式将 被注入对象 和 依赖对象 注册到容器中,
并明确它们相互之间的依赖注入关系
IoCContainer container = ...;
container.register(FXNewsProvider.class, new FXNewsProvider());
container.register(IFXNewsListener.class, new DowJonesNewsListener());
...
FXNewsProvider newsProvider = (FXNewsProvider)container.get(FXNewsProvider.class);
newsProvider.getAndPersistNews();
在这段代码中,展示了 直接编码 这种记录方式。
这是管理 依赖绑定关系 的最基本方式。
配置文件方式
较为普遍的依赖注入关系管理方式。
最为常见的是通过 XML 文件管理对象注册和对象间依赖关系。
<bean id="newsProvider" class="..FXNewsProvider">
<property name="newsListener">
<ref bean="djNewsListener" />
</property>
<property name="newsPersister">
<ref bean="djNewsPersister" />
</property>
</bean>
<bean id="djNewsListener"
class="..impl.DowJonesNewsListener">
</bean>
<bean id="djNewsPersister"
class="..impl.DowJonesNewsPersister">
</bean>
IoC Service Provider 通过读取配置文件,得到其中的实例使用:
...
container.readConfigurationFiles(...);
FXNewsProvider newsProvider = (FXNewsProvider) container.getBean("newsProvider");
newsProvider.getAndPersistNews();
元数据方式(注解的方式)
这种方式的实现代表是 Google Guice。这是一套轻量级的 IoC 框架。
通过在类中使用 注解 来标注各个对象间的依赖关系,交给 Guice 框架处理
Guice 框架根据注解提供的信息组装对象,交给客户端对象使用。
第一步 使用 Guice 提供的注解标注依赖关系后的 FXNewsProvider 的定义
public class FXNewsProvider {
private IFXNewsListener newsListener;
private IFXNewsPersister newsPersister;
@Inject
public FXNewsProvider(IFXNewsListener listener, IFXNewsPersister persister) {
this.newsListener = listener;
this.newsPersister = persister;
}
...
}
通过 @Inject 注解,指明用 构造方法注入 方式,为 FXNewsProvider 注入其依赖的对象。
第二步 进一步制定依赖注入相关信息
public class NewsBindingModule extends AbstractModule {
@Override
protected void configure() {
bind(IFXNewsListener.class).to(DowJonesNewsListener.class).in(Scopes.SINGLETON);
bind(IFXNewsPersister.class).to(DowJonesNewsPersister.class).in(Scopes.SINGLETON);
}
}
第三步 从 Guice 获取并使用创建完成的 FXNewsProvider
Injector injector = Guice.createInjector(new NewsBindingModule());
FXNewsProvider newsProvider = injector.getInstance(FXNewsProvider.class);
newsProvider.getAndPersistNews();