【Spring 原理】Bean 的作用域与生命周期

文章目录

一、Bean的作用域

1.1 概念

在Spring IoC&DI,Spring 是通过以下方式管理对象的。

  1. 通过@Controller , @Service , @Repository , @Component , @Configuration , @Bean 来声明Bean对象。
  2. 通过 ApplicationContext 或者 BeanFactory 来获取对象
  3. 通过@Autowired , Setter 方法或者构造方法等来为应用程序注入所依赖的Bean对象。

  1. 通过@Bean 声明bean , 把bean存在Spring容器中
java 复制代码
@Component
public class DogBeanConfig {
	@Bean
	public Dog dog(){
		Dog dog = new Dog();
		dog.setName("旺旺");
		return dog;
	}
}
  1. 从Spring容器中获取Bean
java 复制代码
@SpringBootApplication
public class SpringIocApplication {
	public static void main(String[] args) {
		//获取Spring上下文对象
		ApplicationContext context = SpringApplication.run(SpringIocApplication.class, args);
		//从Spring上下文中获取对象
		Dog dog = context.getBean(Dog.class);
		System.out.println(dog);	
	}
}

也可以通过在代码中直接注入ApplicationContext的方式来获取Spring容器

java 复制代码
@SpringBootTest
class DemoApplicationTests {
	@Autowired
	private ApplicationContext applicationContext; //Spring 容器

	@Test
	void contextLoads() {
		DogBean dog1 = applicationContext.getBean(DogBean.class);
		System.out.println(dog1);	
	}
}

观察运行结果:

发现输出的bean对象地址值是一样的,说明每次从Spring容器中取出来的对象都是同一个。这也是"单例模式"

单例模式:确保一个类只有一个实例,多次创建也不会创建出多个实例。

默认情况下,Spring容器中的bean都是单例的,这种行为模式,我们就称之为Bean的作用域。

Bean 的作用域是指 Bean 在 Spring 框架中的某种行为模式。

1.2 Bean的作用域

在Spring中支持6种作用域,后4种在Spring MVC环境才生效

  1. singleton:单例作用域
  2. prototype:原型作用域(多例作用域)
  3. request:请求作用域
  4. session:会话作用域
  5. Application: 全局作用域
  6. websocket:HTTP WebSocket 作用域
作用域 说明
singleton 每个Spring IoC容器内同名称的bean只有一个实例(单例)(默认)
prototype 每次使用该bean时会创建新的实例(非单例)
request 每个HTTP 请求生命周期内, 创建新的实例(web环境中, 了解)
session 每个HTTP Session生命周期内, 创建新的实例(web环境中, 了解)
application 每个ServletContext生命周期内, 创建新的实例(web环境中, 了解)
websocket 每个WebSocket生命周期内, 创建新的实例(web环境中, 了解)

二、Bean的生命周期

2.1 概念

生命周期指的是一个对象从诞生到销毁的整个生命过程,我们把这个过程就叫做一个对象的生命周期。 Bean 的生命周期分为以下5个部分:

  1. 实例化(为Bean分配内存空间)
  2. 属性赋值(Bean注入和装配,比如@AutoWired )
  3. 初始化
    a. 执行各种通知,如 BeanNameAware , BeanFactoryAware ,ApplicationContextAware 的接口方法。
    b. 执行初始化方法
    ▪ xml定义init-method
    ▪ 使用注解的方式 @PostConstruct
    ▪ 执行初始化后置方法( BeanPostProcessor )
  4. 使用Bean
  5. 销毁Bean
    a. 销毁容器的各种方法,如 @PreDestroy , DisposableBean 接口方法,destroymethod。

实例化和属性赋值对应构造方法和setter方法的注入。 初始化和销毁是用户能自定义扩展的两个阶段,可以在实例化之后,类加载完成之前进行自定义"事件"处理。

执行流程如下图所示:

2.1 代码演示

java 复制代码
@Component
public class BeanLifeComponent implements BeanNameAware {

	private UserComponent userComponent;

	public BeanLifeComponent() {
		System.out.println("执行构造函数");
	}

	@Autowired
	public void setUserComponent(UserComponent userComponent) {
		System.out.println("设置属性userComponent");
		this.userComponent = userComponent;
	}

	@Override
	public void setBeanName(String s) {
		System.out.println("执行了 setBeanName 方法:" + s);
	}


	@PostConstruct
	public void postConstruct() {
		System.out.println("执行 PostConstruct()");
	}
	public void use() {
		System.out.println("执行了use方法");
	}


	@PreDestroy
	public void preDestroy() {
		System.out.println("执行:preDestroy()");
	}
}

通过运行结果观察

  1. 先执行构造函数
  2. 设置属性
  3. Bean初始化
  4. 使用Bean
  5. 销毁Bean
相关推荐
亦暖筑序4 分钟前
AgentScope-Java 入门:用 Middleware 审计 Agent 调用
java·ai编程·agentscope
你驴我14 分钟前
WhatsApp 消息撤回与编辑的幂等性设计实践
java·服务器·前端·后端·python
一缕清烟在人间17 分钟前
HarmonyOS开发实战:小分享-TextEditPage文字编辑器——Header+TextArea+工具栏
后端·华为·harmonyos·鸿蒙
程序员cxuan27 分钟前
Opus 5 深夜炸场,价格还挺香。。。
人工智能·后端·程序员
青山木1 小时前
Hot 100 ---腐烂的橘子
java·数据结构·后端·算法·leetcode·广度优先
卷无止境1 小时前
Python的collections模块:那些被低估的"瑞士军刀"
后端·python
卷无止境1 小时前
Python的方法解析顺序:一场关于继承顺序的精妙设计
后端·python
小龙报1 小时前
【优选算法】1. 水果成蓝 2.找到字符串中所有字母的异位词
java·c语言·数据结构·数据库·c++·redis·算法
宁&沉沦1 小时前
Chrome 扩展 Manifest 字段版本支持一览(全量)
前端·后端·编辑器
自强的小白1 小时前
重点!起始时间和结束时间与创建时间和修改时间的区别(localdate与LocaldateTIME区别)以及增删改查什么时候设置目前时间(添加和更新员工时)
java