Spring学习 | Bean作用域生命周期

news2024/11/19 3:36:10

文章目录

  • 一、作用域
    • 1.1 xml文件中配置
    • 1.2 注解配置
  • 二、生命周期
    • 2.1 四个阶段
    • 2.2 添加后置处理器
    • 2.3 实现aware类型接口
    • 2.4 Bean 初始化的方式
    • 2.5 Bean 销毁的方式
    • 2.6 测试程序


学习视频🎥:https://www.bilibili.com/video/BV1Vf4y127N5

一、作用域

❓ 引入概念

  • 单实例对象:对于所有的请求都是同一个对象去处理,相当于静态代码,只加载一次,使用多次。spring 中创建的bean默认是单例实例的
  • 多实例对象:对于多次请求,创建多个对象去处理

1.1 xml文件中配置

🔑 修改spring 中的bean 作用域(设置单例还是多例):<bean>标签中添加属性——scope,scope 的值由多种选择

singleton

  • 默认值,表示创建的对象是单实例的
  • 将scope 属性这是为 singleton 后,加载spring 配置文件时就会把对象创建出来

prototype

  • 将创建的对象设置为多实例
  • 将scope 属性这是为 prototype 后,加载spring 配置文件时不会创建对象,在获取对象或使用对象的时候才会创建

③ request:将对象的作用域设置为request 域

④ session:将对象的作用域设置为session 域

<bean id="u" class="com.Key.spring.bean.User" scope="prototype"></bean>

1.2 注解配置

在需要修改的作用域的类上添加@Component@Scope注解,注解中直接添加值即可,值的选择和默认值同上

💡 需要Bean 需要被创建后才能修改其作用域,所以必须先添加@Component注解(其他创建对象的注解也可)

@Component
@Scope("prototype")
public class User {
    // code...
}

二、生命周期

👀参考博文:谈谈你对Spring Bean生命周期的理解【面试】

生命周期

2.1 四个阶段

bean 的声明周期可初步分为四个阶段

Bean 的实例化阶段:执行Bean 的无参构造器

Bean 的属性注入阶段:执行Bean 的所有成员变量对应的set 方法

Bean 的初始化阶段:执行自定义的初始化方法或Java 接口内部方法

❓ 获取Bean阶段:在Bean 的初始化阶段后、销毁阶段前还有获取和使用Bean 的阶段

// 获取对象
BeanLifeDemo lifeDemo = context.getBean("bl", BeanLifeDemo.class);
// 使用对象
System.out.println(lifeDemo);

Bean 的销毁阶段:执行自定义的销毁方法或Java 接口内部方法(需要手动执行)

2.2 添加后置处理器

  • 后置处理器:创建一个类实现BeanPostProcessor接口,并实现接口的两个方法
  • 执行时间:在Bean 初始化阶段的前后分别执行后置处理器的postProcessBeforeInitialization()方法和postProcessAfterInitialization()方法

2.3 实现aware类型接口

  • aware类型接口:能感知到所有Aware前面的含义的接口,如BeanNameAware、ApplicationContextAware

  • 接口的作用:加载资源到Spring中,Aware前面的名字对应加载的资源

  • 执行时间:Bean 属性注入阶段之后、后置处理器的postProcessBeforeInitialization()方法之前

  • 各个aware 接口的执行顺序以及各自对应的执行方法(去掉Aware,前面加上set

    ① BeanNameAware --> setBeanName()
    ② BeanClassLoaderAware --> setBeanClassLoader()
    ③ BeanFactoryAware --> setBeanFactory()
    ④ EnvironmentAware --> setEnvironment()
    ⑤ ResourceLoaderAware --> setResourceLoader()
    ⑥ ApplicationEventPublisherAware --> setApplicationEventPublisher()
    ⑦ ApplicationContextAware --> setApplicationContex()

    BeanFactoryApplicationContext的区别:BeanFactoryAware接口之前加载的资源都是公共的,之后加载的资源都是ApplicationContext独有的

2.4 Bean 初始化的方式

  1. 基于xml 文件:在Bean 对应的类中自定义一个初始化方法,并在配置文件的<bean>标签中添加init-method属性,值为自定义的初始化方法名
  2. 基于注解:在Bean 对应的类中自定义一个初始化方法,方法上添加注解@PostConstruct
  3. 实现接口(基于Java):让Bean 对应的类实现InitializingBean接口,并实现接口的afterPropertiesSet()方法

💡 常用的方法是前面两种,即自定义初始化方法,销毁方法也一样

2.5 Bean 销毁的方式

  1. 基于xml 文件:在Bean 对应的类中自定义一个销毁方法,并在配置文件的<bean>标签中添加destroy-method属性,值为自定义的销毁方法名
  2. 基于注解:在Bean 对应的类中自定义一个销毁方法,方法上添加注解@PreDestroy
  3. 实现接口(基于Java):让Bean 对应的类实现DisposableBean接口,并实现接口的destroy()方法

💡 Bean 的销毁不会自动执行,需要手动调用工厂对象的 close() 方法

/*
    创建工厂对象
     - 注意这里是直接采用ClassPathXmlApplicationContext作为对象类型,而不是Application接口
     - 因为close()方法是在ClassPathXmlApplicationContext中创建的,不是实现于Application接口
*/
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beanLifeDemo.xml");

// code...

// 关闭工厂对象,同时销毁Bean(执行对应的销毁方法)
context.close();

2.6 测试程序

  • 测试Bean --> BeanLifeDemo.java

    public class BeanLifeDemo implements InitializingBean, DisposableBean, BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, EnvironmentAware, ResourceLoaderAware, ApplicationEventPublisherAware, ApplicationContextAware {
    
    /*+---------------------------------------实例化阶段---------------------------------------------+*/
    
        public BeanLifeDemo() {
            System.out.println("一、实例化 --> 执行无参构造器...");
        }
                
    /*+---------------------------------------注入属性阶段---------------------------------------------+*/
        private String name;
        private int age;
        public void setName(String name) {
            System.out.println("二、注入属性 --> 2.1 执行setName()");
            this.name = name;
        }
        public void setAge(int age) {
            System.out.println("二、注入属性 --> 2.2 执行setAge()");
            this.age = age;
        }
        @Override
        public String toString() {
            return "BeanLifeDemo{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
                
    /*+---------------------------------------实现各个aware 接口的各个set方法---------------------------------------------+*/
    
        @Override
        public void setBeanClassLoader(ClassLoader classLoader) {
            System.out.println("三、实现aware 接口 --> 3.2 对应BeanClassLoaderAware接口");
        }
    
        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            System.out.println("三、实现aware 接口 --> 3.3 对应BeanFactoryAware接口");
        }
    
        @Override
        public void setBeanName(String s) {
            System.out.println("三、实现aware 接口 --> 3.1 对应BeanNameAware接口");
        }
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            System.out.println("三、实现aware 接口 --> 3.7 对应ApplicationContextAware接口");
        }
    
        @Override
        public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
            System.out.println("三、实现aware 接口 --> 3.6 对应ApplicationEventPublisherAware接口");
        }
    
        @Override
        public void setEnvironment(Environment environment) {
            System.out.println("三、实现aware 接口 --> 3.4 对应EnvironmentAware接口");
        }
    
        @Override
        public void setResourceLoader(ResourceLoader resourceLoader) {
            System.out.println("三、实现aware 接口 --> 3.5 对应ResourceLoaderAware接口");
        }
                
    /*+---------------------------------------初始化阶段---------------------------------------------+*/
        /**
         * 自定义初始化方法
         *  - 基于xml文件:在<bean>中添加 init-method 属性,属性值为方法名
         *  - 基于注解:在方法上添加注解 @PostConstruct
         */
        public void initMethod() {
            System.out.println("五、初始化 --> 5.2 自定义初始化方法");
        }
    
        /**
         * 实现Java 接口内部的初始化方法
         *  - 实现 InitializingBean 接口
         *  - 不用配置和添加注解
         */
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("五、初始化 --> 5.1 Java接口内部的初始化方法");
        }  
    
    /*+---------------------------------------销毁阶段---------------------------------------------+*/
    
        /**
         * 自定义销毁方法
         *  - 基于xml文件:在<bean>中添加 destroy-method 属性,属性值为方法名
         *  - 基于注解:在方法上添加注解 @PreDestroy
         */
        public void destroyMethod() {
            System.out.println("八、销毁 --> 8.2 自定义销毁方法");
        }
    
        /**
         * 实现Java 接口内部的销毁方法
         *  - 实现 DisposableBean 接口
         *  - 不用配置和添加注解
         */
        @Override
        public void destroy() throws Exception {
            System.out.println("八、销毁 --> 8.1 Java接口内部的销毁方法");
        }
    }           
    
  • 自定义后置处理器 --> MyBeanPostProcessor.java

    public class MyBeanPostProcessor implements BeanPostProcessor {
    
        /**
         * 在Bean 初始化前执行的方法
         */
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("四、将Bean交给后置处理器 --> Bean初始化前执行...");
            return bean;
        }
    
        /**
         * 在Bean 初始化后执行的方法
         */
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("六、将Bean交给后置处理器 --> Bean初始化后执行...");
            return bean;
        }
    }
    
  • 基于xml 文件配置 --> beanLifeDemo.xml

    <!-- 创建自定义的后置处理器对象(配置后置处理器) -->
    <bean id="myBeanPost" class="com.Key.spring.ioc.beanlife.MyBeanPostProcessor"></bean>
    
    <!--
        创建bean生命周期演示对象
         - 注入属性
         - 配置自定义的初始化方法和销毁方法
    -->
    <bean id="bl" class="com.Key.spring.ioc.beanlife.BeanLifeDemo" init-method="initMethod" destroy-method="destroyMethod">
        <property name="name" value="宋江"></property>
        <property name="age" value="54"></property>
    </bean>
    
  • 测试方法

    @Test
    public void testBeanLife() {
        // 加载spring配置文件,获取工厂对象
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beanLifeDemo.xml");
        // 获取对象
        BeanLifeDemo lifeDemo = context.getBean("bl", BeanLifeDemo.class);
    
        System.out.println("七、获取实例化对象 --> " + lifeDemo);
    
        // 关闭工厂对象,即销毁Bean,spring bean不会自动销毁,必须调用工厂对象的close() 方法
        context.close();
    }
    
  • 测试打印结果
    打印结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/69973.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux系统中裸机按键中断的驱动方法

大家好&#xff0c;今天主要和大家聊一聊&#xff0c;如何实现按键中断的驱动​方法。 目录 ​第一&#xff1a;外部中断头文件实现 ​第二&#xff1a;外部中断源文件的具体实现 ​第三&#xff1a;编写对应的main.c函数 ​第一&#xff1a;外部中断头文件实现 #ifndef _…

基于keras平台CNN神经网络模型的服装识别分析

在许多介绍图像识别任务的介绍中&#xff0c;通常使用着名的MNIST数据集。 最近我们被客户要求撰写关于图像识别的研究报告&#xff0c;包括一些图形和统计输出。但是&#xff0c;这些数据存在一些问题&#xff1a; 1.太简单了。例如&#xff0c;一个简单的MLP模型可以达到99…

Java搭建宝塔部署实战毕设项目springboot客户管理系统源码

大家好啊&#xff0c;我是测评君&#xff0c;欢迎来到web测评。 本期给大家带来一套Java开发的毕业设计项目&#xff0c;springboot客户管理系统源码&#xff0c;感兴趣的朋友可以自行下载搭建测试。 技术架构 技术框架&#xff1a;SpringBoot MySQL5.7 mybatis shiro Lay…

DDR4时序标准规范(一)

DDR4时序标准规范引脚描述DDR4 SDRAM寻址DDR4架构的模块描述功能描述简化状态机基本功能复位和初始化程序上电和初始化顺序电压稳定后的复位初始化顺序无控制的下电顺序引脚描述 标志类型功能CK_t, CK_c输入Clock: CK_t和CK_c是差分时钟输入。所有的地址和控制输入信号在CK_t的…

主成分分析(PCA)原理及R语言实现及分析实例

主成分分析&#xff08;PCA&#xff09;是一种数据降维技巧&#xff0c;它能将大量相关变量转化为一组很少的不相关变量&#xff0c;这些无关变量称为主成分。最近我们被客户要求撰写关于主成分分析&#xff08;PCA&#xff09;的研究报告&#xff0c;包括一些图形和统计输出。…

Vagrant搭建Centos

1.下载安装vagrant 01访问Vagrant官网 ​ https://www.vagrantup.com/ 02 点击Download ​ Windows&#xff0c;MacOS&#xff0c;Linux等 03 选择对应的版本 04 傻瓜式安装 05 命令行输入vagrant&#xff0c;测试是否安装成功,显示如下&#xff1a; 2.下载安装virtua…

半解析快速傅里叶变换

我们提出了一种处理傅里叶变换的方法&#xff0c;其并不需要二次多项式相位项的抽样&#xff0c;而是用解析的方法处理。我们提出该理论的同时也给出了几个例子证明其潜力。 1.简介 物理光学建模需要频繁地从空间转换到角频域&#xff0c;反之亦然。这可以由电场和磁场分…

网络编程(用于不同电脑之间的信息交互):UDP、TCP

网络编程&#xff1a; 在网络通信写一下&#xff0c;不同计算机运行的程序&#xff0c;可以进行数据传输 IP地址&#xff1a;设备&#xff08;手机、电脑等&#xff09;在网络中的地址&#xff0c;是唯一的标识 端口&#xff1a;应用程序在设备中唯一的表示 协议&#xff1a…

数据结构学习——表、查找

定义 设记录表L(R1 R2…其中Ri(L<i<n)为记录&#xff0c; 对给定的某个值k&#xff0c; 在表L中确定key k的记录的过程&#xff0c;称为查找。若表Lz中存在记录Ri de key k,记为Ri.key,则查找成功&#xff0c;返回该记录在表L中的序号i&#xff08;或Ri的地址&#xff…

优秀的 Verilog/FPGA开源项目介绍(二十)- 张量处理单元(TPU)

介绍张量处理单元( Tensor Processing Unit, TPU ) 是谷歌专门为神经网络机器学习开发的人工智能加速器 专用集成电路(ASIC) &#xff0c;特别是使用谷歌自己的TensorFlow软件。谷歌于 2015 年开始在内部使用 TPU&#xff0c;并于 2018 年将它们作为其云基础设施的一部分并通过…

Zabbix6.0使用教程 (三)—zabbix6.0的安装要求

接上篇&#xff0c;我们继续为大家详细介绍zabbix6.0的使用教程之zabbix6.0的安装部署。接下来我们将从zabbix部署要求到四种不同的安装方式逐一详细的为大家介绍。本篇讲的是部署zabbix6.0的要求。 zabbix6.0安装要求 硬件&#xff1a;内存和磁盘 Zabbix6.0安装 运行需要物…

算法精品讲解(2)——DP问题入门(适合零基础者,一看就会)

目录 前言 DP问题它是什么&#xff08;了解&#xff09; 从中学的例题谈起 再来说一下&#xff0c;DP问题的核心思想&#xff08;理解&#xff09; DP问题的解决方法 先说方法论&#xff1a; 再说具体的例子 例一&#xff1a; 例二&#xff1a; 例三&#xff1a; DP和…

kotlin之range范围表达式

Kotlin 中的 Range 有 CharRange、LongRange、IntRange range 范围 CharRange、LongRange、IntRange 范围区间 var a:IntRange 50..100for (i in a){ //遍历50~100的分数分别在什么位置print("成绩&#xff1a;$i")if(i in 1..59){ //1~59 范围println("…

Leica Infinity三维映射环境数据

Leica Infinity三维映射环境数据 Leica Infinity是软件工程师和该领域专家的名字&#xff0c;以及您的工作计划信息。该软件被设计和呈现为一个强大的产品&#xff0c;并且来自六边形组。Leica Infinity产品的居民试图用新的眼光创造新的数据处理。使用此软件&#xff0c;您可以…

和ChatGPT 比一比谁更懂Kubernetes?

有时&#xff0c;很难得到关于云原生世界中棘手话题的明确答案。哪个是最好的服务网格&#xff1f;平台工程只是devops的另一个标签吗&#xff1f;多云是一种风险吗&#xff1f; 如果你无法从一个人那里得到直截了当的答案——为什么不问一台机器呢&#xff1f; 因此&#xf…

net6自动注册到Consul 代码实例

简单理解: 服务多的时候&#xff0c;服务地址都是写固定&#xff0c;增加一个地址&#xff0c;配置一次&#xff0c;配置nginx或者其他配置&#xff0c;麻烦 有了这个就可以通过应用服务上报服务名servicename和访问地址&#xff0c;同一个服务名servicename可以有多个节点&a…

【教学类-15-05】20221207《八款字体的描字帖-2*4格》(中班大班)

成品样式&#xff1a; 80号字&#xff08;适应2-3个名字的大小&#xff09; 68号字&#xff08;适应4个名字大小&#xff08;2-3个名字也可以用&#xff0c;字会很小&#xff09;&#xff09; 打印样式&#xff1a; 背景需求&#xff1a; 前期进行多次的Python学具教学活动&a…

能跟CAD、BIM软件联合使用的地图神器,比奥维谷歌地图还方便!

是的&#xff0c;今天王工推荐的跟之前的地图工具不一样&#xff0c;百度、谷歌、MAPBOX那些称之为地图工具&#xff0c;这个简直就是地图的浏览器&#xff01;而且它还可以与CAD、BIM软件联合使用&#xff01; 实在是比奥维地图“香”。 海量图源任意浏览 ▲ 任意切换各种地…

OpUtils的网络扫描

什么是网络扫描程序 网络扫描程序只需扫描整个网络基础架构&#xff0c;即可获取和记录网络资源的可用性、性能和利用率指标。它执行 Ping 扫描和 SNMP 扫描&#xff0c;以识别网络中运行的实时主机和服务。网络扫描程序可以执行网络扫描以显示详细信息&#xff0c;例如当前登…

第十四届蓝桥杯集训——JavaC组首篇——环境搭建(win11)

还有9天就截止报名了&#xff0c;我们也算正式开始培训了&#xff0c;今年希望能取得更好的成绩。 今年的蓝桥杯从环境开始——本博客为win10电脑的Java_JDK环境搭建&#xff1a; 学生机环境-Java编程环境&#xff08;第十四届大赛&#xff09; 链接: https://pan.baidu.com…