Bean 作用域、生命周期和Spring执行流程

这篇具有很好参考价值的文章主要介绍了Bean 作用域、生命周期和Spring执行流程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Bean作用域问题案例分析

假设现在有⼀个公共的 Bean,提供给 A ⽤户和 B ⽤户使⽤,然⽽在使⽤的途中 A ⽤户却“悄悄”地修改了公共 Bean 的数据,导致 B ⽤户在使⽤时发⽣了预期之外的逻辑错误。

公共 Bean

@Component
public class DogBean {
    @Bean
    public Dog dog() {
        Dog dog = new Dog();
        dog.setName("旺财");
        dog.setId(1);
        dog.setAge(5);
        return dog;
    }
}

A 用户使用时修改

@Controller
public class ScopeController {

    @Autowired
    private Dog dog;

    public void doScope(){
        System.out.println("do scope controller");
        System.out.println("原始dog对象:" + dog.toString());

        Dog dog2 = dog;
        dog2.setAge(10);
        dog2.setId(2);
        dog2.setName("小黑");

        System.out.println("修改后的dog对象:" + dog.toString());
    }
}

Bean 作用域、生命周期和Spring执行流程,Java,spring,后端,Bean生命周期,Bean作用域

B 用户使用时

@Controller
public class ScopeController2 {
    @Resource
    private Dog dog;

    public void doScope(){
        System.out.println("do scope controller2");

        System.out.println(dog.toString());
    }
}

Bean 作用域、生命周期和Spring执行流程,Java,spring,后端,Bean生命周期,Bean作用域

原因分析

我们可以看到,B 用户在使用这个Bean对象时,得到的Dog是被A 用户修改过的,这无疑会给 B 用户带来很大的麻烦。操作以上问题的原因是因为 Bean 默认情况下是单例状态(singleton),也就是所有⼈的使⽤的都是同⼀个对象,之前我们学单例模式的时候都知道,使⽤单例可以很⼤程度上提⾼性能,所以在 Spring 中 Bean 的作⽤域默认也是 singleton 单例模式。

作用域定义

限定程序中变量的可⽤范围叫做作⽤域,或者说在源代码中定义变量的某个区域就叫做作⽤域。⽽ Bean 的作⽤域是指 Bean 在 Spring 整个框架中的某种⾏为模式,⽐如 singleton 单例作⽤域,就表示 Bean 在整个 Spring 中只有⼀份,它是全局共享的,那么当其他⼈修改了这个值之后,那么另⼀个⼈读取到的就是被修改的值。

Bean 的6种作用域

Spring 容器在初始化⼀个 Bean 的实例时,同时会指定该实例的作⽤域。Spring有 6 种作⽤域,最后
四种是基于 Spring MVC ⽣效的:

  1. singleton:单例作⽤域
  2. prototype:原型作⽤域(多例作⽤域)
  3. request:请求作⽤域
  4. session:回话作⽤域
  5. application:全局作⽤域
  6. websocket:HTTP WebSocket 作⽤域

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

singleton

  • 官⽅说明:(Default) Scopes a single bean definition to a single object instance for each Spring IoC container.
  • 描述:该作⽤域下的Bean在IoC容器中只存在⼀个实例:获取Bean(即通过applicationContext.getBean等⽅法获取)及装配Bean(即通过@Autowired注⼊)都是同⼀个对象。
  • 场景:通常⽆状态的Bean使⽤该作⽤域。⽆状态表示Bean对象的属性状态不需要更新
  • 备注:单例模式默认的作用域,只有一个全局对象

prototype

  • 官⽅说明:Scopes a single bean definition to any number of object instances.
  • 描述:每次对该作⽤域下的Bean的请求都会创建新的实例:获取Bean(即通过applicationContext.getBean等⽅法获取)及装配Bean(即通过@Autowired注⼊)都是新的对象实例。
  • 场景:通常有状态的Bean使⽤该作⽤域
  • 备注:原型模式【多例默认】,每次访问都会创建一个新对象

request

  • 官⽅说明:Scopes a single bean definition to the lifecycle of a single HTTP request. That is,each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.
  • 描述:每次http请求会创建新的Bean实例,类似于prototype
  • 场景:⼀次http的请求和响应的共享Bean
  • 备注:限定SpringMVC中使⽤

session

  • 官⽅说明:Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.
  • 描述:在⼀个http session中,定义⼀个Bean实例
  • 场景:⽤户回话的共享Bean, ⽐如:记录⼀个⽤户的登陆信息
  • 备注:限定SpringMVC中使⽤

application

  • 官⽅说明:Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext.
  • 描述:在⼀个http servlet Context中,定义⼀个Bean实例
  • 场景:Web应⽤的上下⽂信息,⽐如:记录⼀个应⽤的共享信息
  • 备注:限定SpringMVC中使⽤

websocket

  • 官⽅说明:Scopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext.
  • 描述:在⼀个HTTP WebSocket的⽣命周期中,定义⼀个Bean实例
  • 场景:WebSocket的每次会话中,保存了⼀个Map结构的头信息,将⽤来包裹客户端消息头。第⼀次初始化后,直到WebSocket结束都是同⼀个Bean。
  • 备注:限定Spring WebSocket中使⽤

设置作用域

使⽤ @Scope 标签就可以⽤来声明 Bean 的作⽤域,@Scope 标签既可以修饰⽅法也可以修饰类,@Scope 有两种设置⽅式:

  1. 直接设置值:@Scope(“prototype”)
  2. 使⽤枚举设置:@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Component
public class DogBean {
    @Scope("prototype")
    @Bean
    public Dog dog() {
        Dog dog = new Dog();
        dog.setName("旺财");
        dog.setId(1);
        dog.setAge(5);
        return dog;
    }
}

这样设置完成后,A 用户的修改对 B 用户的使用就不会造成影响了。

Spring 执行流程

1、启动容器

Bean 作用域、生命周期和Spring执行流程,Java,spring,后端,Bean生命周期,Bean作用域

2、Bean 初始化

配置文件中的bean、配置了加载组件路径下的类进行扫描【看有没有类注解】
Bean 作用域、生命周期和Spring执行流程,Java,spring,后端,Bean生命周期,Bean作用域

3、注册Bean对象到容器中

通过五大注解来把对象注入到容器中,并且只有在包扫描路径上的类,且使用Spring的注解才可以被注册到容器中。
Bean 作用域、生命周期和Spring执行流程,Java,spring,后端,Bean生命周期,Bean作用域

具体参考博客:使用spring注解储存对象

4、装配Bean属性

如果Bean对象 需要使用其他Bean对象作为属性,可以使用注解@Autowired、@Resource
Bean 作用域、生命周期和Spring执行流程,Java,spring,后端,Bean生命周期,Bean作用域
具体参考博客:spring依赖注入

Bean 生命周期

Bean 作用域、生命周期和Spring执行流程,Java,spring,后端,Bean生命周期,Bean作用域

1、实例化

这是生命周期的第一步。在这个阶段,Spring会创建一个Bean的实例。这就像在工厂里制造一个产品一样,但在这里,Spring负责创建和管理Bean对象。

2、设置属性

一旦Bean实例化了,Spring会通过依赖注入的方式设置Bean的属性。这就像给产品添加特性和功能一样。你可以在配置文件中指定属性值,然后Spring会把这些值设置给Bean。

3、初始化

在这个阶段,Bean被初始化。你可以定义初始化方法,Spring会在设置属性后调用这些方法。这允许你在Bean准备好之前做一些额外的设置或者操作。

  1. 执行各种通知: 实现了各种 Aware 通知的方法,如 BeanNameAware、BeanFactoryAware、ApplicationContextAware 的接口方法;
  2. BeanPostProcessor的前置处理(postProcessBeforeInitialization): 如果在应用中定义了BeanPostProcessor接口的实现类,Spring会在Bean初始化之前调用这些实现类的postProcessBeforeInitialization方法。这提供了一个机会,你可以在Bean被初始化之前进行一些定制化的操作。
  3. 初始化方法(InitializingBean和init-method): 如果Bean实现了InitializingBean接口,Spring会在属性设置后调用它的afterPropertiesSet方法。执⾏ @PostConstruct 初始化⽅法,依赖注⼊操作之后被执⾏。此外,你还可以通过配置指定一个自定义的初始化方法(通常使用init-method属性)。在这个方法中,你可以执行任何你需要在Bean初始化时完成的逻辑。
  4. BeanPostProcessor的后置处理(postProcessAfterInitialization): 类似于前置处理,如果有BeanPostProcessor接口的实现类,Spring会在Bean初始化之后调用这些实现类的postProcessAfterInitialization方法。这个阶段可以用来进行一些额外的操作,例如修改Bean的属性或状态。

4、使用Bean

一旦Bean被初始化,它就准备好被使用了。你可以在应用程序的其他部分中引用并使用这个Bean,执行你所需的操作。这就像使用你制造的产品一样。

5、销毁Bean

当应用程序关闭或者不再需要Bean时,Spring会执行销毁操作。你可以定义销毁方法,在Bean不再需要时执行一些清理工作,比如关闭数据库连接或者释放资源。

生命周期演示

package com.fyd.controller;

import org.springframework.beans.factory.BeanNameAware;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class BeanLifeComponent implements BeanNameAware {
    @Override
    public void setBeanName(String name) {
        System.out.println("执行了 Bean Name 通知" + name);
    }


    public void init(){
        System.out.println("执行了 init 方法");
    }

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

    /**
     * 销毁前执行方法
     */
    @PreDestroy
    public void myPreDestroy(){
        System.out.println("执行了 myPreDestroy 方法");
    }

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

xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd ">


    <context:component-scan base-package="com.fyd"/>

    <bean id="beanlife" class="com.fyd.controller.BeanLifeComponent"
    init-method="init"></bean>
    
</beans>

调用代码

import com.fyd.controller.BeanLifeComponent;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanLifeTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");

        BeanLifeComponent beanLifeComponent = context.getBean("beanlife",BeanLifeComponent.class);
        beanLifeComponent.use();
        // 关闭容器
        context.destroy();

    }
}

执行结果:
Bean 作用域、生命周期和Spring执行流程,Java,spring,后端,Bean生命周期,Bean作用域文章来源地址https://www.toymoban.com/news/detail-657442.html

到了这里,关于Bean 作用域、生命周期和Spring执行流程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring(Bean 作用域和生命周期)

    目录 1. 案例1: Bean作用域的问题 2. 作用域 3. 设置 Bean 的作用域 4. Spring 的执行流程 5. Bean 的生命周期 现在有一个公共的 Bean,通过给 A 用户 和 B 用户使用, 然后在使用的过程中 A 偷偷的修改了公共 Bean 的数据, 导致 B 在使用时发生了预期之外的逻辑错误 (1) 公共 Bean:   [名称是

    2024年02月19日
    浏览(99)
  • Spring Bean作用域与生命周期

    目录 Bean的作用域: Bean有六大行为模式 1、singleton:单例模式(默认) 2、prototype: 原型模式(多例模式) 3、request: 请求作用域(Spring MVC) 4、session: 会话作用域(Spring MVC) 5、application: 全局作用域(Spring MVC) 6、websocket: HTTP WebSocket 作用域(Spring WebSocket) applicationContext和singleton的区别  Bea

    2024年02月02日
    浏览(42)
  • Spring | Bean 作用域和生命周期

    Spring 是用来读取和存储 Bean,因此在 Spring 中 Bean 是最核心的操作资源,所以接下来我们深入学习⼀下 Bean 对象 假设现在有⼀个公共的 Bean,提供给 A 用户和 B 用户使用,然而在使用的途中 A 用户却 “悄悄” 地修改了公共 Bean 的数据,导致 B 用户在使用时发生了预期之外的逻

    2024年02月14日
    浏览(40)
  • Spring Bean的作用域及生命周期

    目录 前言: Bean的作用域(Scope) 单例模式 原型模式(多例作用域) 请求作用域(request) 会话作用域 全局作用域 网络长连接 Spring执行流程 Bean的生命周期 测试 小结:     使用Spring框架时,我们需要清楚Spring托管Bean的作用域和生命周期,这样使用框架才会更加得心应手。

    2024年02月03日
    浏览(38)
  • Spring Bean的作用域和生命周期

    Bean 的作用域指的是 Bean 在 Spring 容器中的行为(Bean 实例创建及生命周期),它的行为是由 Spring 来管理的,可以根据具体情况选择不同的作用域来达到性能优化、资源利用最大化和可维护性等目的。 Bean 作用域(Scope)类型主要有如下几种: 其中前两种是 Spring 核心作用域,

    2024年02月12日
    浏览(55)
  • 【Spring】Bean的作用域和生命周期

    目录 一、引入案例来探讨Bean的作用域 二、Bean的作用域 2.1、Bean的6种作用域 2.2、设置Bean的作用域 三、Spring的执行流程  四、Bean的声明周期 1、生命周期演示 首先我们创建一个User类,定义一个用户信息,在定义一个Users类,使用方法注解将user存入Spring中,然后两个用户A对这

    2024年02月14日
    浏览(43)
  • 5、Spring之bean的作用域和生命周期

    5.1.1.1、配置bean 注意:当bean不配置scope属性时,默认是singleton(单例) 5.1.1.2、测试 由控制台日志可知,此时ioc获取到的两个bean本质上是同一个对象 5.1.2.1、配置bean 5.1.2.2、测试 由控制台日志可知,此时ioc获取到的两个bean本质上是不同的对象 如果是在WebApplicationContext环境下

    2024年02月14日
    浏览(45)
  • Spring系列4 -- Bean的作用域和生命周期

    目录 1. 案例 2. 作用域定义 2.1 Bean的6种作用域 2.2 设置作用域 3. Sring的执行流程 4. Bean的生命周期 思考: 为什么不是先进行初始化然后再进行设置属性呢?         假设现在有⼀个公共的 Bean,提供给 A ⽤户和 B ⽤户使⽤,然⽽在使⽤的途中 A ⽤户却“悄悄”地修改了公共

    2024年02月15日
    浏览(33)
  • 【Spring专题】Bean的生命周期流程图

    我向来不主张【通过源码】理解业务,因为每个人的能力有限,甚至可能会因为阅读错误导致出现理解上的偏差,所以我决定,还是先帮大家【开天眼】,先整体看看流程图,好知道,Spring在写源码的过程中到底干了啥事情。 对于【一、之前推测的简单流程图】大家可以不看

    2024年02月13日
    浏览(43)
  • 【框架源码】Spring源码解析之Bean生命周期流程

    观看本文前,我们先思考一个问题,什么是Spring的bean的生命周期?这也是我们在面试的时候,面试官常问的一个问题。 在没有Spring之前,我们创建对象的时候,采用new的方式,当对象不在被使用的时候,由Java的垃圾回收机制回收。 而 Spring 中的对象是 bean,bean 和普通的 J

    2024年02月09日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包