Bean的作用域和生命周期

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

Bean的作用域

Bean是Spring里面存储的对象,Bean的作用域指的是Bean对象在Spring容器里面的行为
下面我们用一个例子来看Bean作用域问题:

  • 我们先创建一个公共类Users,调用getUser()方法可以或得一个公共的User对象,我们设置这个公共类的User的id为222,User的name为李四:
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对公共对象的操作如下:
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:

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已经是被改动后的了。
导致这样结果的原因就是:

  private User user;
   User  user2=user;

这里代码实际上定义一个User类型的变量,这个变量指向的是user对象,并没有新的对象。这时候使用user2去修改对象的时候,就相当于修改了user对象。
归根结底导致这个问题的原因就是Bean的作用域,Bean对象默认的是单例模式。(单例模式是指在程序的运行期间只有一份)。

  • 如何避免默认单例模式带来的问题?
    手动设置,通过@Scope注解,如@Scope(“prototype”)、prototype就是原型模式:
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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值