【JavaEE&Spring】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的存储

两种类型的注解

  1. 类注解:@Controller、@Service、@Repository、@Component、@Configuration
  2. ⽅法注解:@Bean

bean 的命名规则

  • bean名称以⼩写字⺟开头,然后使⽤驼峰式⼤⼩写.
  • 当有多个字符并且第⼀个和第⼆个字符都是⼤写时, 将保留原始的⼤⼩写

bean 的获取

  • 获取bean对象, 是⽗类BeanFactory提供的功能
  • ApplicationContext VS BeanFactory
    • 继承关系和功能方面来说: Spring 容器有两个顶级的接口: BeanFactory 和 ApplicationContext。其中 BeanFactory 提供了 基础的访问容器的能力, 而ApplicationContext 属于 BeanFactory 的子类, 它除了继承了 BeanFactory 的所有功能之外, 它还有独特的特性,还添加了对国际化支持、资源访问支持、资源访问支持、以及事件传播等方面的支持;
    • 从性能方面:ApplicationContext 是一次性加载并初始化所有的 Bean 对象,而BeanFactory 是需要哪个才去加载哪个,因此更加轻量

为什么要这么多类注解?

  • @Controller:控制层, 接收请求, 对请求进⾏处理, 并进⾏响应.
  • @Servie:业务逻辑层, 处理具体的业务逻辑.
  • @Repository:数据访问层,也称为持久层. 负责数据访问操作
  • @Configuration:配置层. 处理项⽬中的⼀些配置信息.

在这里插入图片描述

方法注解 @Bean

只使用类注解, 存在两个问题:

  1. 使⽤外部包⾥的类, 没办法添加类注解
  2. ⼀个类, 需要多个对象, ⽐如多个数据源

这种场景, 我们就需要使⽤⽅法注解 @Bean

注意:

  • ⽅法注解要配合类注解使⽤
  • 注解@Bean存的对象类型是方法返回的类型, 命名是方法名字
  • @Bean 可以进行重命名
  • @ComponentScan 指定 Spring 扫描的路径, 默认扫描的范围是SpringBoot启动类所在包及其⼦包

2.1 DI 注入 @Autowired

三种方法

  1. 属性注⼊(Field Injection)
  2. 构造⽅法注⼊(Constructor Injection)
  3. Setter 注⼊(Setter Injection)

三种注⼊优缺点分析

  • 属性注入:
    • 优点: 简洁, 使用方便
    • 缺点
      1. 只能用于 IoC 容器, 如果是非 IoC容器不可用, 并且只有在使用的时候才会出现 NPE(空指针异常)
      2. 不能注入一个 final 修饰的属性
  • 构造函数注入
    • 优点
      1. 可以注入 final 修饰的属性
      2. 注入的对象不会被修改
      3. 依赖对象在使用前一定会被完全初始化, 因为依赖是在类的构造方法中执行的, 而构造方法是在类加载阶段就会被执行的方法
      4. 通用性好, 构造方法是 jdk 支持的, 所以更换任何框架, 他都是适用的
    • 缺点:
      • 注入多个对象时候, 代码会比较繁琐
  • Setter注⼊
    • 优点: ⽅便在类实例之后, 重新对该对象进⾏配置或者注⼊
    • 缺点:
      1. 不能注⼊⼀个Final修饰的属性
      2. 注⼊对象可能会被改变, 因为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。

3. 练习代码自取

代码提取