Bean 的作用域和生命周期

1. Bean 的作用域

作用域名称 说明 生效环境
singleton 单例作用域 通用 Spring 环境
prototype 原型作用域(多例作用域) 通用 Spring 环境
request 请求作用域,每一个 HTTP 请求周期内创建新的实例 web 环境
session 会话作用域,每一个 HTTP session 生命周期内,创建新的实例 web 环境
Application 全局作用域,每一个 ServletContext 生命周期内,创建新的实例 web 环境
websocket WebSocket 作用域 web 环境

通过@Scope注解来指定作用域:

Java 复制代码
@Configuration
public class DogConfig {
    @Bean
    public Dog dog() {
        Dog dog = new Dog();
        dog.setName("旺财");
        return dog;
    }

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
    public Dog singleDog() {
        return new Dog();
    }

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public Dog prototypeDog() {
        return new Dog();
    }
}
Java 复制代码
@RestController
@RequestMapping("/scope")
public class ScopeController {
    @Resource(name = "singleDog")
    private Dog singleDog;

    @Resource(name = "prototypeDog")
    private Dog prototypeDog;

    @Autowired
    private ApplicationContext context;
    @RequestMapping("/single")
    public String single() {
        Dog dog = (Dog)context.getBean("singleDog");
        return "注入的对象:" + singleDog.toString() + "," + "从容器中获取的对象:" + dog.toString();
    }
    @RequestMapping("/prototype")
    public String prototype() {
        Dog dog = (Dog)context.getBean("prototypeDog");
        return "注入的对象:" + prototypeDog.toString() + "," + "从容器中获取的对象:" + dog.toString();
    }
}

先来测试单例的:

可以看出,获取的两个对象地址值相同,是同一个对象

再来看多例作用域:

注入的对象是在程序启动前就已经注入进来了,之后再获取都是这个对象,而从容器中获取,每次请求都会再获取一个对象

通过@RequestScope@SessionScope@ApplicationScope可以分别配置相应的作用域

Java 复制代码
@Bean
@RequestScope
public Dog requestScopeDog() {
    return new Dog();
}

@Bean
@SessionScope
public Dog sessionScopeDog() {
    return new Dog();
}

@Bean
@ApplicationScope
public Dog applicationScopeDog() {
    return new Dog();
}

2. Bean 的生命周期

Bean 的生命周期可以分为以下 5 个部分:

  1. 实例化:为 Bean 分配内存空间
  2. 属性赋值:Bean 的注入和装配
  3. 初始化:执行各种通知,执行初始化方法
  4. 使用 Bean
  5. 销毁 Bean

来分析一下源码:

AbstractAutowireCapableBeanFactory类中可以找到 createBean 方法

点进 createBean 方法之后能够看到执行了一个 doCreateBean 方法

再点进这个方法,能够看到实例化 Bean 的一个方法:

然后是属性装配和初始化:

在初始化方法中执行通知方法,和一些处理方法:

相关推荐
Bs_MoneyMagnet13 分钟前
基于springboot+vue的旅游景区点评系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring·旅游
cpp_learner22 分钟前
Qt 5.14.2 x86_64 静态编译 —— 从零搭建完整手册
后端
企业数字化笔记2 小时前
固定资产历史数据怎么导入系统?Excel模板、字段映射和数据校验
android·java·数据库·后端
西瓜太郎12342 小时前
request_id 如何串起请求、路由、计费和日志
后端·python
by组态2 小时前
Ricon组态系统通信配置指南
前端·后端·物联网
sbjdhjd2 小时前
ThinkPHP 5.0.10 缓存写入型 RCE 复盘:从手动搭建、换行绕过到源码单步验证 | 05
java·后端·安全·spring·网络安全·数据挖掘·php
LEE2 小时前
Agent 的控制权,为什么正在回到模型手里?
前端·后端
沃夫上校2 小时前
跨域这件事,其实浏览器在替你挡刀
前端·后端·nginx
用户298698530142 小时前
Python 将 Word 文档转换为图片的实践指南
后端·python·api
旺仔不是程序员2 小时前
致命索引失效:索引列运算与函数索引不匹配
数据库·后端·面试