@Autowired和@Resource注解之间的关系区别,Bean的作用域和生命周期,Spring的执行流程

news2024/11/24 9:06:26

目录

一. @Autowired 和 @Resource 注解

二. Bean的作用域 

1. singleton(单例模式)

2. prototype(原型模式)(多例模式)

3. 请求作用域:request

4. 会话作用域:session

三. Spring 的执行流程

四. Bean 的生命周期 

 1. 实例化

 2. 设置属性 

3. Bean 初始化  

   3.1 执行各种各种 Aware 通知; 

   3.2 执行初始化前置方法;

   3.3 执行初始化方法;

   3.4 执行初始化后置方法; 

4. 使用 Bean 对象

5. 销毁 Bean 对象 

6. 代码演示 


一. @Autowired 和 @Resource 注解

在前面的文章中,我们介绍了通过 @Autowired 注解的方式来获取到Spring容器中的Bean对象,实际上,还有另一个注解:@Resource,它的功能也是差不多的,也可以从 Spring容器中获取到Bean对象,但也是存在一定的差别的。 

  1. @Resource 来自于 jdk,而 @Autowired 来自于 Spring;
  2. 使⽤时设置的参数不同:相⽐于 @Autowired 来说,@Resource ⽀持更多的参数设置,例如
    name 设置,根据名称获取 Bean;
  3. @Autowired 可⽤于 Setter 注⼊、构造函数注⼊和属性注⼊,⽽ @Resource 只能⽤于 Setter 注⼊和属性注⼊,不能⽤于构造函数注⼊;
  4. @Autowired在获取Bean对象的时候,先根据类型查找,之后再根据名称查找;而@Resource先根据名称查找,之后再根据类型查找;

问题分析:当在 Spring 中存放多个同一类型 Bean 对象的时候,使用 @Autowired 去获取 Bean对象会出错。

@Component
public class UserBeans {
    @Bean
    public User user1(){
        User user = new User();
        user.setAge(20);
        user.setId(1);
        user.setName("张三");
        return user;
    }

    @Bean
    public User user2(){
        User user = new User();
        user.setAge(22);
        user.setId(11);
        user.setName("李四");
        return user;
    }
}
@Controller
public class UserController2 {
    @Autowired
    private User user;

    public void sayHi(){
        System.out.println("do UserController2");
        System.out.println(user.getName());
    }
}

public class App {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
    UserController2 userController2 = context.getBean("userController2",UserController2.class);
        userController2.sayHi();
    }
}

此时执行是会报错的,因为 @Autowired 注解先通过类型去查找,得到了 user1 和 user2 两个 Bean对象,但是根据 user 名称来去查找的话,是没有找到对应的 Bean 对象的,因此会报错。(查找 Bean 对象的默认名称为 添加 @Autowired 注解的对应属性名称,也就是上述第二段代码的private User user

 解决办法1:修改 @Autowired 注解的对应属性名称

@Controller
public class UserController2 {
    @Autowired
    private User user1;

    public void sayHi(){
        System.out.println("do UserController2");
        System.out.println(user1.getName());
    }
}

此时运行代码就会获取到对应的 Bean对象,也就是存储的 user1 对象。

 

解决办法2:配合使⽤ @Qualifier 注解定义名称

@Qualifier(value = "Bean对象的名称") 

@Controller
public class UserController2 {
    @Autowired
    @Qualifier(value="user1")
    private User user;

    public void sayHi(){
        System.out.println("do UserController2");
        System.out.println(user.getName());
    }
}

也可以得到预期的结果。 

 

解决办法3:使⽤ @Resource(name="Bean对象名称") 定义

@Controller
public class UserController2 {
    
    @Resource(name="user1")
    private User user;

    public void sayHi(){
        System.out.println("do UserController2");
        System.out.println(user.getName());
    }
}

 同样是可以得到预期结果的。

 

二. Bean的作用域 

限定程序中变量的可⽤范围叫做作用域,或者说在源代码中定义变量的某个区域就叫做作用域。而 Bean 的作⽤域是指 Bean 在 Spring 整个框架中的某种行为模式。

1. singleton(单例模式)

singleton 表示的是单例作用域,类似于之前讲过的单例模式。这也是默认情况下的行为模式。在该作用域下的 Bean 在 IoC容器中只存在一个实例,获取到的 Bean 以及对 Bean 进行修改,都是针对同一个 Bean 对象。

代码演示: 

1. 往 Spring 容器中注入一个 User 对象 

@Component
public class UserBeans {
    @Bean
    public User user(){
        User user = new User();
        user.setId(1);
        user.setName("张三");
        return user;
    }
}

2.  通过@Autowired获取到Bean对象,并对其进行修改

@Controller
public class UserController {
    @Autowired
    private User user;

    public void printUser(){
        System.out.println(user);
        // 修改 User
        User myUser = user;     // 给引用对象赋值,其实就是共享对象!!!这两个变量指向了同一个地址
        myUser.setName("李四");
        System.out.println("myUser -> " + myUser);
        System.out.println("User -> " + user);  
    }
}

3. 再新建一个类,通过 @Autowired 获取到Bean对象 


@Controller
public class UserController2 {

    @Resource
    private User user;

    public void printUser2(){
        System.out.println("user -> " + user);  
        // Bean 作用域 -> 默认是单例模式 = 此 Bean 在整个框架(Spring 容器)中只有一份
    }
}

 4. 最后输出观察结果


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

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

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

    }
}

因此也可以得出结论:singleton 单例作用域,他们使用的 Bean 都是 Spring 容器中的同一个对象。这个 Bean 在整个 Spring 中只有一份,是全局共享的,当其他人修改了这个值之后,那么另一个人读到的就是被修改后的值了。

2. prototype(原型模式)(多例模式)

 在原型模式下,每次对该作用域下的 Bean 的请求都会创建新的实例,也就是说每次获取 Bean 对象和修改 Bean 对象都是针对新的 Bean 对象实例而言的。

需要添加注解 @Scope("prototype") 或者@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

代码演示: 

@Component
public class UserBeans {
    @Bean
    @Scope("prototype")
    //@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public User user(){
        User user = new User();
        user.setId(1);
        user.setName("张三");
        return user;
    }
}

 再次运行得到结果:

可以看出,在第二次通过 @Autowired 获取到 Bean 对象的时候,得到的是一个新的实例对象了。

3. 请求作用域:request

 每次 http 请求会创建新的 Bean 实例。适用于⼀次 http 的请求和响应的共享 Bean 的情况。

 限定SpringMVC中使⽤。

4. 会话作用域:session

在⼀个http session中,定义⼀个 Bean 实例。每次 Session 会话共享一个 Bean 对象。限定SpringMVC中使⽤。

 

三. Spring 的执行流程

 

 

四. Bean 的生命周期 

 1. 实例化

给 Bean 对象分配内存空间。 

此处要注意:初始化不等于实例化!!!

类的初始化是完成程序前的准备工作,在这个阶段,静态的会被执行,同时会开辟一块存储空间用来存放静态的数据,初始化只在类加载的时候执行一次,也可以理解为给对象赋值的过程。

类的实例化,是指创建一个对象的过程,这个过程会在堆中开辟内存,将一些非静态的方法,变量存放在里面,在程序执行的过程中,可以创建多个对象,即多次实例化,每次实例化都会开辟一块新的内存。 

 2. 设置属性 

看需求,有的 Bean 对象需要被注入属性,这个属性也会是已经在 Spring 容器中的 Bean,如果该属性还不存在于 Spring 中,那么会先去将该属性 Bean 存储到 Spring 中。 

3. Bean 初始化  

   3.1 执行各种各种 Aware 通知; 

实现了各种 Aware 通知的⽅法,如 BeanNameAware、BeanFactoryAware、
ApplicationContextAware 的接⼝⽅法;

   3.2 执行初始化前置方法;

   3.3 执行初始化方法;

有两种方式,第一种是通过注解 @PostConstruct ,依赖注⼊操作之后执行注解修饰的方法;第二种是通过 xml 的方式,执行自己指定的 init-method ⽅法。如果两者都存在,那么先执行注解的初始化方法。

 

   3.4 执行初始化后置方法; 

 

4. 使用 Bean 对象

通过 getBean() 方法来获取容器中的 Bean 对象并使用。 

5. 销毁 Bean 对象 

销毁容器的各种⽅法,如 @PreDestroy、DisposableBean 接⼝⽅法、destroy-method(XML的方式)。  

6. 代码演示 

public class App {
    public static void main(String[] args) {
// 此时要使用 ApplicationContext 的子类,因为它本身是没有销毁方法的
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        BeanComponent beanComponent = context.getBean("beanComponent",BeanComponent.class);
        beanComponent.sayHi();
        context.close();
    }
}

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

    /**
     * xml 方式的初始化方法
     */
    public void myInit(){
        System.out.println("XML 方式初始化");
    }


    @PostConstruct
    public void doPostConstruct(){
        System.out.println("注解的初始化方法");
    }

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

    // 销毁的方法,销毁的时候执行的一个方法
    @PreDestroy
    public void doPreDestroy(){
        System.out.println("do PreDestroy");
    }
}

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构初阶】环形链表

目录 一、判断链表中是否存在环思路分析 二、求环的长度三、求入环点 一、判断链表中是否存在环 题目链接: 判断链表中是否存在环 思路 把它转换为追击问题(快慢指针) 快指针比慢指针多走一步,当快指针正好进入环时,慢…

脑科学数据挖掘论文精读系列(1)【抑郁对大脑神经影响和对脊椎损伤患者运动恢复的影响探究】

Depression mediated the relationships between precentral-subcortical causal links and motor recovery in spinal cord injury patients 手动防爬虫,原创作者CSDN:总是重复名字我很烦啊,联系邮箱daledeng123163.com直达原文 这是一篇收…

操作系统——操作系统用户界面

0.关注博主有更多知识 操作系统入门知识合集 目录 3.1操作系统启动过程 3.1.1BIOS和主引导记录MBR 思考题: 3.1.2操作系统的启动过程 思考题: 3.2用户界面 3.2.1用户界面概念 思考题: 3.2.2系统调用 3.1操作系统启动过程 3.1.1BIO…

【五一创作】使用Resnet残差网络对图像进行分类(猫十二分类,模型定义、训练、保存、预测)(一)

使用Resnet残差网络对图像进行分类 (猫十二分类,模型定义、训练、保存、预测)(一) 目录 一、项目简介 二、环境说明 1、安装库 2、导入需要的库 三、分类过程 (1)、解压数据集 (2&#xf…

Spring中的Bean

1. Bean的配置 Spring 可以被看作是一个大型工厂,这个工厂的作用就是生产和管理 Spring 容器中的Bean。如果想要在项目中使用这个工厂,就需要开发者对Spring 的配置文件进行配置。 Spring 容器支持XML 和 Properties 两种格式的配置文件,在实…

【Python Web】Flask超实用基础知识总结(内附代码)

Flask是一种轻量级Web应用框架,使用Python编写。它是一个简单易用的框架,适合构建小型到中型的Web应用程序。Flask提供了基本的Web开发功能,如路由、请求处理、模板渲染、文件上传等。 下面是Flask的一些基础语法 文章目录 1.静态文件处理2.…

【建议收藏】计算机视觉是什么?这几个计算机视觉的核心任务你真的了解吗?

文章目录 📚引言📖计算机视觉的核心任务📑图像分类和对象识别📑目标检测📑语义分割📑实例分割📑图像生成 📖计算机视觉的应用领域📑人脸识别📑自动驾驶&#…

【论文阅读】LORA: LOW-RANK ADAPTATION OF LARGE LAN- GUAGE MODELS

3.最近很多工作好像都绕不开lora,无论是sd还是llm.... 1. 背景 问题:大模型重新训练所有模型参数的完全微调变得不太可行。lora在做什么 我们提出了低秩自适应,即LoRA,它冻结预先训练的模型权重,并将可训练的秩分解矩…

高级数据结构 Trie树(字典树)

高级数据结构 Trie树(字典树) (Trie Tree)字典树_Rkun18的博客-CSDN博客 字典树节点表示 #define TRIE_MAX_CHAR_NUM 26 //这里你可以自由设置 根据不同需求设置 如果有大小或者其他符号你就需要增大这个数字struct TrieNode{T…

在amd64与arm上用paddlelite部署paddelOCR(Ascend硬件)

由于部署的硬件是华为昇腾 NPU(Ascend310),参考网址https://www.paddlepaddle.org.cn/lite/v2.10/demo_guides/huawei_ascend_npu.html#npu-paddle-lite 先拉取paddlelite用来编译库 git clone https://github.com/PaddlePaddle/Paddle-Lit…

2. Java 异常体系

2.1 Throwable java.lang.Throwable 类是 Java 程序执行过程中发生的异常事件对应的类的根父类。 Throwable 中的常用方法: public void printStackTrace():打印异常的详细信息。 包含了异常的类型、异常的原因、异常出现的位置、在开发和调试阶段都得…

倾斜摄影超大场景的三维模型轻量化纹理压缩的关键技术

倾斜摄影超大场景的三维模型轻量化纹理压缩的关键技术 倾斜摄影超大场景的三维模型轻量化处理中纹理压缩是轻量化处理的重要手段之一,可以在保证模型真实感的前提下,减小数据体积、降低传输带宽和提高渲染性能。以下是几个关键的纹理压缩技术&#xff1a…

自然语言处理知识抽取(pkuseg、DDParser安装及使用)

一、分词简介 1.基本概念 分词是自然语言处理中的一个重要步骤,它可以帮助我们将文本分成一个个词语,以便更好地理解和分析文本。在计算机视觉、语音识别、机器翻译等领域,分词都扮演着重要的角色。 目前,常用的分词库包括 jie…

搭建Redis主从集群+哨兵+代理predixy

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、Redis是什么?二、搭建Redis集群步骤1.环境和版本2.Redis 安装部署3.主从同步配置4.哨兵模式配置5.代理predixy配置 总结 前言 提示&#xff1a…

深度学习 -- Dataset与DataLoader

前言 在模型训练的步骤中,数据的部分非常重要,它的过程主要分为数据收集、数据划分、数据读取、数据预处理。 数据收集的有原始样本和标签(Img,label) 数据集的划分需要分为训练集、验证集、测试集。 训练集负责训练模型,验证集…

【C++】C++11常用特性总结

哥们哥们,把书读烂,困在爱里是笨蛋! 文章目录 一、统一的列表初始化1.统一的{}初始化2.std::initializer_list类型的初始化 二、简化声明的关键字1.decltype2.auto && nullptr 三、STL中的一些变化1.新增容器:array &…

趣说数据结构(练习2) —— 顺序表/链表力扣刷题(中等难度)

练习 2 —— 顺序表/链表力扣刷题&#xff08;中等难度&#xff09; 1. 反转链表 II 力扣原题&#xff1a;https://leetcode.cn/problems/reverse-linked-list-ii/ 题目描述 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从…

数据可视化大屏的页面布局以及自适应

在做数据可视化大屏之前&#xff0c;我们需要考虑到页面的布局问题以及页面缩放自适应问题&#xff0c;下面分别就这两个方面讲解。 页面布局 类似这种页面区块的明显划分&#xff0c;常用的布局方式有两种&#xff1a; 1、flex布局 2、grid布局 grid布局 grid布局可以按区块…

山东专升本计算机第二章-Windows7操作系统

Windows7操作系统 2.3Windows7的文件和文件夹管理 考点7 Windows7的基础知识 文件&#xff0c;是指存放在外存储器上的一组相关信息的•集合 文件名是操作系统中区分不同文件的唯一标志 文件名是由主文件名和扩展名两部分组成不能使用 ▏ < > * ? \ / &#xff1a; …

单向带头链表的添加修改删除操作

public class HeroNodeDemo {public static void main(String[] args) {HeroNode hero1 new HeroNode(1, "松江");HeroNode hero2 new HeroNode(2, "武松");HeroNode hero3 new HeroNode(3, "及时雨");HeroNode hero4 new HeroNode(4, "…