一点背景
Inversion of Control:控制反转
IoC是一种设计思想、一种规范,任何容器技术都可以自由选择是否遵循
IoC通过控制反转的方式,屏蔽掉构造组件的细节,核心策略为依赖注入
、依赖查找
IoC的设计目的
- 实现与业务之间解耦
- 专注于模块设计
- 使用契约而非猜测具体实现的方式去完成一个模块
- 解决依赖取消时的副作用
依赖处理
- 依赖查找-Dependency Lookup:主动获取依赖,代表容器
EJB
- 依赖注入-Dependency Injection:被动获取依赖,容器代表
Spring
两种依赖处理对比
类型 | 方式 | 便利性 | 侵入性 | Api依赖性 | 可读性 |
---|---|---|---|---|---|
依赖查找 | 主动获取 | 相对繁琐 | 高 | 依赖容器API | 高 |
依赖注入 | 被动获取 | 相对便利 | 低 | 不依赖容器API | 低 |
各有优势,根据项目具体需求使用,不可一昧否定
生命周期管理
- 容器
- 资源(Bean 或其他资源)
配置
- 容器
- 资源(Bean 或其他资源)
- 外部化配置
由上述定义,可以看到一个熟悉的名词Dependency Injection
,也就是常说的DI
。
所以,
Spring不等于IoC,Spring是IoC众多实现者中的一个,在Spring出现之前就有了EJB等等实现了IoC的框架
Spring 做为IoC有什么优势
典型的IoC管理,提供依赖查找和依赖注入功能
AOP抽象
事务抽象
事件机制
SPI扩展
强大的第三方整合
易测试性
更好的面向对象
Injection Using Construction Or Setting
Construction Injection:构造器注入
- 被注入的Bean本身必须是成熟态,否则会出现循环依赖问题
- 不可以为空的属性
- 适用于Bean声明周期中不变的属性
Setting Injection:Set方法注入
- 可以为空的属性
- 适用于Bean声明周期中可变的属性
- 无法确定设置属性的顺序
循环依赖
使用Construction会出现循环依赖,这不一定代表着构造器注入不好。
相反的,如果出现循环依赖,那说明代码设计上就有缺陷,没有达到Bean之间的解耦
使用Setting不会出现循环依赖,并且操作简单,但会导致Bean的属性有可能被改变,需要注意自己的业务代码
问题:如何实现或利用IoC框架来实现业务逻辑、简化开发?
设计模式
DefaultListableBeanFactory 实现的设计模式
- 抽象工厂(BeanFactory 接口实现)
- 组合模式(组合 AutowireCandidateResolver 等实例)
- 单例模式(Bean Scope)
- 原型模式(Bean Scope)
- 模板模式(模板方法定义:AbstractBeanFactory)
- 适配器模式(适配 BeanDefinitionRegistry 接口)
- 策略模式(Bean 实例化)
- 代理模式(ObjectProvider 代理依赖查找)
编程模型
- Configurable模式(可写模型)