Spring中Bean的作用域和生命周期

Bean的作用域

我们知道传统意义上的作用域就是一个一个变量限定在程序的可用范围或者源代码中某个变量定义的某个区域叫做作用域!
我们Spring中的Bean作用域并不是传统意义上的定义,Spring下的Bean的作用域指的是一个Bean对象的在Spring下的行为模式,就列如我们知道的单例模式singleton就是Bean的一种作用域!

Bean的六种作用域

  • singleton 单例作用域(默认)
  • prototype 原型作用域(多例模式)
  • request 请求作用域(SpringMVC)
  • session会话作用域(SpringMVC)
  • application 全局作用域(SpringMVC)
  • websocketHTTP WebSocket作用域(Spring WebSocket)

singleton单例作用域
该作用域下的Bean在IoC容器下只存在一个实例!
所以对该bean进行注入,装配bean都是同一个对象!
Spring默认作用域

当我们创建一个Bean注册到Spring中后,如果有2个类需要注入该Bean!一类进行读取操作,另一个类进行修改操作!如果修改操作在前,那另一个类读取的操作就会读到脏数据,本来想读取到的是Bean初始值,结果读取到了另一个类修改后的数据!,这就说明Bean对象在Spring下是共享的,一个bean对象是单例!当注入时,是多个类共享的!

//创建User Bean对象!
public class User {
    private String name;
    private int id;

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

    public String getName() {
        return name;
    }

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

//将Bean 注册到Spring中!
@Component
public class Users {
    @Bean //将对象注册到spring中!
    public User getUser(){
        User user = new User();
        user.setId(666);
        user.setName("java");
        return user;
    }
}

//User1进行读操作!
@Controller
public class UserController1 {
    //注入对象!
    @Autowired
    private User user;
    public User getUser() {
        return user;
    }
}

//User2进行修改操作!
@Controller
public class UserController2 {
    @Autowired //注入对象!
    private User user;
    //将user对象改了!
    public User getUser() {
        user.setName("C++");
        user.setId(999);
        return user;
    }
}
//先修改Bean后读取
//启动类!!!
public class app {
    public static void main(String[] args) {
        //获取上下文!
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        //user2把bean对象改了!
        UserController2 userController2 = context.getBean(UserController2.class);
        System.out.println(userController2.getUser());
        //user1正在读取bean! 预期读取结果是 java 666 因为这是bean注册的初始值!
        UserController1 userController1 = context.getBean(UserController1.class);
        System.out.println(userController1.getUser());
    }
}

运行结果
在这里插入图片描述
User1读取到的是修改后的Bean!

Bean在Spring默认的作用域是singleton

prototype原型作用域(多例作用域)
Spring中对同一个Bean,进行注入装箱每个类获取到的bean都是一个新的实例对象!
通常有动态Bean使用该作用域

request请求作用域
每一次http请求都会创建一个新的Bean实例.类似于prototype作用域
一次http请求和响应的共享Bean
限定于SpringMVC中使用

session会话作用域
在一次http session中定义一个Bean实例
用户会话的共享Bean ,比如通过这个作用域记录一个用户的登入信息!
限定于SpringMVC中使用

application全局作用域
在一个http servlet Context中定义一个Bean实例
Web应用的上下文信息,例如记录应用的共享信息
限定于SpringMVC中使用

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

singleton和application对比

  • singleton是Spring Core的作用域 application是Spring Web的作用域
  • singleton作用于IoC容器,application作用于Servlet容器中

Bean的生命周期

Bean的执行流程
在这里插入图片描述
Bean对象执行流程

启动Spring容器 —>实例化Bean(分配内存空间,从无到有) —>
Bean注册到Spring中(存操作) —>将Bean装配到需要用的类中(取操作)

Bean生命周期

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

Bean 的生命周期分为以下 5 大部分:
1.实例化 Bean(为 Bean 分配内存空间)
2.设置属性(Bean 注入和装配)
3.Bean 初始化

  • 实现了各种 Aware 通知的方法,如 BeanNameAware、BeanFactoryAware、ApplicationContextAware 的接口方法;
  • 执行 BeanPostProcessor 初始化前置方法;
  • 执行 @PostConstruct 初始化方法,依赖注入操作之后被执行;
  • 执行自己指定的 init-method 方法(如果有指定的话);
  • 执行 BeanPostProcessor 初始化后置方法。

4.使用 Bean
5.销毁 Bean

销毁容器的各种方法,如 @PreDestroy、DisposableBean 接口方法、destroy-method。

执行流程如下图所示
在这里插入图片描述
实例化和初始化区别

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

简单说就是实例化只是分配了内存空间,并没有进行其他操作!
而初始化是真正创建了一个实例,给这块空间存放了数据!

我们拿买房举例理解Bean生命流程

  • 实例化(买了一套房)
  • 设置属性(装修)
  • 初始化(买家电,家具各种初始化)
  • 使用Bean(入住使用房间)
  • 销毁Bean(将房子卖了)

在这里插入图片描述

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

bug 郭

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

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

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

打赏作者

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

抵扣说明:

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

余额充值