持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第14天,点击查看活动详情
Bean 的介绍
Spring Bean 是 Spring IOC 容器在运行时管理的对象。Spring Bean 是 Spring 程序中不可或缺的一部分。如果将 Spring 看做一个大型工厂的话,那么 Bean 就是这个工厂中的产品。如果要想让这个工厂来生产和管理 Bean ,就需要在配置文件中告诉它需要哪些 Bean,以及如何组装这些 Bean。这里所说的 Bean 本质就是 Java 中的类。
下面是配置文件中一个 bean 标签中所涉及到的属性,如下表所示 :
| 属性 | 描述 |
|---|---|
| class | 这个属性是强制性的,并且指定用来创建 bean 的 bean 类。 |
| id | 这个属性指定唯一的 bean 标识符。在基于 XML 的配置元数据中,你可以使用 id 或 name 属性来指定 bean 标识符。 |
| scope | 这个属性指定由特定的 bean 定义创建的对象的作用域。 |
| constructor-arg | 它是用来注入依赖关系的 |
| properties | 它是用来注入依赖关系的 |
| autowiring mode | 它是用来注入依赖关系的 |
| lazy-initialization mode | 延迟初始化的 bean 告诉 IoC 容器在它第一次被请求时,而不是在启动时去创建一个 bean 实例。 |
| initialization 方法 | 在 bean 的所有必需的属性被容器设置之后,调用回调方法。 |
| destruction 方法 | 当包含该 bean 的容器被销毁时,使用回调方法。 |
Bean 的作用域
默认情况下,Spring 只会为 IOC 容器中声明的 Bean 创建一个实例,并且这个实例是在整个 IOC 容器范围内都能共享的,所以后续的对象通过 getBean() 方法调用和 Bean 的引用都将返回这个唯一的实例。假如我们现在需要不同的实例 Bean ,我们该如何处理呢?
这就设计到 Bean 的作用域了。还记得前面加粗的属性 scope 吗,它就是用来指定 Bean 的作用域的。默认情况下,scope 的值为 Singleton,表示单例。在 Spring 中提供了 6 种作用域,如下表所示 :
| 作用域 | 描述 |
|---|---|
| singleton | 单例模式(默认) ,实例化的 Bean 在整个 Spring IOC 容器生命周期中只创建一次,单个 Bean 被绑定到单个对象实例。 |
| prototype | 多例模式,Spring IOC 容器初始化时不创建 Bean 的实例,而是在通过 getBean 获取 Bean 时才会创建一个新的 Bean 实例并返回, 单个 Bean 定义可以被绑定到多个对象实例。 |
| request | 单个 Bean 定义被绑定到单个的 HTTP 请求生命周期。就是每一个 HTTP 请求都有属于他自己的单独实例创建,这个只能在 web-aware Spring ApplicationContext 中有效。 |
| session | 单个 Bean 定义会被绑定到 HTTP Session 的生命周期中,这个只能在 web-aware Spring ApplicationContext 中有效。 |
| application | 单个 Bean 定义会被绑定到 ServletContext 的生命周期中,这个只能在 WebApplicationContext 中有效。 |
| websocket | 单个 Bean 的定义会被绑定到 WebSocket 的生命周期中,这个只能在 WebApplicationContext 中有效。 |
上述几种作用域,在实际开发中 singleton 和 prototype 值最常用的两种。
1. singleton
a. 在 applicationContextByName.xml 配置文件中配置 Employee 这个 JaveBean,并指定 scope="singleton",如下所示
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="employee" class="com.yamiya.pojo.Employee" scope="singleton">
</bean>
</beans>
说明:scope 是用来设置作用域的,如果不写,默认也是 singleton,表示单例。
b.在测试类 SpringTest 中添加测试方法,代码如下:
@Test
public void test1() throws IOException{
Employee e1 = context.getBean("employee",Employee.class);
Employee e2 = context.getBean("employee",Employee.class);
Employee e3 = context.getBean("employee",Employee.class);
System.out.println(e1);
System.out.println(e2);
System.out.println(e3);
}
分析:观察上图可以发现,虽然调用三次 getBean 方法获取了三个实例对象,但是三个实例对象的地址都是一样的,也就是说这三个实例对象实际是同一个实例对象。这就是单例模式(singleton),它是在 Bean 整个生命周期内只被创建一次,创建好了之后,它在整个 IOC 容器中是被共享的。
2. prototype
a. 将配置文件中的作用域改为 scope="prototype",代码如下
b. 测试代码不变,直接点击进行测试,结果如下图所示
分析:观察上图可以发现,调用三次 getBean 方法获取了三个实例对象,三个实例对象的地址都不一样,也就是说分别创建了三个实例对象。这就是多例模式(prototype),实例对象是在调用 getBean 方法时才会被创建,每调用一次 getBean 方法获取的实例化对象都不一样。
总结
Spring Bean 作用域,重点是以下两种作用域:
-
singleton:表示单例(默认)模式实例化的
Bean在整个Spring IOC容器生命周期中只创建一次,单个Bean被绑定到单个对象实例 -
prototype:表示多例模式Spring IOC容器初始化时不创建Bean的实例,而是在通过getBean获取Bean时才会创建一个新的Bean实例并返回, 单个Bean定义可以被绑定到多个对象实例。