Bean的作用域和生命周期

变量的作用域

变量的作用域是指一个变量生效的范围,作用的范围。比如定义了一个类变量,就意味着类里面的所有方法都可以使用;如果变量定义在方法里面,就称为方法变量,方法变量只能在方法里面去使用。

Bean的作用域

Bean是Spring里面存储的对象,Bean的作用域指的是Bean对象在Spring容器里面的行为。

下面我们用一个例子来看Bean作用域问题:

  • 我们先创建一个公共类Users,调用getUser()方法可以或得一个公共的User对象,我们设置这个公共类的User的id为222,User的name为李四:
java 复制代码
package com.java.demo.model;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
// 公共类
@Component
public class Users {
    @Bean("user")
    public  User getUser(){
         User user=new User();
         user.setId(222);
         getUser().setName("李四");
         return  user;
    }
}
  • 假设有两个人需要对这个公共类进行改进,在这里我们用UserController2和UserController3来代表这两个人。
  • UserController2对公共对象的操作如下:
java 复制代码
import com.java.demo.model.User;
import com.java.demo.model.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class UserController2 {
    @Autowired
    private User user;
    public  void doMethod(){
        User  user2=user;
        System.out.println("UserController2修改之前"+user);
        user2.setName("张三");
        user2.setId(1111);
        System.out.println("UserController2修改之前:"+user);
    }
}

UserController2先定义了一个User类型的变量user2然后将user给user2,然后打印了一下修改之前的user,接着对user2进行id设置和name设置,最后打印一下修改后的user。
可以看到,公共对象user已经被修改了,id和name都被UserController2进行了修改。虽然UserController2是对user2进行了操作,可是还是改变了原本的user。

我们再看一下 UserController3:

java 复制代码
package com.java.demo.controller;

import com.java.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;

@Controller
public class UserController3 {
    @Autowired
    private User user;
    public void doMethod(){
        System.out.println("UserController3 的user:"+user);
    }
}

UserController3并没有对公共对象user进行任和操作,只是在doMethod方法里面打印了一下公共对象user。UserController3希望拿到的user是没有被改动的user,那我们来看一下代码执行的结果(我们在main方法里面,先调用UserController2的doMethod方法,再调用UserController3的doMethod方法):
代码执行结果:

结果发现,虽然UserController2重新定义了一个变量,然后进行修改,但是原来的公共对象依旧被改动了,导致UserController3拿到的公共对象user已经是被改动后的了。

导致这样结果的原因就是:

java 复制代码
  private User user;
   User  user2=user;

这里代码实际上定义一个User类型的变量,这个变量指向的是user对象,并没有新的对象。这时候使用user2去修改对象的时候,就相当于修改了user对象。

归根结底导致这个问题的原因就是Bean的作用域,Bean对象默认的是单例模式。(单例模式是指在程序的运行期间只有一份)。

  • 如何避免默认单例模式带来的问题?
    手动设置,通过@Scope注解,如@Scope("prototype")、prototype就是原型模式:
java 复制代码
package com.java.demo.model;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
// 公共类
@Component
public class Users {
    @Bean
    @Scope("prototype")
    public  User getUser(){
         User user=new User();
         user.setId(222);
        user.setName("李四");
         return  user;
    }
}

Bean作用域类型:

概念:Bean作用域指的是Bean在Spring容器中的某种行为,比如单例模式,比如原型模式等。

  1. singleton:单例作用域(默认的作用域)
    补充问题:单例模式的Bean是线程安全的吗?不是,因为所有人都可以操作这个公共变量,所以不是线程安全的,使用ThreadLocal可以变成线程安全的。
  2. prototype:原型作用域(多例模式)
  3. request:请求作用域,只适用于Spring MVC项目(就是Spring Web项目)
  4. session:回话作用域,一个Http会话共享一个Bean,是适用于Spring MVC项目。
  5. application:全局作用域,表示的是一个Context容器共享一个作用域。只适用于Spring MVC项目。
  6. websocket:Http WebSocket作用域,只适用于Webscoket作用域。

Spring的生命周期

  1. 启动容器
  2. 读取配置文件,进行Bean的实例化
  3. 将Bean加入到容器中
  4. 装配Bean属性(给当前类的属性赋值)

Bean的生命周期

  1. 实例化(内存空间的分配)
  2. 设置Bean属性(进行依赖注入,将依赖的Bean赋值到当前类的属性上)
  3. Bean的初始化
    3.1 执行各种通知
    3.2 初始化的前置方法
    3.3 初始化方法
    3.4 初始化的后置方法
  4. 使用Bean
  5. 销毁Bean
相关推荐
Bs_MoneyMagnet10 小时前
基于springboot+vue的心理咨询预约与随访平台的设计与实现 源码+文档
vue.js·spring boot·后端·spring·毕业设计·旅游·计算机毕业设计
步行cgn15 小时前
Spring 底层如何创建对象:反射机制与实例化策略
java·后端·spring
步行cgn17 小时前
Spring 注入 null 和空字符串详解
数据库·spring·oracle
Wang's Blog18 小时前
Java框架快速入门: Spring Security+OAuth2之单点登录(SSO)实战
服务器·spring·状态模式
譕痕18 小时前
Idea 集成 智能体开发工具“千问(qwen)”
java·ide·spring·语言模型
步行cgn19 小时前
Spring 注入内部 Bean 详解
java·spring·rpc
前端初见20 小时前
Java+AI零基础入门到大牛
java·spring boot·spring·java-ee·intellij-idea
天天喝旺仔20 小时前
深入理解 JWT:从 Token 结构、签名机制到前后端鉴权实战
redis·安全·spring·微服务·https
QQ_216962909621 小时前
基于SpringBoot+Vue的小生活平台的设计与实现
java·数据库·vue.js·spring boot·spring·微信小程序·生活
yxlalm21 小时前
SpringAI+RAG-检索文档变知识:从上传到精准检索的完整链路
spring·知识库·rag