Spring学习 | Bean作用域生命周期
创始人
2024-03-25 00:09:32
0

文章目录

  • 一、作用域
    • 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 作用域(设置单例还是多例):标签中添加属性——scope,scope 的值由多种选择

singleton

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

prototype

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

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

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


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

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

2.5 Bean 销毁的方式

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

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

    
    
    
    
    
  • 测试方法

    @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();
    }
    
  • 测试打印结果
    打印结果

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...
AWR报告解读 WORKLOAD REPOSITORY PDB report (PDB snapshots) AW...