0


Bean 作用域和生命周期

1. 观察案例

User:

publicclassUser{publicint id;publicString name;publicintgetId(){return id;}publicvoidsetId(int id){this.id = id;}publicStringgetName(){return name;}publicvoidsetName(String name){this.name = name;}@OverridepublicStringtoString(){return"User{"+"id="+ id +", name='"+ name +'\''+'}';}}

UserBean(公共的Bean):

importorg.springframework.context.annotation.Bean;importorg.springframework.stereotype.Component;@ComponentpublicclassUserBean{@Bean(name ="user1")publicUsergetUser(){User user =newUser();
    user.setId(1);
    user.setName("张三");return user;}}

UserController1 在使用时,进行了修改操作:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Controller;@ControllerpublicclassUserController1{@AutowiredprivateUser user1;publicUsergetUser1(){User user = user1;System.out.println("userController1 修改之前的 User: "+user);
        user.setId(2);
        user.setName("李四");return user;}}

UserController2 再去使用公共 Bean:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Controller;@ControllerpublicclassUserController2{@AutowiredprivateUser user1;publicUsergetUser2(){User user = user1;return user;}}

打印 UserController1 和 UserController2 公共 Bean 的值:

importbeans.UserController1;importbeans.UserController2;importorg.springframework.context.ApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;publicclassApp{publicstaticvoidmain(String[] args){ApplicationContext context =newClassPathXmlApplicationContext("spring-config.xml");UserController1 userController1 = context.getBean("userController1",UserController1.class);User user1 = userController1.getUser1();System.out.println("userController1 修改之后的 User: "+user1);UserController2 userController2 = context.getBean("userController2",UserController2.class);User user2 = userController2.getUser2();System.out.println("userController2 在 userController1 修改之后读出的 User: "+user2);}}

结果:

在这里插入图片描述

原因:

Bean 作用域:bean 在 spring 整个框架中,默认所有人使用同一个对象,作用域默认是

singleton(单例模式)

2. 作用域定义

限定程序中变量的可⽤范围叫做作⽤域,或者说在源代码中定义变量的某个区域就叫做作⽤域。

⽽ Bean 的作⽤域是指 Bean 在 Spring 整个框架中的某种⾏为模式,⽐如 singleton 单例作⽤域,就表示 Bean 在整个 Spring 中只有⼀份,它是全局共享的,那么当其他⼈修改了这个值之后,那么另⼀个⼈读取到的就是被修改的值

3. Bean 的 6 种作用域

Spring 容器在初始化⼀个 Bean 的实例时,同时会指定该实例的作⽤域.

  1. singleton:单例模式(默认)
  1. prototype: 原型模式(多例模式)
  1. request: 请求作用域(Spring MVC)
  1. session: 会话作用域(Spring MVC)
  1. application: 全局作用域(Spring MVC)
  1. websocket: HTTP WebSocket 作用域(Spring WebSocket)
注意:

后 4 种状态是 Spring MVC 中的值,在普通的 Spring 项⽬中只有前两种

3.1 singleton

描述:

该作⽤域下的Bean在IoC容器中只存在⼀个实例:获取Bean(即通过applicationContext.getBean等⽅法获取)及装配Bean(即通过@Autowired注⼊)都是同⼀个对象。

场景:

通常⽆状态的Bean使⽤该作⽤域。⽆状态表示Bean对象的属性状态不需要更新

备注:

Spring默认选择该作⽤域

3.2 prototype

描述:

每次对该作⽤域下的Bean的请求都会创建新的实例:获取Bean(即通过applicationContext.getBean等⽅法获取)及装配Bean(即通过@Autowired注⼊)都是新的对象实例。

场景:

通常有状态的Bean 使⽤该作⽤域

3.3 request

描述:

每次http请求会创建新的Bean实例,类似于prototype

场景:

⼀次http的请求和响应的共享Bean

备注:

限定SpringMVC中使⽤

3.4 session

描述:

在⼀个http session中,定义⼀个Bean实例

场景:

⽤户回话的共享Bean, ⽐如:记录⼀个⽤户的登陆信息

备注:

限定SpringMVC中使⽤

3.5 application

描述:

在⼀个http servlet Context中,定义⼀个Bean实例

场景:

Web应⽤的上下⽂信息,⽐如:记录⼀个应⽤的共享信息

备注:

限定SpringMVC中使⽤

3.6 websocket

描述:

在⼀个HTTP WebSocket的⽣命周期中,定义⼀个Bea实例

场景:

WebSocket的每次会话中,保存了⼀个Map结构的头信息,将⽤来包裹客户端消息头。第⼀次初始化后,直WebSocket结束都是同⼀个Bean。

备注:

限定Spring WebSocket中使⽤

单例作⽤域(singleton)和全局作⽤域(application)区别

1: 

singleton 是 Spring Core 的作⽤域;application 是 Spring Web 中的作⽤域;

2: 

singleton 作⽤于 IoC 的容器,⽽ application 作⽤于 Servlet 容器

4. 设置 Bean 作用域

1:

使用枚举设置(类似于枚举,是常量的方式):

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
2:

直接设置值:

@Scope(“prototype”)

4.1 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

在这里插入图片描述

4.2 @Scope(“prototype”)

在这里插入图片描述

5. Bean 生命周期

所谓的⽣命周期指的是⼀个对象从诞⽣到销毁的整个⽣命过程,我们把这个过程就叫做⼀个对象的⽣命周期.

Bean 的⽣命周期分为以下 5 ⼤部分:

1: 实例化(给 bean 分配内存空间)
2: 设置属性(对象注入)
3: 初始化
a) 

执行各种通知(执行各种 Aware)

b)

执行初始化的前置方法(BeanPostProcessor)

c)

执行构造方法,两种执行方式,一种是执行 @PostConstruct,另一种实质性 init-method

d)

执行初始化的后置方法(BeanPostProcessor)

4: 使用 Bean
5: 销毁 Bean

(销毁容器的各种方法)

a)

@PreDestroy

b)

重写 DisposableBean 接口方法

c)

destroy-method

在这里插入图片描述

5.1 实例化和初始化的区别

实例化和属性设置是 Java 级别的系统“事件”,其操作过程不可⼈⼯⼲预和修改;⽽初始化是给开发者提供的,可以在实例化之后,类加载完成之前进⾏⾃定义“事件”处理

5.2 生命流程"案例"

Bean 的⽣命流程看似繁琐,但咱们可以以⽣活中的场景来理解它,⽐如我们现在需要买⼀栋房⼦,那么我们的流程是这样的:

  1. 先买房(实例化,从⽆到有);
  2. 装修(设置属性);
  3. 买家电,如洗⾐机、冰箱、电视、空调等([各种]初始化);
  4. ⼊住(使⽤ Bean);
  5. 卖出去(Bean 销毁)。

5.3 演示代码

importorg.springframework.beans.factory.BeanNameAware;importjavax.annotation.PostConstruct;importjavax.annotation.PreDestroy;//@ComponentpublicclassBeanLifeComponentimplementsBeanNameAware{@PostConstructpublicvoidpostConstruct(){System.out.println("执行 @PostConstruct");}publicvoidinit(){System.out.println("执行 init-method");}publicvoiduse(){System.out.println("使用 bean");}@PreDestroypublicvoidpreDestroy(){System.out.println("执行了 @PreDestroy");}publicvoidsetBeanName(String s){System.out.println("执行了 Aware 通知");}}

xml 配置:

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:content="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><content:component-scanbase-package="beans"></content:component-scan><beanid="beanLifeComponent"class="beans.BeanLifeComponent"init-method="init"></bean></beans>

测试:

importorg.springframework.context.support.ClassPathXmlApplicationContext;publicclassApp2{publicstaticvoidmain(String[] args){ClassPathXmlApplicationContext context =newClassPathXmlApplicationContext("spring-config.xml");BeanLifeComponent beanLifeComponent = context.getBean("beanLifeComponent",BeanLifeComponent.class);
        beanLifeComponent.use();
        context.destroy();}}

结果:
在这里插入图片描述

标签: java spring 后端

本文转载自: https://blog.csdn.net/chenbaifan/article/details/125694638
版权归原作者 粉色的志明 所有, 如有侵权,请联系我们删除。

“Bean 作用域和生命周期”的评论:

还没有评论