【JavaEE&Spring】Spring IoC&DI
Spring IoC& DI
1. IoC
- Spring 是包含了众多⼯具⽅法的 IoC 容器
IoC: Inversion of Control (控制反转), 也就是说 Spring 是⼀个"控制反转"的容器。
- 什么是控制反转呢? 也就是控制权反转; 什么的控制权发生了反转? 获取依赖对象的过程被反转了
- 也就是说, 当需要某个对象时, 传统开发模式中需要自己通过 new 创建对象, 现在不需要再进行创建, 把创建对象的任务交给容器, 程序中需要依赖注入 (Dependency Injection, DI) 就可以了
- 这个容器称为; IoC 容器, Spring 是一个IoC 容器, 所以有时Spring也称为 Spring 容器
DI 介绍
IoC 是⼀种思想,也是"⽬标", ⽽思想只是⼀种指导原则,最终还是要有可⾏的落地⽅案,⽽ DI 就属于具体的实现。所以也可以说, DI 是IoC的⼀种实现.
2. IoC & DI 使⽤
Spring 把存储在容器中的对象称为 bean
2.1 Bean的存储
两种类型的注解
- 类注解:@Controller、@Service、@Repository、@Component、@Configuration
- ⽅法注解:@Bean
bean 的命名规则
- bean名称以⼩写字⺟开头,然后使⽤驼峰式⼤⼩写.
- 当有多个字符并且第⼀个和第⼆个字符都是⼤写时, 将保留原始的⼤⼩写
bean 的获取
- 获取bean对象, 是⽗类BeanFactory提供的功能
- ApplicationContext VS BeanFactory
- 继承关系和功能方面来说: Spring 容器有两个顶级的接口: BeanFactory 和 ApplicationContext。其中 BeanFactory 提供了 基础的访问容器的能力, 而ApplicationContext 属于 BeanFactory 的子类, 它除了继承了 BeanFactory 的所有功能之外, 它还有独特的特性,还添加了对国际化支持、资源访问支持、资源访问支持、以及事件传播等方面的支持;
- 从性能方面:ApplicationContext 是一次性加载并初始化所有的 Bean 对象,而BeanFactory 是需要哪个才去加载哪个,因此更加轻量
为什么要这么多类注解?
- @Controller:控制层, 接收请求, 对请求进⾏处理, 并进⾏响应.
- @Servie:业务逻辑层, 处理具体的业务逻辑.
- @Repository:数据访问层,也称为持久层. 负责数据访问操作
- @Configuration:配置层. 处理项⽬中的⼀些配置信息.
方法注解 @Bean
只使用类注解, 存在两个问题:
- 使⽤外部包⾥的类, 没办法添加类注解
- ⼀个类, 需要多个对象, ⽐如多个数据源
这种场景, 我们就需要使⽤⽅法注解 @Bean
注意:
- ⽅法注解要配合类注解使⽤
- 注解@Bean存的对象类型是方法返回的类型, 命名是方法名字
- @Bean 可以进行重命名
- @ComponentScan 指定 Spring 扫描的路径, 默认扫描的范围是SpringBoot启动类所在包及其⼦包
2.1 DI 注入 @Autowired
三种方法
- 属性注⼊(Field Injection)
- 构造⽅法注⼊(Constructor Injection)
- Setter 注⼊(Setter Injection)
三种注⼊优缺点分析
- 属性注入:
- 优点: 简洁, 使用方便
- 缺点
- 只能用于 IoC 容器, 如果是非 IoC容器不可用, 并且只有在使用的时候才会出现 NPE(空指针异常)
- 不能注入一个 final 修饰的属性
- 构造函数注入
- 优点
- 可以注入 final 修饰的属性
- 注入的对象不会被修改
- 依赖对象在使用前一定会被完全初始化, 因为依赖是在类的构造方法中执行的, 而构造方法是在类加载阶段就会被执行的方法
- 通用性好, 构造方法是 jdk 支持的, 所以更换任何框架, 他都是适用的
- 缺点:
- 注入多个对象时候, 代码会比较繁琐
- 优点
- Setter注⼊
- 优点: ⽅便在类实例之后, 重新对该对象进⾏配置或者注⼊
- 缺点:
- 不能注⼊⼀个Final修饰的属性
- 注⼊对象可能会被改变, 因为setter⽅法可能会被多次调⽤, 就有被修改的⻛险
@Autowired存在问题
当同⼀类型存在多个bean时, 使⽤@Autowired会存在问题
解决方法:
- @Primary
- 使⽤@Primary注解:当存在多个相同类型的Bean注⼊时,加上@Primary注解,来确定默认的实现。
- @Qualifier
- 使⽤@Qualifier注解:指定当前要注⼊的bean对象。 在@Qualifier的value属性中,指定注⼊的bean的名称。
- @Qualifier注解不能单独使⽤,必须配合@Autowired使⽤
- @Resource
- 使⽤@Resource注解:是按照bean的名称进⾏注⼊。通过name属性指定要注⼊的bean的名称。
@Autowird 与 @Resource的区别
- @Autowired 是spring框架提供的注解,⽽@Resource是JDK提供的注解
- @Autowired 默认是按照类型注⼊,⽽@Resource是按照名称注⼊
- 使⽤时设置的参数不同:相⽐于 @Autowired 来说,@Resource ⽀持更多的参数设置,例如name 设置,根据名称获取 Bean。