IoC
IoC
IoC 思想
Spring IoC 的了解
IoC(Inversion of Control:控制反转) 是一种设计思想,而不是一个具体的技术实现。IoC 的思想就是将原本在程序中手动创建对象的控制权,交由 Spring 框架来管理。不过, IoC 并非 Spring 特有,在其他语言中也有应用。IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个 Map(key,value),Map 中存放的是各种对象。
IoC 最常见以及最合理的实现方式叫做依赖注入(Dependency Injection,简称 DI)。
为什么叫控制反转?
- 控制 :指的是对象创建(实例化、管理)的权力
- 反转 :控制权交给外部环境(Spring 框架、IoC 容器)
Bean
将一个类声明为 Bean 的注解有哪些?
@Component
:通用的注解,可标注任意类为Spring
组件。如果一个 Bean 不知道属于哪个层,可以使用@Component
注解标注。@Repository
: 对应持久层即 Dao 层,主要用于数据库相关操作。@Service
: 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。@Controller
: 对应 Spring MVC 控制层,主要用户接受用户请求并调用 Service 层返回数据给前端页面。
@Component 和 @Bean 的区别是什么?
@Component
注解作用于类,而@Bean
注解作用于方法。@Component
通常是通过类路径扫描来自动侦测以及自动装配到 Spring 容器中(我们可以使用@ComponentScan
注解定义要扫描的路径从中找出标识了需要装配的类自动装配到 Spring 的 bean 容器中)。@Bean
注解通常是我们在标有该注解的方法中定义产生这个 bean,@Bean
告诉了 Spring 这是某个类的实例,当我需要用它的时候还给我。@Bean
注解比@Component
注解的自定义性更强,而且很多地方我们只能通过@Bean
注解来注册 bean。比如当我们引用第三方库中的类需要装配到Spring
容器时,则只能通过@Bean
来实现。通常是某个框架的 Config 类里面生命待注入的内容
注入 Bean 的注解有哪些?
@Component
@Resource
@Inject
Autowired
属于 Spring 内置的注解,默认的注入方式为byType
(根据类型进行匹配),也就是说会优先根据接口类型去匹配并注入 Bean (接口的实现类)。
这会有什么问题呢? 当一个接口存在多个实现类的话,byType
这种方式就无法正确注入对象了,因为这个时候 Spring 会同时找到多个满足条件的选择,默认情况下它自己不知道选择哪一个。
对于Autowired
,还是建议通过结合 @Qualifier
注解来显式指定名称而不是依赖变量的名称。
这种情况下,注入方式会变为 byName
(根据名称进行匹配),这个名称通常就是类名(首字母小写)。就比如说下面代码中的 smsService
就是我这里所说的名称,这样应该比较好理解了吧。
简单总结一下:
@Autowired
是 Spring 提供的注解,@Resource
是 JDK 提供的注解。Autowired
默认的注入方式为byType
(根据类型进行匹配),@Resource
默认注入方式为byName
(根据名称进行匹配)。- 当一个接口存在多个实现类的情况下,
@Autowired
和@Resource
都需要通过名称才能正确匹配到对应的 Bean。Autowired
可以通过@Qualifier
注解来显式指定名称,@Resource
可以通过name
属性来显式指定名称。
单例 Bean 的线程安全问题了解吗?
大部分时候我们并没有在项目中使用多线程,所以很少有人会关注这个问题。单例 Bean 存在线程问题,主要是因为当多个线程操作同一个对象的时候是存在资源竞争的。
常见的有两种解决办法:
- 在 Bean 中尽量避免定义可变的成员变量。
- 在类中定义一个
ThreadLocal
成员变量,将需要的可变成员变量保存在ThreadLocal
中(推荐的一种方式)。
不过,大部分 Bean 实际都是无状态(没有实例变量)的(比如 Dao、Service),这种情况下, Bean 是线程安全的。
源码
工厂模式里面,单例注册表(懒加载)
https://www.cnblogs.com/nickup/p/9800120.html?ivk_sa=1024320u
https://www.likecs.com/show-308120142.html
自动装配
在 Spring 框架中共有 5 种自动装配,让我们逐一分析。
- no:这是 Spring 框架的默认设置,在该设置下自动装配是关闭的,开发者需要自行在 bean 定义 中用标签明确的设置依赖关系。
- byName:该选项可以根据 bean 名称设置依赖关系。当向一个 bean 中自动装配一个属性时,容 器将根据 bean 的名称自动在在配置文件中查询一个匹配的 bean。如果找到的话,就装配这个属 性,如果没找到的话就报错。
- byType:该选项可以根据 bean 类型设置依赖关系。当向一个 bean 中自动装配一个属性时,容器 将根据 bean 的类型自动在在配置文件中查询一个匹配的 bean。如果找到的话,就装配这个属性, 如果没找到的话就报错。
- constructor:造器的自动装配和 byType 模式类似,但是仅仅适用于与有构造器相同参数的 bean,如果在容器中没有找到与构造器参数类型一致的 bean,那么将会抛出异常。
- autodetect:该模式自动探测使用构造器自动装配或者 byType 自动装配。首先,首先会尝试找合 适的带参数的构造器,如果找到的话就是用构造器自动装配,如果在 bean 内部没有找到相应的构 造器或者是无参构造器,容器就会自动选择 byTpe 的自动装配方式。
IoC 容器
BeanFactory 和 ApplicationContext 的区别
BeanFactory 接口提供了一个先进的配置机制,使得任何类型的对象的配置成为可能。 ApplicationContex 接口对 BeanFactory(是一个子接口)进行了扩展,在 BeanFactory 的基础上添加了其他功能,比如与 Spring 的 AOP 更容易集成,也提供了处理 message resource 的机制(用于国际化)、事件传播以及应用层的特别配置,比如针对 Web 应用的 WebApplicationContext。
org.springframework.beans.factory.BeanFactory 是 Spring IoC 容器的具体实现, 用来包装和管理前面提到的各种 bean。BeanFactory 接口是 Spring IoC 容器的核心接口。
BeanFactory 可以理解为含有 bean 集合的工厂类。BeanFactory 包含了种 bean 的定义,以便在接收到客户端请求时将对应的 bean 实例化。
BeanFactory 还能在实例化对象的时生成协作类之间的关系。此举将 bean 自身与 bean 客户端的配置中解放出来。BeanFactory 还包含 了 bean 生命周期的控制,调用客户端的初始化方法 (initialization methods)和销毁方法(destruction methods)。
从表面上看,application context 如同 bean factory 一样具有 bean 定义、bean 关联关系的设 置,根据请求分发 bean 的功能。但 applicationcontext 在此基础上还提供了其他的功能。
- 提供了支持国际化的文本消息
- 统一的资源文件读取方式
- 已在监听器中注册的 bean 的事件,Event
Spring 的核心容器有两种:
BeanFactory:IOC 容器基本实现,是 Spring 内部的使用接口,不提供开发人员进行使用加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象
ApplicationContext(这个接口经常使用):BeanFactory 接口的子接口,提供更多更强大的功能,一般由开发人员进行使用,加载配置文件时候就会把在配置文件对象进行创建。所以我们着重了解下这个接口。
而创建 ApplicationContext 接口实例通常采用两种方法,
一个是通过 ClassPathXmlApplicationContext 创建
一个则是通 FileSystemXmlApplicationContext 创建
这种方法如果在参数中写的不是绝对路径,那么调用的时候会默认绝对路径来找,这会导致程序的灵活性变差,所以这个一般不推荐使用