JavaEE进阶学习:Bean 作用域和生命周期

1.Bean 作用域

.通过一个案例来看 Bean 作用域的问题

假设现在有一个公共的 Bean,提供给 A 用户和 B 用户使用,然而在使用的途中 A 用户却“悄悄”地修改了公共 Bean 的数据,导致 B 用户在使用时发生了预期之外的逻辑错误。

我们预期的结果是,公共 Bean 可以在各自的类中被修改,但不能影响到其他类。

package com.java.demo.model;

/**
 * @projectName: Demo
 * @package: com.java.demo.model
 * @className: User
 * @author: 王嘉辉
 * @description:
 * @date: 2023/11/28 16:18
 * @version: 1.0
 */
public class User {

    private int id;
    private String name;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

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

package com.java.demo.model;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

/**
 * @projectName: Demo
 * @package: com.java.demo.model
 * @className: Users
 * @author: 王嘉辉
 * @description:
 * @date: 2023/11/28 16:18
 * @version: 1.0
 */

/**
 * 公共类
 */
@Component
public class Users {

    /**
     * 公共对象
     * @return
     */
    @Bean("user")
    public User getUser() {
        User user = new User();
        user.setId(1);
        user.setName("凹凸曼");
        return user;
    }
}

package com.java.demo.controller;

/**
 * @projectName: Demo
 * @package: com.java.demo.controller
 * @className: UserController
 * @author: 王嘉辉
 * @description:
 * @date: 2023/11/26 21:36
 * @version: 1.0
 */

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

/**
 * 用户控制器 - 版本
 * 作者:李四
 */
@Controller
public class UserController {
    @Autowired
    private User user;

    public void doMethod() {

        System.out.println("UserController user -> " + user);
    }
}

package com.java.demo.controller;

/**
 * @projectName: Demo
 * @package: com.java.demo.controller
 * @className: UserController2
 * @author: 王嘉辉
 * @description:
 * @date: 2023/11/28 16:23
 * @version: 1.0
 */

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

/**
 * 用户控制器 - 版本2
 * 作者:张三
 */
@Controller
public class UserController2 {

    @Autowired
    private User user;

    public void doMethod() {
        User user2 = user;
        System.out.println("UserController2 修改之前: user -> " + user);
        user2.setName("三三");
        System.out.println("UserController2 修改之后: user -> " + user);
    }
}

import com.java.demo.controller.UserController;
import com.java.demo.controller.UserController2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @projectName: Demo
 * @package: com.java.demo
 * @className: App
 * @author: 王嘉辉
 * @description:
 * @date: 2023/11/28 16:31
 * @version: 1.0
 */
public class App {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

        UserController2 userController2 = context.getBean("userController2",UserController2.class);
        userController2.doMethod();

        UserController userController = context.getBean("userController",UserController.class);
        userController.doMethod();
    }
}

在这里插入图片描述

在这里插入图片描述
我们的Users 默认是单例模式,想要 公共 Bean 可以在各自的类中被修改,但不能影响到其他类

我们可以加一个作用域

在这里插入图片描述

1.什么叫作用域

Bean 作用域指的是 Bean 在 Spring 容器中的某种行为(单例,原型…)

2.Bean 的 6 种作用域

Spring 容器在初始化⼀个 Bean 的实例时,同时会指定该实例的作用域。Spring有 6 种作用域,最后四种是基于 Spring MVC 生效的:

  1. singleton:单例作用域
  2. prototype:原型作用域(多例作用域)
  3. request:请求作用域 (只适用于Spring MVC 项目)
  4. session:回话作用域 (一个 HTTP 会话共享一个Bean,只适用于Spring MVC 项目)
  5. application:全局作用域(表示的是一个 Context 容器共享一个作用域,只适用于Spring MVC 项目)
  6. websocket:HTTP WebSocket 作用域

单例模式的 Bean 是线程安全的么?

不是,使用TreadLocal(本地线程变量)

3.设置 Bean 的作用域

1.@Scope(“prototype”)

package com.java.demo.model;

import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/**
 * @projectName: Demo
 * @package: com.java.demo.model
 * @className: Users
 * @author: 王嘉辉
 * @description:
 * @date: 2023/11/28 16:18
 * @version: 1.0
 */

/**
 * 公共类
 */
@Component
public class Users {

    /**
     * 公共对象 -> 默认是单例模式
     * @return
     */
    @Bean(name = "user")
    @Scope("prototype") //原型模式 | 多例模式(每一次使用注解请求的时候,都会 new 一个新的之前对象)
    //@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public User getUser() {
        User user = new User();
        user.setId(1);
        user.setName("凹凸曼");
        return user;
    }
}

2.@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

package com.java.demo.model;

import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/**
 * @projectName: Demo
 * @package: com.java.demo.model
 * @className: Users
 * @author: 王嘉辉
 * @description:
 * @date: 2023/11/28 16:18
 * @version: 1.0
 */

/**
 * 公共类
 */
@Component
public class Users {

    /**
     * 公共对象 -> 默认是单例模式
     * @return
     */
    @Bean(name = "user")
    //@Scope("prototype") //原型模式 | 多例模式(每一次使用注解请求的时候,都会 new 一个新的之前对象)
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public User getUser() {
        User user = new User();
        user.setId(1);
        user.setName("凹凸曼");
        return user;
    }
}

2.Spring 执行流程和 Bean 的生命周期

1.执行流程

在这里插入图片描述

Bean 执行流程(Spring 执行流程):启动 Spring 容器 -> 实例化 Bean(分配内存空间,从无到有) -> Bean 注册到 Spring 中(存操作) -> 将 Bean 装配到需要的类中(取操作)。

2.Bean 的生命周期

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

  1. 实例化(内存分配空间)

  2. 设置 Bean 的属性(进行依赖注入,将依赖的 Bean 赋值到当前类的属性上)

  3. Bean 的初始化

  • 执行各种通知
  • 初始化的前置方法
  • 初始化方法
  • 初始化的后置方法
  1. 使用 Bean

  2. 销毁 Bean

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

import org.springframework.beans.factory.BeanNameAware;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * @projectName: untitled
 * @package: PACKAGE_NAME
 * @className: BeanLifeComponent
 * @author: 王嘉辉
 * @description:
 * @date: 2023/11/28 21:12
 * @version: 1.0
 */
public class BeanLifeComponent implements BeanNameAware {
    @Override
    public void setBeanName(String s) {
        System.out.println("执行了 BeanNameAware -> " + s);
    }
    @PostConstruct
    public void doPostConstruct() {
        System.out.println("执行了 @PostConstruct");
    }
    public void myinit() {
        System.out.println("执行了 myinit");
    }

    @PreDestroy
    public void doPreDestroy() {
        System.out.println("执行了 @PreDestroy");

    }

    public void useBean() {
        System.out.println("使用 Bean");
    }

}

import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @projectName: untitled
 * @package: PACKAGE_NAME
 * @className: BeanLifeTest
 * @author: 王嘉辉
 * @description:
 * @date: 2023/11/28 21:25
 * @version: 1.0
 */
public class BeanLifeTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        BeanLifeComponent component =
                context.getBean("mybean",BeanLifeComponent.class);
        component.useBean();
        context.close();
    }
}

<?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.java.demo"></content:component-scan>
    <bean id="mybean" class="BeanLifeComponent" init-method="myinit" ></bean>
</beans>

在这里插入图片描述

在这里插入图片描述
符合上述 Bean初始化 的流程

3.为什么要先设置属性在进行初始化

import com.java.demo.model.User;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * @projectName: untitled
 * @package: PACKAGE_NAME
 * @className: BeanLifeComponent
 * @author: 王嘉辉
 * @description:
 * @date: 2023/11/28 21:12
 * @version: 1.0
 */
public class BeanLifeComponent implements BeanNameAware {

    @Autowired
    private User user;

    @Override
    public void setBeanName(String s) {
        System.out.println("执行了 BeanNameAware -> " + s);
    }

    @PostConstruct
    public void doPostConstruct() {
        System.out.println("执行了 @PostConstruct");
        System.out.println(user.toString());
    }

    public void myinit() {
        System.out.println("执行了 myinit");
    }

    @PreDestroy
    public void doPreDestroy() {
        System.out.println("执行了 @PreDestroy");

    }

    public void useBean() {
        System.out.println("使用 Bean");
    }

}

在这里插入图片描述

在 Bean 的生命周期中,先设置属性再进行初始化的原因是因为在实例化 Bean 对象时,Spring 容器会调用 Bean 的构造方法创建 Bean 对象,并将对象的属性注入到 Bean 中。如果在初始化之前就进行依赖注入,那么被注入的属性可能还没有完全初始化,这样可能会导致对象状态不一致的问题。

当初始化 Bean 时,容器会调用 Bean 的初始化方法。这个时候,Bean 对象已经被完全初始化,可以安全地进行一些初始化操作。因此,先设置属性再进行初始化可以确保 Bean 对象的完整性和正确性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/198067.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

leaflet对线设置渐变色

效果展示&#xff1a; 引用leaflet-polycolor组件 npm install leaflet-polycolor .vue文件中使用 import leafletPolycolor from leaflet-polycolor; leafletPolycolor(L); const latLngs [[37.03, 111.92], [37.53444, 111.98555], [36.88, 112.12], [37.53444, 112.24], […

Redis深入理解-主从架构下内核数据结构、主从同步以及主节点选举

Redis 主从挂载后的内核数据结构分析 主节点中&#xff0c;会通过 clusteNode 中的 slaves 来记录该主节点包含了哪些从节点&#xff0c;这个 slaves 是一个指向 *clusterNode[] 数组的数据结构从节点中&#xff0c;会通过 clusterNode 中的 slaveof 来记录该从节点属于哪个主…

04_Flutter自定义Slider滑块

04_Flutter自定义Slider滑块 一.Slider控件基本用法 Column(mainAxisAlignment: MainAxisAlignment.start,children: <Widget>[Text("sliderValue: ${_sliderValue.toInt()}"),Slider(value: _sliderValue,min: 0,max: 100,divisions: 10,thumbColor: Colors.…

《微信小程序开发从入门到实战》学习三十四

4.2 云开发JSON数据库 MySQL、Oracle之类的“关系型数据库”。JSON数据库是“非关系型数据库”&#xff0c;没有行表列的概念。 4.2.1 JSON数据库基本概念 集合:一个数据库有多个集合&#xff0c;一个集合存储通常是同一类数据&#xff0c;可看作为JSON数组&#xff0c;数组…

webpack具体实现--未完

1、前端模块打包工具webpack webpack 是 Webpack 的核心模块&#xff0c;webpack-cli 是 Webpack 的 CLI 程序&#xff0c;用来在命令行中调用 Webpack。webpack-cli 所提供的 CLI 程序就会出现在 node_modules/.bin 目录当中&#xff0c;我们可以通过 npx 快速找到 CLI 并运行…

Chrome 访问不了项目?10080端口 ERR_UNSAFE_PORT:问题原因 / 解决方案

文章目录 被禁用端口列表解决方法方法一、更换端口 / 使用代理 / 使用域名方法二、对浏览器下手WindowsMac 最近有客户反馈&#xff0c;在chrome浏览器中访问不了项目&#xff0c;其他浏览器都是正常的。 &#xff1f;奇了怪了&#xff0c;难道客户对chrome做了什么操作&#x…

Asp.net core WebApi 配置自定义swaggerUI和中文注释

1.创建asp.net core webApi项目 默认会引入swagger的Nuget包 <PackageReference Include"Swashbuckle.AspNetCore" Version"6.2.3" />2.配置基本信息和中文注释&#xff08;默认是没有中文注释的&#xff09; 2.1创建一个新的controller using Micr…

直接插入排序和希尔排序

前言 我们前面几期介绍了线性和非线性的基本数据结构。例如顺序表、链表、栈和队列、二叉树等~&#xff01;本期和接下来的几期我们来详解介绍各个排序的概念、实现以及性能分析&#xff01; 本期内容 排序的概念以及其运用 常见的排序算法 直接插入排序 希尔排序 一、排序的…

Leetcode算法系列| 3. 无重复字符的最长子串

目录 1.题目2.题解C# 解法一&#xff1a;滑动窗口算法C# 解法二&#xff1a;索引寻找Java 解法一&#xff1a;滑动窗口算法Java 解法二&#xff1a;遍历字符串 1.题目 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示例1: 输入: s "ab…

力扣141-环形链表

文章目录 力扣141-环形链表示例代码实现要点剖析 力扣141-环形链表 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测…

源码剖析 Spring Security 的实现原理

Spring Security 是一个轻量级的安全框架&#xff0c;可以和 Spring 项目很好地集成&#xff0c;提供了丰富的身份认证和授权相关的功能&#xff0c;而且还能防止一些常见的网络攻击。我在工作中有很多项目都使用了 Spring Security 框架&#xff0c;但基本上都是浅尝辄止&…

C语言——输入两个正整数 m 和 n。求其最大公约数和最小公倍数。

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> int main() {int m, n;int i;int x 1;int y 0;printf("请输入两个正整数m和n&#xff1a;\n");scanf("%d,%d", &m, &n);for (i 1; i < m && i < n; i) {if (m % i 0 …

【doccano】文本标注工具——安装运行教程

笔记为自我总结整理的学习笔记&#xff0c;若有错误欢迎指出哟~ 【doccano】文本标注工具 doccano简介安装doccano1. 创建并激活虚拟环境2. 安装doccano 运行Doccano访问Doccano doccano简介 doccano是一个开源的文本注释工具。它为文本分类、序列标记和序列到序列任务提供注释…

Axios 并发请求指南 - 3 种简单实用的方法

在实际开发中&#xff0c;我们经常需要同时发送多个请求&#xff0c;并在所有请求完成后进行处理&#xff0c;这就是所谓的并发请求。实现 Axios 并发请求的关键是使用 Axios.all 方法&#xff0c;它接受一个 Promise 的数组作为参数&#xff0c;当这些 Promise 都 resolve 时&…

【C++】杨辉三角详解和C++代码示例

杨辉三角的每行第i个数是由上一行的第i-1个数和第i个数相加得到的&#xff0c;且每行的第一个数和最后一个数都是1&#xff0c;每行的中间个数等于它两肩上的数字相加。 目录 C代码输出结果8行输出15行输出25行输出 C代码 #include <iostream> #include <vector>…

Python Selenium 图片资源自动搜索保存 项目实践

实现访问首页 from os.path import dirnamefrom selenium import webdriverclass ImageAutoSearchAndSave:"""图片自动搜索保存"""def __init__(self):"""初始化"""self.driver webdriver.Chrome(executable_pa…

STK Components 二次开发- 卫星地面站

前期卫星地面站创建已经说过&#xff0c;本次说一下卫星和地面站可见性时卫星名称和轨迹线变色问题。 1.创建卫星 // Get the current TLE for the given satellite identifier. var tleList TwoLineElementSetHelper.GetTles(m_satelliteIdentifier, JulianDate.Now);// Us…

【VRTK】【VR开发】【Unity】9-瞬移

课程配套学习资源下载 https://download.csdn.net/download/weixin_41697242/88485426?spm=1001.2014.3001.5503 【移动的种类】 瞬移只是VR中移动的一种种类,其它还有连续移动,物理移动,摔臂移动等等。 瞬移自身也有多个分类,本篇介绍: 即时瞬移冲刺瞬移定点瞬移【瞬…

Linux CentOS_7解决无法上网的问题

参考视频&#xff1a;保姆式教学虚拟机联网liunx(centos)_哔哩哔哩_bilibili 配置网络&#xff1a;解决上网问题 第一步&#xff1a;选择网络模式 第二步&#xff1a;配置网卡命令&#xff1a;打开终端执行命令&#xff1a; 1、先切换到根目录下&#xff0c;防止在第执行cd …

在Mysql中,什么是回表,什么是覆盖索引,索引下推?

一、什么是回表查询&#xff1f; 通俗的讲就是&#xff0c;如果索引的列在 select 所需获得的列中&#xff08;因为在 mysql 中索引是根据索引列的值进行排序的&#xff0c;所以索引节点中存在该列中的部分值&#xff09;或者根据一次索引查询就能获得记录就不需要回表&#x…