• Bean的作用域和声明周期


    Bean的作用域

    Bean作用域的定义

    Bean 的作⽤域是指 Bean 在 Spring 整个框架中的某种⾏为模式,⽐如 singleton 单例作⽤域,就

    表示 Bean 在整个 Spring 中只有⼀份,它是全局共享的,那么当其他⼈修改了这个值之后,那么另⼀个⼈读取到的就是被修改的值

    Bean作用域的分类

    1. singleton:单例作⽤域

    2. prototype:原型作⽤域(多例作⽤域)

    3. request:请求作⽤域

    4. session:回话作⽤域

    5. application:全局作⽤域

    6. websocket:HTTP WebSocket 作⽤域

    【singleton 单例作用域】

    描述:该作⽤域下的Bean在***IoC容器***中只存在⼀个实例:获取Bean(即通过applicationContext.getBean等⽅法获取)及装配Bean(即通过@Autowired注⼊)都是同⼀个对象。

    场景:通常⽆状态的Bean使⽤该作⽤域。⽆状态表示Bean对象的属性状态不需要更新

    备注:Spring默认选择该作⽤域

    【prototype 多例作用域】

    描述:每次对该作⽤域下的Bean的请求都会创建新的实例:获取Bean(即通过applicationContext.getBean等⽅法获取)及装配Bean(即通过@Autowired注⼊)都是新的对象实例

    场景:通常有状态的Bean使⽤该作⽤域。有状态表示Bean对象的属性需要更新

    【request请求作用域】

    描述:每次http请求会创建新的Bean实例,类似于prototype

    场景:⼀次http的请求和响应的共享Bean

    备注:限定SpringMVC中使⽤

    【session会话作用域】

    描述:在⼀个http session中,定义⼀个Bean实例

    场景:⽤户回话的共享Bean, ⽐如:记录⼀个⽤户的登陆信息

    备注:限定SpringMVC中使⽤

    【application全局作用域(了解)】

    描述:在⼀个http servlet Context中,定义⼀个Bean实例

    场景:Web应⽤的上下⽂信息,⽐如:记录⼀个应⽤的共享信息

    备注:限定SpringMVC中使⽤

    【websocket HTTP WebSocket 作⽤域(了解)】

    描述:在⼀个HTTP WebSocket的⽣命周期中,定义⼀个Bean实例

    场景:WebSocket的每次会话中,保存了⼀个Map结构的头信息,将⽤来包裹客户端消息头。第⼀次初始化后,直到WebSocket结束都是同⼀个Bean
    备注:限定Spring WebSocket中使用

    如何设置Bean对象中的作用域

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

    1.直接设置作用域的具体值,如:@Scope(“prototype”);

    2.设置 ConfigurableBeanFactory 和 WebApplicationContext 提供的 SCOPE_XXX 变量,如 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)。

    注意:无论我们是使用类注解还是方法注解来将对象保存到Spring容器中,要改变该bean对象的作用域,只有在添加一个@Scope进行设置就行

    使用方法注解:

    @Component
    public class UserBeans {
        @Scope("prototype")
        @Bean("userService_1")
        public UserService getUserService() {
            return new UserService();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    使用类注解:

    @Controller
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public class UserController {
        public void doUserController() {
            System.out.println("do UserController.");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Spring的主要执行流程

    1. 启动容器

    2. Bean的初始化

    3. 将bean对象注册到Spring容器中(给bean对象开辟内存空间)

      配置文件中的bean、配置了加载文件路径的类的扫描(看看有没使用类注解或者方法注解)

    4. 装配bean对象的属性(对象注入)

    5. 使用bean对象

    6. Spring销毁

    Bean对象的生命周期

    所谓的生命周期就是,一个对象从创建到销毁的过程

    Bean对象的生命周期分为5大部分:

    1. 实例化bean对象(不是初始化bean对象,就是给bean对象分配内存空间)

    2. 设置bean属性(对象注入)

    3. 初始化bean

      1. 执行各种通知,如 BeanNameAware、BeanFactoryAware、

        ApplicationContextAware 的接⼝⽅法;

      2. 初始化的前置方法(xml配置文件bean标签有init-method属性来设置前置方法,@PostConstruct注解也能解决这问题,只有在方法前加上这个注解就行)

      3. 初始化方法

      4. 初始化的后置方法

    4. 使用bean对象

    5. 销毁bean对象(xml配置文件bean标签里有destroy-method属性来指定bean对象在销毁时使用哪个方法,@PreDestroy注解也能解决这个问题,在哪个方法前加上这个就行了)

    生命周期代码演示

    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public class UserController implements BeanNameAware {
        @Autowired
        public UserService userService;
        public UserController() {
            System.out.println("无参构造方法:UserController()");
        }
    
        public void init() {
            System.out.println("通过xml配置文件来设置前置方法:UserController.init()");
        }
        @PostConstruct
        public void before() {
            System.out.println("通过注解来设置化前置⽅法:UserController.before()");
        }
        public void doUserController() {
            System.out.println("bean对象的使用");
        }
    
        @Override
        public void setBeanName(String s) {
            System.out.println("Aware 通知:"+s);
        }
        @PreDestroy
        public void destroy() {
            System.out.println("bean对象的销毁:UserController.destroy()");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    @Service
    public class UserService implements BeanNameAware {
        public UserService() {
            System.out.println("无参构造方法:UserService()");
        }
    
        @PostConstruct
        public void before() {
            System.out.println("通过注解来设置化前置⽅法:UserService.before()");
        }
        @PreDestroy
        public void destroy() {
            System.out.println("bean对象的销毁:UserService.destroy()");
        }
        public void doUserService() {
            System.out.println("do UserService.");
        }
    
        @Override
        public void setBeanName(String s) {
            System.out.println("Aware 通知:"+s);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    xml配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:content="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
        <!-- 配置扫描注解的路径   -->
        <content:component-scan base-package="com"></content:component-scan>
        <bean id="userController" class="com.wwj.controller.UserController" init-method="init"></bean>
    </beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    Oracle -- 视图与序列
    php对接微信支付简要流程?面试时你会描述吗?
    jupyter/scipy-notebook:python3.8 docker 镜像
    Excel 可视化教程之可视化的科学与艺术
    OC-编译错误
    领英如何批量添加搜索的人脉,批量加领英推荐人脉,批量加精灵推荐人脉,批量加Groups成员,通过链接批量加人
    【C++基础】观察者模式(“发布-订阅”模式)
    Socket套接字(Java)
    Java项目:SSM图书销售进销存管理系统
    javaBS景区票务管理系统设计与实现计算机毕业设计MyBatis+系统+LW文档+源码+调试部署
  • 原文地址:https://blog.csdn.net/weixin_62877993/article/details/127871631