目录
1.什么是spring IOC?
spring容器主要是对IOC设计模式的实现。主要是使用容器来
统一管理
Bean对象,及管理对象之间的
依赖关系。
在Spring中,我们基本不需要 new 一个类,这些都是让 Spring 去做的。Spring 启动时会把所需的类实例化成对象,如果需要依赖,则先实例化依赖,然后实例化当前类。因为依赖必须通过构建函数传入,所以实例化时,当前类就会接收并保存所有依赖的对象。
这一步也就是所谓的
依赖注入
。
在 Spring 中,类的实例化、依赖的实例化、依赖的传入都交由 Spring Bean 容器控制,而不是用new方式实例化对象、通过非构造函数方法传入依赖等常规方式。实质的控制权已经交由程序管理,而不是程序员管理,所以叫做
控制反转
。
Spring提供了一个容器,称为IOC容器,用来充当IOC思想中的
外部
IOC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IOC容器中统称为
Bean
。
2.IOC/DI的理解
IoC 是 Inversion of Control 的缩写,翻译成中文是“控制反转”的意思,
它不是一个具体的技术,而是一个实现对象解耦的思想。
要解释什么是解耦?就要了解什么是耦合,所谓的**耦合是指:两个或两个以上对象存在依赖,当一方修改之后会影响另一方,那么就说这些对象间存在耦合。**而解耦就是解除两个或两个以上对象,修改之后影响另一方的问题。
DI 是 Dependency Injection 的缩写,翻译成中文是“依赖注入”的意思。
依赖注入不是一种设计实现,而是一种具体的技术
,它是
在 IoC 容器运行期间,动态地将某个依赖对象注入到当前对象的技术就叫做 DI(依赖注入)
。
举个例子:A 类在使用 B 类时,就是通过构造方法将依赖对象 B 引入的,这种实现方法就可以看作是
通过构造方法
实现依赖注入的手段,具体代码如下
class A {
// 先定义一个需要依赖的 B 对象
private B b;
// 通过构造方法实现赋值
public A(B b) {
this.b = b;
}
public void init() {
// 调用 B 类中的 init 方法
b.init();
}
}
从上面的内容中我们可以看出,IoC 和 DI 虽然定义不同,但它们所做的事情都是一样的,都是用来实现对象解耦的,而二者又有所不同:
IoC 是一种设计思想,而 DI 是一种具体的实现技术
。
给大家举个例子很快就可以更清晰:比如博主今天心情比较好,下午想出去吃一顿大餐,那么“想吃一顿大餐”就是一种思想,就是
IOC
但什么样的大餐才是好吃的呢?羊肉火锅还是烧烤啤酒?具体吃什么是
DI
。
因此“博主今天心情比较好,想出去吃大餐”是一种思想、是 IOC,而吃一顿火锅而非烧烤就是具体的实现、是 DI。
3.Bean作用域
Bean 的作用域是指 Bean 在 Spring 整个框架中的某种行为模式。比如 singleton 单例作用域,就表示 Bean 在整个 Spring 中只有一份,它是全局共享的,当有人修改了这个值之后,那么另一个人读取到的就是被修改后的值
。 举个例子,比如我们在 Spring 中定义了一个单例的 Bean 对象 user(默认作用域为单例),具体实现代码如下:
@Component
public class UserBean {
@Bean
public User user() {
User user = new User();
user.setId(1);
user.setName("Java"); // 此行为重点:用户名称为 Java
return user;
}
}
然后,在 A 类中使用并修改了 user 对象,具体实现代码如下:
@Controller
public class AController {
@Autowired
private User user;
public User getUser() {
User user = user;
user.setName("MySQL"); // 此行为重点:将 user 名称修改了
return user;
}
}
最后,在 B 类中也使用了 user 对象,具体实现代码如下:
@Controller
public class BController {
@Autowired
private User user;
public User getUser() {
User user = user;
return user;
}
}
此时我们访问 B 对象中的 getUser 方法,就会发现此时的用户名为 A 类中修改的“MySQL”,而非原来的“Java”,这就说明 Bean 对象 user 默认就是单例的作用域。如果有任何地方修改了这个单例对象,那么其他类再调用就会得到一个修改后的值。
—————–作用域分类————————————————————-
在 Spring 中,Bean 的常见作用域有以下 5 种:
- singleton:单例作用域;
- prototype:原型作用域(多例作用域);
- request:请求作用域;
- session:会话作用域;
- application:全局作用域。
注意:后 3 种作用域,只适用于 Spring MVC 框架。
singleton:该作用域下的 Bean 在 IoC 容器中只存在一个实例:获取 Bean(即通过 applicationContext.getBean等方法获取)及装配 Bean(即通过 @Autowired 注入)都是同一个对象。
prototype:每次对该作用域下的 Bean 的请求都会创建新的实例:获取 Bean(即通过 applicationContext.getBean 等方法获取)及装配 Bean(即通过 @Autowired 注入)都是新的对象实例。
request:每次 Http 请求会创建新的 Bean 实例,类似于 prototype。
session:在一个 Http Session 中,定义一个 Bean 实例。
application:在一个 Http Servlet Context 中,定义一个 Bean 实例。
4.Bean生命周期
Spring 中 Bean 的生命周期是指:Bean 在 Spring(IoC)中从创建到销毁的整个过程。
Spring 中 Bean 的生命周期主要包含以下 5 部分:
- 实例化:为 Bean 分配内存空间;
- 设置属性:将当前类依赖的 Bean 属性,进行注入和装配;
-
初始化:
- 执行初始化的前置方法;
- 执行初始化方法;
- 执行初始化的后置方法。
- 使用 Bean:在程序中使用 Bean 对象;
- 销毁 Bean:将 Bean 对象进行销毁操作。
以上生命周期中,需要注意的是:
“实例化”和“初始化”是两个完全不同的过程,实例化只是给 Bean 分配了内存空间,而初始化则是将程序的执行权,从系统级别转换到用户级别,并开始执行用户添加的业务代码
。
5.上篇文章遗漏总结
1.@Autowired 和 @Resource 注解的区别
(1)@Autowired是spring框架提供的注解,而@Resource是JDK提供的注解
(2)@Autowired必须在spring框架中使用,否则会报错。而@Resource可以不在spring框架中使用
(3)显示指定引用某个Bean,使用方式不同:@Resource(name=“xxx”),@Autowired 结合@Qualifier
2.同一个类型的Bean,如何正确的注入到某个属性