徐昊 · TDD 项目实战 70 讲
徐昊
Thoughtworks 中国区 CTO
18159 人已学习
新⼈⾸单¥98
登录后,你可以任选4讲全文学习
课程目录
已完结/共 88 讲
实战项目二|RESTful开发框架:依赖注入容器 (24讲)
实战项目三|RESTful Web Services (44讲)
徐昊 · TDD 项目实战 70 讲
15
15
1.0x
00:00/00:00
登录|注册

14|DI Container(2):如何通过Sad Path为容器增加功能?

你好,我是徐昊。今天我们将继续使用 TDD 的方式来实现注入依赖容器。

回顾代码与任务列表

到目前为止,我们的代码是这样的:
package geektime.tdd.di;
import jakarta.inject.Provider;
import java.util.HashMap;
import java.util.Map;
public class Context {
private Map<Class<?>, Provider<?>> providers = new HashMap<>();
public <ComponentType> void bind(Class<ComponentType> type, ComponentType instance) {
providers.put(type, (Provider<ComponentType>) () -> instance);
}
public <ComponentType, ComponentImplementation extends ComponentType>
void bind(Class<ComponentType> type, Class<ComponentImplementation> implementation) {
providers.put(type, (Provider<ComponentType>) () -> {
try {
return (ComponentType) implementation.getConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
public <ComponentType> ComponentType get(Class<ComponentType> type) {
return (ComponentType) providers.get(type).get();
}
}
任务列表状态为:
无需构造的组件——组件实例
如果注册的组件不可实例化,则抛出异常
抽象类
接口
构造函数注入
无依赖的组件应该通过默认构造函数生成组件实例
有依赖的组件,通过 Inject 标注的构造函数生成组件实例
如果所依赖的组件也存在依赖,那么需要对所依赖的组件也完成依赖注入
如果组件有多于一个 Inject 标注的构造函数,则抛出异常
如果组件需要的依赖不存在,则抛出异常
如果组件间存在循环依赖,则抛出异常
字段注入
通过 Inject 标注将字段声明为依赖组件
如果组件需要的依赖不存在,则抛出异常
如果字段为 final 则抛出异常
如果组件间存在循环依赖,则抛出异常
方法注入
通过 Inject 标注的方法,其参数为依赖组件
通过 Inject 标注的无参数方法,会被调用
按照子类中的规则,覆盖父类中的 Inject 方法
如果组件需要的依赖不存在,则抛出异常
如果方法定义类型参数,则抛出异常
如果组件间存在循环依赖,则抛出异常
对 Provider 类型的依赖
注入构造函数中可以声明对于 Provider 的依赖
注入字段中可以声明对于 Provider 的依赖
注入方法中可声明对于 Provider 的依赖
自定义 Qualifier 的依赖
注册组件时,可额外指定 Qualifier
注册组件时,可从类对象上提取 Qualifier
寻找依赖时,需同时满足类型与自定义 Qualifier 标注
支持默认 Qualifier——Named
Singleton 生命周期
注册组件时,可额外指定是否为 Singleton
注册组件时,可从类对象上提取 Singleton 标注
对于包含 Singleton 标注的组件,在容器范围内提供唯一实例
容器组件默认不是 Single 生命周期
自定义 Scope 标注
可向容器注册自定义 Scope 标注的回调
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文介绍了如何通过Sad Path为DI容器增加功能。作者使用TDD的方式来实现注入依赖容器,并回顾了已有的代码和任务列表。任务列表包括处理无法实例化的组件、抽象类、接口、构造函数注入、字段注入、方法注入、对Provider类型的依赖、自定义Qualifier的依赖、Singleton生命周期、自定义Scope标注等功能。文章还提出了一个思考题,即下一步如何重构已有代码。通过本文,读者可以了解DI容器的功能扩展和TDD的实践方法。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《徐昊 · TDD 项目实战 70 讲》
新⼈⾸单¥98
立即购买
登录 后留言

全部留言(2)

  • 最新
  • 精选
  • JC
    第二段视频最后,是不是用 Stream.noneMatch 语义上更好些
    2022-05-01
    5
  • 肖韬
    老师,第一段视频中,按照您的 test case,我觉得应该报错。我自己写了相同的代码,确实报错了,但是您的测试用例却没报错,对此百思不得其解。 在 should_bind_type_to_a_class_with_inject_constructor 中,测试用例是这样的: Dependency dependency = new Dependency() {}; context.bind(Component.class, ComponentWithInjectConstructor.class); context.bind(Dependency.class, dependency); 在 Context#bind(Component.class, ComponentWithInjectConstructor.class) 的实现代码中,会根据依赖类型 Dependency.class,要求context中返回它的一个实例。 但是很明显,在测试用例调用 context.bind(Component.class, ComponentWithInjectConstructor.class) 时,dependency 实例此时还不在容器中。所以这里应该报错,但是视频中却没有报错。请老师解答。
    2023-02-12归属地:江苏
    1
收起评论
显示
设置
留言
2
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部