一、Bean的作用域
我们可以在 元素中添加 scope 属性来配置 Spring Bean 的作用范围
Spring 5 共提供了 6 种 scope 作用域,如下表。
| 作用域 (Scope) | 描述 | 创建时机 | 适用场景 |
|---|---|---|---|
singleton |
默认值 ,在整个 Spring IOC 容器中,该 Bean 只有一个实例。(单例模式) | 容器启动时创建 | 无状态的 Bean,如 Service、DAO、工具类 |
prototype |
每次从容器中获取 Bean (getBean()) 时,都会创建一个新的实例。(原型模式) |
每次调用 getBean() 时创建 |
有状态的 Bean,如购物车、用户会话对象 |
request |
每个 HTTP 请求创建一个新的 Bean 实例,仅在 Web 应用中有效。 | 收到 HTTP 请求时创建 | Web 应用中,每个请求独立的 Bean |
session |
每个 HTTP Session 创建一个新的 Bean 实例,仅在 Web 应用中有效。 | 用户首次访问创建 Session 时创建 | Web 应用中,与用户会话绑定的 Bean |
application |
在整个 Web 应用的生命周期内,只有一个 Bean 实例。 | Web 应用启动时创建 | 与整个 Web 应用共享的 Bean |
websocket |
在一个 WebSocket 的生命周期内,创建一个 Bean 实例。 | WebSocket 连接建立时创建 | WebSocket 应用 |
其中最常用的是 singleton 和 prototype
1.1 singleton
singleton 是 Spring 容器默认的作用域。当 Bean 的作用域为 singleton 时,Spring IOC 容器中只会存在一个共享的 Bean 实例。

1.2 prototype
如果一个 Bean 定义的作用域为 prototype,那么这个 Bean 就被称为 prototype bean。对于
prototype bean 来说,Spring 容器会在每次请求该 Bean 时,都创建一个新的 Bean 实例。
在 Spring 配置文件中,可以使用 元素的 scope 属性将 Bean 的作用域定义成 prototype,其
配置方式如下所示:

二、Bean的生命周期(面试当中一定会有)
2.1 Spring Bean 的完整生命周期
在传统的 Java 应用中,Bean 的生命周期很简单,使用 Java 关键字 new 进行 Bean 的实例化后,这个Bean 就可以使用了。一旦这个 Bean 长期不被使用,Java 自动进行垃圾回收。
相比之下,Spring 中 Bean 的生命周期较复杂,Spring IOC容器可以管理Bean的生命周期,Spring允许在Bean生命周期的特定点执行定制的任务,大致可以分为以下 阶段:
1、bean对象创建:IOC容器在初始化时,通过反射机制调用无参构造器创建bean的实例;
2、给bean对象设置属性:通过反射机制调用setter方法实现属性注入;
3、bean对象初始化之前操作:由 bean 的后置处理器负责;
4、bean对象初始化:需在配置 bean 时指定初始化方法;
5、bean对象初始化之后操作:由 bean 的后置处理器负责
6、bean对象就绪可以使用
7、bean 对象销毁:需在配置 bean 时指定销毁方法
8、IOC 容器关闭
代码演示:
Dog.java:
public class Dog {
private String name;
private String owner;
private int age;
public Dog() {
System.out.println("Dog对象被创建...");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("调用setName方法....");
this.name = name;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
System.out.println("调用setOwner方法....");
this.owner = owner;
}
public int getAge() {
return age;
}
public void setAge(int age) {
System.out.println("调用setAge方法....");
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", owner='" + owner + '\'' +
", age=" + age +
'}';
}
}
applicationContext.xml:
<bean id="dog" class="com.gs.bean.Dog" p:name="旺财" p:owner="小明" p:age="5"/>
测试:
public class LifeCycleTest {
@Test
public void testLifeCycle() {
System.out.println("-------容器初始化阶段---------");
ClassPathXmlApplicationContext ac = new
ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("-------对象使用阶段---------");
Dog dog = ac.getBean("dog", Dog.class);
System.out.println(dog);
System.out.println("-------容器关闭阶段---------");
//手动关闭容器
ac.close();//ApplicationContext没有close()
}
}
2.2 如何自定义初始化和销毁方法
我们可以在 Spring Bean 生命周期的某个特定时刻,指定一些生命周期回调方法完成一些自定义的操作,对 Bean 的生命周期进行管理。
方式一:通过接口实现,在 Spring Bean 的 Java 类中,通过实现 InitializingBean 和 DisposableBean 接口,指定 Bean 的生命周期回调方法。
方式二:通过 XML 配置实现,在 Spring 的 XML 配置中,通过 `` 元素中的 init-method 和 destory-method 属性,指定 Bean 的生命周期回调方法。
方式三:使用注解实现。
**注意:**如果一个 Bean 中有多种生命周期回调方法时,优先级顺序为:注解 > 接口 > XML 配置。
2.2.1 通过接口实现
我们可以在 Spring Bean 的 Java 类中,通过实现 InitializingBean 和 DisposableBean 接口,指定Bean 的生命周期回调方法。
注意:通常情况下,我们不建议通过这种方式指定生命周期回调方法,这是由于这种方式会导致代码的耦合性过高。

public class Dog implements InitializingBean, DisposableBean{
private String name;
private String owner;
private int age;
public Dog() {
System.out.println("Dog对象被创建...");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("调用setName方法....");
this.name = name;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
System.out.println("调用setOwner方法....");
this.owner = owner;
}
public int getAge() {
return age;
}
public void setAge(int age) {
System.out.println("调用setAge方法....");
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", owner='" + owner + '\'' +
", age=" + age +
'}';
}
/**
* 初始化回调逻辑
*
* @throws Exception
*/
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("调用接口:InitializingBean,方法:afterPropertiesSet,无参数");
}
/**
* 销毁回调逻辑
*
* @throws Exception
*/
@Override
public void destroy() throws Exception {
System.out.println("调用接口:DisposableBean,方法:destroy,无参数");
}
}
2.2.2 通过 XML 配置实现
我们还可以在 Spring 的 XML 配置中,通过 元素中的 init-method 和 destory-method 属性,指定 Bean 的生命周期回调方法。

public class Dog {
private String name;
private String owner;
private int age;
public Dog() {
System.out.println("Dog对象被创建...");
}
//......
}
applicationContext.xml:
<bean id="dog" class="com.qcby.Dog" p:name="admin" p:owner="aaa"
p:age="18" init-method="大阿萨大师"
destroy-method="就打卡大事件"/>

2.2.3 使用 JSR-250 注解实现
使用 @PostConstruct 和 @PreDestroy 注解是现代 Spring 开发中最推荐的方式,它既解耦又简洁。
Java 类:
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class Dog {
// ... 属性和构造函数 ...
@PostConstruct
public void init() {
System.out.println("调用 @PostConstruct 注解的初始化方法");
}
@PreDestroy
public void destroy() {
System.out.println("调用 @PreDestroy 注解的销毁方法");
}
}
XML 配置:
<!-- 需要开启注解支持 -->
<context:annotation-config/>
2.3 Bean的后置处理器
创建后置处理器类:
// 声明一个自定义的bean后置处理器
// 注意:bean后置处理器不是单独针对某一个bean生效,而是针对IOC容器中所有bean都会执行
public class MyBeanProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)throws BeansException {
System.out.println("☆☆☆" + beanName + " = " + bean);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)throws BeansException {
System.out.println("★★★" + beanName + " = " + bean);
return bean;
}
}
把 bean 的后置处理器放入 IOC 容器:
<!-- bean的后置处理器要放入IOC容器才能生效 -->
<bean id="myBeanProcessor" class="com.gs.process.MyBeanProcessor"/>
三、LomLock
既然 javaBean 中 getXxx ()、setXxx () 方法、toString () 方法、构造器都是按照固定格式生成的,那能否由程序自动生成呢?
- 使用 Lombok 注解就可以省略生成 getXxx ()、setXxx () 方法、toString () 方法、构造器等固定格式代码的繁琐操作,提高开发效率。
Lombok 是一个在 java 开发过程中用注解的方式,简化了 JavaBean 的编写,避免了冗余和样板式代码而出现的插件,让编写的类更加简洁。
3.1 Lombok 原理:
Lombok 是将自动生成的代码织入字节码文件中,从而实现:源代码没有,但是字节码文件有 ------ 毕竟我们最终运行的是字节码文件,只要字节码文件中有即可。而这个过程因为要参与源文件编译,所以需要安装 IDEA 插件。
在 IDEA 安装 Lombok 插件:
File → Settings → Plugins → Browse repositories → 搜索 lombok
加入依赖:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
3.2 使用 Lombok 注解:
@Getter/@Setter:自动生成 getter/setter;
@ToString:自动重写 toString () 方法,会印出所有变量;
@EqualsAndHashCode:自动生成 equals (Object other) 和 hashCode () 方法,包括所有非静态变量和非 transient 的变量;
@NoArgsConstructor,@AllArgsConstructor,@RequiredArgsConstructor:这三个很像,都是在自动生成该类的构造器,差别只在生成的构造器的参数不一样而已;
@NoArgsConstructor:生成一个没有参数的构造器
@AllArgsConstructor:生成一个包含所有参数的构造器
@RequiredArgsConstructor:生成一个包含 "特定参数" 的构造器,特定参数指的是那些有加上 final 修饰词的变量;补充一下,如果所有的变量都是正常的,都没有用 final 修饰的话,那就会生成一个没有参数的构造器
@Data:整合包,只要加了 @Data 这个注解,等同于同时加了以下注解 @Getter/@Setter、@ToString、@EqualsAndHashCode、@RequiredArgsConstructor;