24|DI Container(12):如何增补功能?
徐昊
你好,我是徐昊。今天我们继续使用 TDD 的方式实现注入依赖容器。
回顾代码与任务列表
到目前为止,我们的代码是这样的:
任务列表的状态为:
无需构造的组件——组件实例
如果注册的组件不可实例化,则抛出异常
抽象类
接口
构造函数注入
无依赖的组件应该通过默认构造函数生成组件实例
有依赖的组件,通过 Inject 标注的构造函数生成组件实例
如果所依赖的组件也存在依赖,那么需要对所依赖的组件也完成依赖注入
如果组件有多于一个 Inject 标注的构造函数,则抛出异常
如果组件没有 Inject 标注的构造函数,也没有默认构造函数(新增任务)
如果组件需要的依赖不存在,则抛出异常
如果组件间存在循环依赖,则抛出异常
字段注入
通过 Inject 标注将字段声明为依赖组件
如果字段为 final 则抛出异常
依赖中应包含 Inject Field 声明的依赖
方法注入
通过 Inject 标注的方法,其参数为依赖组件
通过 Inject 标注的无参数方法,会被调用
按照子类中的规则,覆盖父类中的 Inject 方法
如果方法定义类型参数,则抛出异常
依赖中应包含 Inject Method 声明的依赖
对 Provider 类型的依赖
从容器中取得组件的 Provider(新增任务)
注入构造函数中可以声明对于 Provider 的依赖
注入字段中可以声明对于 Provider 的依赖
注入方法中可声明对于 Provider 的依赖对 Provider 类型的依赖
可从容器中获取依赖的 Provider(新增任务)
注入构造函数中可以声明对于 Provider 的依赖
注入字段中可以声明对于 Provider 的依赖
注入方法中可声明对于 Provider 的依赖
自定义 Qualifier 的依赖
注册组件时,可额外指定 Qualifier
注册组件时,可从类对象上提取 Qualifier
寻找依赖时,需同时满足类型与自定义 Qualifier 标注
支持默认 Qualifier——Named
Singleton 生命周期
注册组件时,可额外指定是否为 Singleton
注册组件时,可从类对象上提取 Singleton 标注
对于包含 Singleton 标注的组件,在容器范围内提供唯一实例
容器组件默认不是 Single 生命周期
自定义 Scope 标注
可向容器注册自定义 Scope 标注的回调
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
本文介绍了如何使用TDD的方式实现注入依赖容器。通过代码示例展示了如何实现构造函数注入、字段注入和方法注入,并对任务列表进行了详细回顾。文章还提出了一系列思考题,引发读者对遗漏部分的思考。整体而言,本文以实际代码为例,深入浅出地介绍了DI容器的实现方式,适合读者快速了解和掌握相关技术特点。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《徐昊 · TDD 项目实战 70 讲》,新⼈⾸单¥98
《徐昊 · TDD 项目实战 70 讲》,新⼈⾸单¥98
立即购买
登录 后留言
全部留言(4)
- 最新
- 精选
- aoe神奇的方法 static abstract class TypeLiteral<T> { public ParameterizedType getType() { return (ParameterizedType)((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; } } ParameterizedType type = (ParameterizedType) new TypeLiteral<Provider<Component>>() {}.getType(); assertEquals(Provider.class, type.getRawType()); assertEquals(Component.class, type.getActualTypeArguments()[0]);2022-05-062
- 张铁林跟着敲完,都不知道在干啥了,必须要回来多练才清楚2022-05-041
- 蝴蝶15分钟左右,我不明白为啥provider.get(this)能强转成(Provider<Object>)。一个是 ComponentProvider,一个是 Provider,没有继承,没有同名方法,又不是 python 的 ducktype。困惑啊2022-08-29归属地:广东1
- 蝴蝶@Test public void should_retrieve_bind_as_provider() { Component instance = new Component() { }; config.bind(Component.class, instance); Context context = config.getContext(); ParameterizedType type = new TypeLiteral<Provider<Component>>() {}.getType(); Provider<Component> provider = (Provider<Component>) context.get(type).get(); assertSame(provider.get(), instance); } static abstract class TypeLiteral<T> { public ParameterizedType getType() { return (ParameterizedType) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; } } public Optional get(ParameterizedType type) { Class<?> componentClass = (Class<?>) type.getActualTypeArguments()[0]; return Optional.ofNullable(providers.get(componentClass)) .map(provider -> provider.get(this)); } 抛出了异常信息: java.lang.ClassCastException: class xxx.ContainerTest$DependencyInject$2 cannot be cast to class jakarta.inject.Provider (com.coolme.di.ContainerTest$DependencyInject$2 and jakarta.inject.Provider are in unnamed module of loader 'app') 有踩过坑的小伙伴吗?2022-08-29归属地:广东
收起评论