【Spring】Bean的作用域与生命周期

Bean作用域问题引入

假设有一个Bean对象,但是A用户在使用的时候将Bean对象的数据修改了,导致B用户在使用的时候发生了预期之外的逻辑错误

有一个对象为Animal

public class Animal {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Animal{" +
                "name='" + name + '\'' +
                '}';
    }
}

将该对象注入到Spring容器中

@Component
public class Animals {

    @Bean
    public Animal animal(){
        Animal animal = new Animal();
        animal.setName("老虎");
        return animal;
    }
}

A用户使用Bean对象时,进行了修改操作

@Controller
public class AnimalController1 {

    @Autowired
    private Animal animal;

    public void getAnimal(){
        Animal animal = this.animal;
        animal.setName("大象");
        System.out.println(animal);
    }
}

B用户在去使用Bean对象

@Controller
public class AnimalController2 {
    
    @Autowired
    private Animal animal;
    
    public void getAnimal(){
        System.out.println(animal);
    }
}

打印A用户和B用户公共Bean的值

public class App4 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        AnimalController1 animalController1 = context.getBean(AnimalController1.class);
        animalController1.getAnimal();

        System.out.println("---------");
        
        AnimalController2 animalController2 = context.getBean(AnimalController2.class);
        animalController2.getAnimal();
    }
}

打印结果:都打印了A用户修改后的值

打印结果

出现上述结果的原因是Bean默认是单例作用域,也就是所有用户使用的都是同一个对象,但是我们想要的结果是公共Bean可以被用户在自己的类中修改,但是不能影响到其他类,那该如何做?

了解了下面Bean的作用域后,答案自然知晓

Bean的作用域

Bean的作用域指的是Bean在整个Spring框架中的某个行为模式,比如singleton单例作用域表示Bean在整个Spring中只有一份,是全局共享的,当有一个用户修改了这个对象后,其他用户获取的就是这个修改后的对象

Bean的作用域有六种:

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

注意: 后四种是基于Spring MVC生效的,普通的Spring项目中只有前两种

singleton

该作用域下的Bean在IoC容器中只存在一个实例,通常无状态的Bean使用该作用域,无状态表示Bean对象无人修改,该作用域是Spring默认作用域,这就是上述问题原因的所在

prototype

每次对该作用域下的Bean的请求都会创建新的实例,通常有状态的Bean使用该作用域,有状态表示Bean对象有人修该,对于上述问题,就可以将Bean的作用域设置为prototype

request

每次http请求会创建新的Bean实例,一次HTTP的请求和响应共享一个Bean对象实例,限定SpringMVC中使用

session

每个HTTP会话中,都会创建Bean实例,用户会话共享Bean, 比如记录一个用户的登陆信息,限定SpringMVC中使用

application

在一个HTTP Servlet上下文中,定义一个Bean实例,Web应用的上下文信息,比如,记录一个应用的共享信息,限定SpringMVC中使用

websocket

在一个HTTP WebSocket的生命周期中,定义一个Bean实例,WebSocket的每次会话中,保存了一个Map结构的头信息,用来包裹客户端消息头,第一次初始化后,直到WebSocket结束都是同一个Bean
限定Spring WebSocket中使用

解决上述问题

通过了解Bean的作用域,可以得到Bean的作用域为prototype,来解决上述问题

Bean作用域的设置方式:

  1. @Scope(“prototype”)
  2. @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

在存储Bean对象的时候添加上述注解,两种方式任选择一种

对上述代码进行修改:只需要在存储Bean时,添加上述两个注解中的一个即可

@Component
public class Animals {

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public Animal animal(){
        Animal animal = new Animal();
        animal.setName("老虎");
        return animal;
    }
}

打印结果

Bean的生命周期

Bean的生命周期就是一个Bean对象从诞生到销毁的过程

Bean的生命周期分为以下五个步骤:

  1. 实例化Bean

为Bean分配内存空间

  1. 设置属性

Bean注入和装配

  1. 初始化Bean

执行各种Aware通知,如 BeanNameAware,BeanFactoryAware、ApplicationContextAware 的接口方法
执行初始化的前置方法
执行构造方法,两种执行方式,一种是@PostConstruct,另一种是自己指定的init-method方法
执行初始化的后置方法

  1. 使用Bean
  2. 销毁Bean

销毁Bean的各种方法,@PreDestroy,DisposableBean接口方法,指定的destroy-method方法

流程如下图:

Bean生命周期

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Spring Bean 的作用域生命周期Spring 框架中非常重要的两个概念,这里简单介绍一下。 1. Bean 的作用域Spring 中,Bean 的作用域指的是 Bean 实例的创建和销毁的范围。Spring 提供了以下五种作用域: - singleton:单例模式,容器中只有一个 Bean 实例,所有对 Bean 的请求都将返回同一个实例。 - prototype:每次请求都会创建一个新的 Bean 实例。 - request:每个 HTTP 请求都会创建一个新的 Bean 实例。 - session:每个 HTTP Session 都会创建一个新的 Bean 实例。 - global session:基于 Servlet 3.0+ 的环境下,每个全局的 HTTP Session 都会创建一个新的 Bean 实例。 2. Bean 的生命周期 Bean 的生命周期指的是 Bean 实例从创建到销毁的整个过程。Spring 提供了以下七个阶段: - 实例化 Bean:Spring 根据 Bean 的定义创建一个 Bean 的实例。 - 设置 Bean 属性:Spring 将配置文件中的属性设置到 Bean 实例中。 - BeanNameAware:如果 Bean 实现了 BeanNameAware 接口,SpringBean 的 ID 传递给 setBeanName 方法。 - BeanFactoryAware:如果 Bean 实现了 BeanFactoryAware 接口,SpringBeanFactory 实例传递给 setBeanFactory 方法。 - InitializingBean:如果 Bean 实现了 InitializingBean 接口,Spring 将调用 afterPropertiesSet 方法。 - 自定义初始化方法:Bean 可以配置自定义的初始化方法。 - DisposableBean:如果 Bean 实现了 DisposableBean 接口,Spring 将调用 destroy 方法。 - 自定义销毁方法:Bean 可以配置自定义的销毁方法。 以上就是 Spring Bean 的作用域生命周期的简单介绍。理解 Bean 的作用域生命周期对于正确使用 Spring 框架非常重要。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

X_H学Java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值