当前位置: 首页 > news >正文

Bean的作用域和生命周期

Bean的作用域

我们先来看下面这段代码

首先是一个Dog类  (此处使用lombok来完成setter、getter、toString方法)

@Setter
@Getter
public class Dog {private String name;}

然后在DogBeanConfig类里面写一个返回Dog的方法,并将这个方法的返回对象存入Spring容器

@Component
public class DogBeanConfig {@Beanpublic Dog singleDog() {Dog dog = new Dog();return dog;}
}

 然后在类里分别注入这个Dog对象

RestController
public class DogController {@Autowiredprivate Dog singleDog;@RequestMapping("/single")public String single(){Dog contextDog = (Dog)applicationContext.getBean("singleDog");return "dog:"+singleDog.toString()+",contextDog:"+contextDog;}
}

结果

多次访问, 得到的都是同⼀个对象, 并且 @Autowired 和 applicationContext.getBean() 也是同⼀个对象.(在打印对象时,Java的Object.toString()方法(如果类没有重写这个方法)会返回对象的类名加上这个哈希码的十六进制表示) 快速查看对象的类型或唯一性时,这种输出非常有用。

这就是Bean的不同作⽤域了


Bean的六种作用域

(在Spring中⽀持6种作⽤域,后4种在Spring MVC环境才⽣效)

1. 单例模式:singleton(默认)-- 每次注入都是同一份对象。默认为这种模式也是Spring为了性能的考虑。

2. 原型模式:prototype -- 每次注入都是一个新的对象。

3. 请求作用域(适用于Spring MVC / Spring Web):request -- 每次http请求中共享一份Bean对象。

4. 回话作用域(适用于Spring MVC / Spring Web):session -- 每次会话(session)共享一份Bean对象。

5. 全局作用域(适用于Spring MVC / Spring Web):applicaton -- 每个http servlet context中共享一份Bean对象。

6. websocket:适用于Spring WebSocket项目。


Bean的作用域设置

Bean设置作用域使用 @Scope 注解

使用方法:

@Scope 注解里加上作用域名,比如:@Scope("prototype") 此时被该注解修饰的类为原型模式。

定义⼏个不同作⽤域的Bean

package demo.beanscope;import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.ApplicationScope;
import org.springframework.web.context.annotation.RequestScope;
import org.springframework.web.context.annotation.SessionScope;/*** Created with IntelliJ IDEA.* Description:* User: 22652* Date: 2024-08-03* Time: 13:37*/
@Component
public class DogBeanConfig {@Beanpublic Dog dog() {Dog dog = new Dog();dog.setName("旺旺");return dog;}@Bean@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)public Dog singleDog() {Dog dog = new Dog();return dog;}@Bean@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)public Dog prototypeDog() {Dog dog = new Dog();return dog;}@Bean@RequestScopepublic Dog requestDog() {Dog dog = new Dog();return dog;}@Bean@SessionScopepublic Dog sessionDog() {Dog dog = new Dog();return dog;}@Bean@ApplicationScopepublic Dog applicationDog() {Dog dog = new Dog();return dog;}
}

@RequestScope 等同于 @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)其他同理

 测试不同作⽤域的Bean取到的对象是否⼀样

package demo.beanscope;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** Created with IntelliJ IDEA.* Description:* User: 22652* Date: 2024-08-03* Time: 13:41*/
@RestController
public class DogController {@Autowiredprivate Dog singleDog;@Autowiredprivate Dog prototypeDog;@Autowiredprivate Dog requestDog;@Autowiredprivate Dog sessionDog;@Autowiredprivate Dog applicationDog;@Autowiredprivate ApplicationContext applicationContext;@RequestMapping("/single")public String single(){Dog contextDog = (Dog)applicationContext.getBean("singleDog");return "dog:"+singleDog.toString()+",contextDog:"+contextDog;}@RequestMapping("/prototype")public String prototype(){Dog contextDog = (Dog)applicationContext.getBean("prototypeDog");return "dog:"+prototypeDog.toString()+",contextDog:"+contextDog;}@RequestMapping("/request")public String request(){Dog contextDog = (Dog)applicationContext.getBean("requestDog");return"dog:"+requestDog.toString()+",contextDog:"+contextDog.toString();}@RequestMapping("/session")public String session(){Dog contextDog = (Dog)applicationContext.getBean("sessionDog");return"dog:"+sessionDog.toString()+",contextDog:"+contextDog.toString();}@RequestMapping("/application")public String application(){Dog contextDog = (Dog)applicationContext.getBean("applicationDog");return"dog:"+applicationDog.toString()+",contextDog:"+contextDog.toString();}
}

观察Bean的作⽤域

单例作⽤域: http://127.0.0.1:8080/single 多次访问, 得到的都是同⼀个对象, 并且 @Autowired 和 applicationContext.getBean() 也是同⼀个对象。

多例作⽤域: http://127.0.0.1:8080/prototype 观察ContextDog, 每次获取的对象都不⼀样(注⼊的对象在Spring容器启动时, 就已经注⼊了, 所以多次 请求也不会发⽣变化)

请求作⽤域: http://127.0.0.1:8080/request 在⼀次请求中, @Autowired 和 applicationContext.getBean() 也是同⼀个对象. 但是每次请求, 都会重新创建对象

 

 

会话作⽤域: http://127.0.0.1:8080/session 在⼀个session中, 多次请求, 获取到的对象都是同⼀个.

 换⼀个浏览器访问, 发现会重新创建对象.(另⼀个Session)

Application作⽤域: http://127.0.0.1:8080/application在⼀个应⽤中, 多次访问都是同⼀个对象 

 Application scope就是对于整个web容器来说, bean的作⽤域是ServletContext级别的. 这个和 singleton有点类似,区别在于: Application scope是ServletContext的单例, singleton是⼀个 ApplicationContext的单例. 在⼀个web容器中ApplicationContext可以有多个. (了解即可)

Bean的生命周期 

 ⽣命周期指的是⼀个对象从诞⽣到销毁的整个⽣命过程, 我们把这个过程就叫做⼀个对象的⽣命周期. 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.

如图

//通知需要BeanNameAware接口
public class BeanComponent implements BeanNameAware {@Overridepublic void setBeanName(String s) {System.out.println("执行了通知: " + s);}public void myInit() {System.out.println("XML方式的初始化方法");}@PostConstructpublic void doPostConstruct() {System.out.println("注解方法的初始化方法");}public void myDestroy() {System.out.println("XML方式的销毁方法");}@PreDestroypublic void doPreDestroy() {System.out.println("注解方式的销毁方法");}public void sayHi() {System.out.println("执行 sayHi方法");}
}

下面我们来执行这个类。

public static void main(String[] args) {//启动容器ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");//从容器获取Bean对象BeanComponent beanComponent = context.getBean("beanComponent", BeanComponent.class);//执行Bean对象的内容beanComponent.sayHi();//销毁Bean对象的方法context.destroy();}

http://www.lryc.cn/news/413623.html

相关文章:

  • 【Qt】QMainWindow之菜单栏
  • uni-app封装组件实现下方滑动弹出模态框
  • MATLAB(15)分类模型
  • 非虚拟机安装Centos7连接wifi并开机自动联网
  • 怎么选择的开放式耳机好用?2024超值耳机分享!
  • Web 框架
  • 嗖嗖移动业务大厅(JDBC)
  • 大学生编程入门指南:如何从零开始?
  • 如何基于欧拉系统完成数据库的安装
  • 防御笔记第九天(持续更新)
  • html+css+js前端作业和平精英6个页面页面带js
  • 详解基于百炼平台及函数计算快速上线网页AI助手
  • 【TVM 教程】在 CUDA 上部署量化模型
  • 使用 continue 自定义 AI 编程环境
  • 谷粒商城实战笔记-118-全文检索-ElasticSearch-进阶-aggregations聚合分析
  • ansible,laas,pass,sass
  • 【开源分享】PHP在线提交工单源码|工单管理系统源码 (附源码搭建教程)
  • 【深入探秘Hadoop生态系统】全面解析各组件及其实际应用
  • Flink DataStream API编程入门
  • 案例分享|Alluxio在自动驾驶数据闭环中的应用
  • 为什么选择 Baklib 而不是 Salesforce 进行知识库管理
  • 【C++11】解锁C++11新纪元:深入探索Lambda表达式的奥秘
  • c语言排序(2)
  • vue3+ts+element plus开源框架基础
  • RabbitMQ快速入门(MQ的概念、安装RabbitMQ、在 SpringBoot 项目中集成 RabbitMQ )
  • Linux文件与目录管理命令 ls cp rm mv使用方法
  • KubeSphere 部署的 Kubernetes 集群使用 GlusterFS 存储实战入门
  • elasticsearch源码分析-08Serch查询流程
  • 【协作提效 Go - gin ! swagger】
  • 栈和队列——3.滑动窗口最大值