【Spring】-Spring中Bean对象的存取

news2025/2/9 6:43:46

作者:学Java的冬瓜
博客主页:☀冬瓜的主页🌙
专栏:【Framework】
主要内容:往spring中存储Bean对象的三大方式:XML方式(Bean标签);五大类注解;方法注解。从spring中取对象的两种方式:基本方法、注解方法(属性注入、set注入、构造方法注入)。

在这里插入图片描述

在这里插入图片描述

文章目录

  • Spring中Bean的存取方式
  • 一、三大方式存储对象到spring容器中
    • 1、XML方式把Bean存储到spring
      • 1.1、创建Bean类
      • 1.2、将Bean注册到Spring的xml配置文件
    • 2、五大类注解方式 @Controller等存储Bean到spring
      • 2.1、五大类注解和JavaEE标准分层
      • 2.2、五大类注解方式 往spring中 存储Bean对象
    • 3、方法注解方式 @Bean存储对象到spring中
      • 3.1、实体类的命名
      • 3.2、存储Bean对象
  • 二、获取Bean对象(依赖注入)
    • 1、获取对象的最基本的方法
      • 2.1、获取Spring容器方式
        • 法一:BeanFactory接口和ClassPathResource继承类
        • 法二:ApplicationContext接口和ClassPathXmlApplicationContext继承类
      • 2.2、getBean获取指定的Bean对象
      • 2.3、获取Bean对象的名称的命名源码分析
    • 2、使用依赖注入从spring获取对象
        • 2.1、法一:属性注入
        • 2.2、法二:setter注入
        • 2.3、法三:构造方法注入
        • 补充:在依赖注入中 @Autowired和 @Resource的区别

Spring中Bean的存取方式

在Spring中,Bean的装配方式有两种,xml方式和注解方式。自己开发的类可以使用@Component注解或xml方式装配,推荐使用注解,因为更加简洁方便。
引入第三方库的包可以使用@Bean注解的方式或xml的方式,推荐使用xml方式,将库的内容和自己的代码分离。

一、三大方式存储对象到spring容器中

1、XML方式把Bean存储到spring

1.1、创建Bean类

a. 在Java目录下创建多级目录包com.spring.bean,在该包下创建Student类和Teacher类

在这里插入图片描述

b. Bean对象中,Student类如下(Teacher类的属性和方法与之相似,有私有属性,有Set和Get方法,构造方法)

package com.spring.bean;

public class Student {
    private String name;
    private int age;

    public Student(){
        System.out.println("init Student");
    }

    public void wmi(){
        System.out.println("I am student: my name is "+ name);
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

1.2、将Bean注册到Spring的xml配置文件

a. 在resources下创建spring中对象注册的配置文件,可以命名为spring-config.xml

在这里插入图片描述

b.将下列配置信息粘贴到配置文件中,并且使用bean标签对student和teacher类进行注册,注册时id属性是对保存到spring中的对象的重命名class 属性是该类在项目中的路径+包名+类名,而相应的文件会从spring依赖中自动获取。

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--将类对象,com.spring.bean.Student存进spring容器,名字是student,是一个spring bean-->
    <bean id="student" class="com.spring.bean.Student"/>
    <bean id="teacher" class="com.spring.bean.Teacher"/>
</beans>

2、五大类注解方式 @Controller等存储Bean到spring

2.1、五大类注解和JavaEE标准分层

A:五大类注解
@Controller:控制器,验证用户请求的数据的正确性 。
@Service:服务,调度具体的执行方法。
@Repository:用户持久层,和数据库进行交互。
@Component:组件(工具类)
@Configuration:配置项,项目中的一些配置。为什么有配置项类?有很多原因,有一个就是在启动程序时,配置文件不一定会加载,这时就需要使用配置项来起到在程序运行时告诉程序需要先加载配置文件的作用。

B:JavaEE标准分层
在后端的分层当中,至少有控制层、服务层,数据持久层三个层次。

在这里插入图片描述

C:使用五大类注解和标准分层规范项目
下图中:实体类使用entity或model表示,其他部分按照五大类注解的方式分层,分出控制器类,服务类,数据库操作类,组件,配置文件类。

在这里插入图片描述

2.2、五大类注解方式 往spring中 存储Bean对象

A:创建包,Bean对象,并给类(Bean对象)添加适当的五大类注解
注意:满足需要存储在spring中的类在配置文件的base-package中,且这个类使用了五大类注解,就可以使用spring进行存取。
在这里插入图片描述

B:创建spring配置文件spring-config.xml,并在配置文件中注册可能要存入spring所有类的所在包
在下图中,可能存入spring的类是TestController包下的任意一个类(或TestController包的字包中的类)。如下图,springTest包的子包中的类都将保存在spring中,所以注册包springTest:
base-package="springTest"
在这里插入图片描述
在这里插入图片描述

注意点:

  • 在配置文件中注册可能涉及的包存储的类使用五大类注解二者缺一不可,如果缺少,报错说没有找到这个Bean对象。
  • 需要存储在spring中的类本身的位置可以在注册的包中或者它的子包中。
  • 使用五大类注解和注册包这个方法与使用bean标签(XML方式)(使用路径+包名+类名)的方式可以混合使用。即如果存在某个类需要存储在spring中,但又不适合放在注册的包里的任何位置,就可以将这个类放在注册包之外,但是使用bean注册当前类对象(即使用XML的方式存取对象)。

3、方法注解方式 @Bean存储对象到spring中

3.1、实体类的命名

补充:
实体类的管理实体类不交给spring管理,由我们自己管理
实体类的命名
DO,基本对象,和数据库表结构一一对应,如UserEntity或UserDO或者直接和数据库表名一致 User
VO,扩展对象,前端传给后端的对象。如UserVO,使用多个VO描述各种业务。

3.2、存储Bean对象

要点

  • 1> 方法注解需要配合五大类注解使用。比如UserBeans类下有多个方法注解,在UserBeans上需要加上五大类注解(一般是@Component)。之所以如此,是为了提高效率。
  • 2> 方法注解的对象名可以改名。方法注解 对象的名字不同于五大类注解,方法注解是默认方法名,但是可以在方法注解@Bean后加括号,使用name或value属性给Bean对象改名。

在这里插入图片描述

注意:

  • 给Bean对象改名后,就不能再使用方法名获取到对象,只能使用修改后的名字。
  • 如果存在方法名相同的两个@Bean方法在不同类中(都未修改名字),当获取Bean对象时可以在方法上添加@Order(数字),数字小的方法会先注入,但是后注入的方法会发生覆盖。

二、获取Bean对象(依赖注入)

1、获取对象的最基本的方法

2.1、获取Spring容器方式

a.目的相同BeanFactoryApplicationContext的目的相同,都是为了获取到spring容器
b.实现不同
BeanFactory是使用类似于懒汉模式进行类加载并进行对象的初始化(获取到spring后,使用getBean方法获取对象时,才进行相关对象的类加载,并进行对象的初始化)。
ApplicationContext则是使用类似于饿汉模式(一获取spring容器会立即加载配置文件,并进行对象的初始化(执行构造方法,静态方法,静态代码块等))
c.父子关系:BeanFactory是ApplicationContext的子类

法一:BeanFactory接口和ClassPathResource继承类

给ClassPathResource传参spring的配置文件的文件名,给XmlBeanFactory传参ClassPathResource文件,最后BeanFactory接口接收其子类XmlBeanFactory类。

// 获取spring容器
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));

使用BeanFactory和XmlBeanFactory和ClassPathResource获取Bean对象完整代码:

import com.spring.bean.Student;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class TeacherMain {
    public static void main(String[] args) {
        // 懒汉加载:调用时,才加载spring容器中的bean对象,效率不高,但是内存消耗低。
        BeanFactory factory = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));

        Student student = (Student) factory.getBean("student");

        student.wmi();
    }
}

法二:ApplicationContext接口和ClassPathXmlApplicationContext继承类

获取spring容器(使用ApplicationContext接收其子类ClassPathXmlApplicationContext,给ClassPathXmlApplicationContext传参配置文件的文件名)

// 获取Spring容器
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

使用ApplicationContext接口和其子类ClassPathXmlApplicationContext获取Bean对象的完整代码:

import com.spring.bean.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class StudentMain {
    public static void main(String[] args) {
        // 饿汉加载:一次性加载并初始化spring配置文件中的对象,后续操作spring容器中的bean对象时会很快,但是费内存。
        // 1通过resources文件夹中的xml文件名,获取spring容器
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        
        // 2获取Bean对象
        Student student2 = context.getBean("student", Student.class);

        // 3使用spring bean对象
        student.wmi();
    }
}

2.2、getBean获取指定的Bean对象

getBean方法的参数,可以使用多种方式进行传参:
一,使用名称获取
二、使用类型获取,(如果存储两个名称不同,类型相同的对象,会找不到唯一的Bean,从而报错)
三、使用名称+类型获取(最保险,不容易出错)

在这里插入图片描述

2.3、获取Bean对象的名称的命名源码分析

在获取Bean对象时,Bean对象名是什么?
首先,为了突出重点,我们先直接亮出结论:

规律:
①:如果需要保存在spring中的对象所属的类 的首字母和第二个字母都大写,如(ACar->ACar),那么Bean对象的名字为原类名。使用context.getBean("原类名", 类名.class)方式从spring中获取对象。
②:如果不是情况一,那就把首字母小写(如A->a,RedCar->redCar)。如要从spring中获取一个CarController使用context.getBean("carController", CarController.class)获取CarController对象。

现在,我们查看spring源码,印证我们的结论:

A:操作:双击shift键,搜索BeanName,找到好几个类,因为我们是要找Bean的命名规则,根据Bean的命名英文推导,一个一个去找,我这里直接给出结论:双击shift键,搜索BeanName,出现下图,点击AnnotationBeanNameGenerator(注解BeanName生成类)。
在这里插入图片描述
B:点击左边的structure,弹出该类的各种方法。点击generatorBeanName方法。按住ctrl,点击下图中调用的方法。
在这里插入图片描述
C:在generatorBeanName方法中 ctrl+点击方法调用,跳转到BuildDefaultBeanName(参数一,参数二),在该方法中再次ctrl+点击方法调用跳转到它的重载函数BuildDefaultBeanName(参数)。再使用ctrl+点击方法调用,跳转到了最终的目的函数。
在这里插入图片描述
D:目的函数Introspector类的decapitalize方法中
注意: decapitalize方法中,传入的参数name是要存入spring的对象所属的类名。
如果传入的参数是null,或者参数长度为0,那么直接返回类名,代表这个存入spring的对象的名字是null或空字符串。
如果传入的参数长度大于1,且首字母和次首字母都是大写,那么直接返回类名,代表这个存入spring的对象的名字是原类名。
如果传入参数不是null,长度大于0,如果只有一个字母,将首字母小写返回。如果有多个字母,且首字母和第二个字母不都是大写,那就将原类名的第一个字母小写返回,作为存入spring的对象的名字。
在这里插入图片描述
E:结论: spring代码生成Bean对象的命名是使用jdk的标准起名的
看下图,在上面的操作C时,点击标出来的蓝色框定位当前类AnnotationBeanNamGenerator的位置,可以看到这个类是存在于spring源码中的。
在这里插入图片描述
操作C完成后,跳转到到Introspector类的decapitalize方法中,再寻找Introspector类的所在位置,如下图,它出现在了jdk的rt.jar中。
在这里插入图片描述
在这里插入图片描述

2、使用依赖注入从spring获取对象

注意:指在Controller的类中注入Service,在Service中注入Repository。学spring到目前为止暂时无法实现 在main方法所在的类中注入Controller,在main中只能使用getBean获取对象,后续在springboot中则不需要main方法,而是tomcat自动执行。

2.1、法一:属性注入

属性注入:
步骤A:加注解 @Autowired
步骤B:写要注入的类作为当前类的属性。
如下图:
在这里插入图片描述
属性注入优缺点:
优点:简单,易操作。
缺点:
1> 无法实现final修饰的变量的注入,如private final CarService carService使用属性注入,无法成功注入;
2> 兼容性不足,只适用于IoC容器;
3> 易违反单一设计原则(注入多个对象,做多个功能)。

2.2、法二:setter注入

setter注入:
步骤A:要注入对象作为当前类的属性。
步骤B:注解@Autowired + set方法给要注入的对象赋值。(参数是自己从spring中取出来传给set方法作为参数)在这里插入图片描述set注入的优缺点:
优点:严格遵循单一设计原则
缺点:
1> 无法实现final修饰的变量注入;
2> 注入的对象有被修改的风险,因为set方法是public修饰的。

2.3、法三:构造方法注入

构造方法注入:
步骤A:要注入对象作为当前类的属性。
步骤B:注解+构造方法给注入对象赋值。(参数是自己从spring中取出来传给构造方法作为参数)
在这里插入图片描述
构造方法注入优缺点:
优点:
1>可以实现final修饰变量的注入。(在Java中,final修饰的变量要么直接赋值,要么在构造方法中赋值,这是语法规定,因此构造方法可以实现final修饰变量的注入,而set方法无法实现)
2>注入对象无法被修改,因为构造方法只执行一次。
3> 构造方法注入可以保证注入对象被完全初始化。因为构造方法注入是对象实例化的过程中进行的,而属性注入和set注入是在对象实例化之后进行的。
4> 通用性更好,因为是Java语法规定,不仅仅适用于IoC容器。

补充:在依赖注入中 @Autowired和 @Resource的区别

问题1: @Autowired和 @Resource有时可以替换,有时不行,接下来分析它们的区别:
来源不同:@Autowired来自spring,@Resource来自JDK
使用范围不同:@Autowired可以适用于三种注入,@Resource只支持属性注入和set注入,不支持构造方法注入。
参数个数和类型不同:@Resource支持多个参数设置,适用于同一个类注入多个对象情况,对修改对象名字上更加灵活;@Autowired只有一个boolean类型的参数设置。
查找Bean对象方式不同:@Autowired先根据类型查找,后根据名称查找(注入变量的名称),ByType;@Resource先根据名称查找,后根据类型查找,ByName。

问题2:当存储了同类型的多个对象时,可以使用两种方式依赖注入对象。
1> @Resource参数的设置
在这里插入图片描述
2> @Autowired + @Qualifier(value=“对象名”)
在这里插入图片描述

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

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

相关文章

穿越未来:探索虚拟现实科技的未来前景

虚拟现实&#xff08;Virtual Reality&#xff0c;简称VR&#xff09;科技&#xff0c;正如一颗崭新的明星&#xff0c;迅猛崛起&#xff0c;为人类带来前所未有的体验和想象空间。随着科技的飞速发展&#xff0c;VR 科技的未来充满了无限的可能性&#xff0c;正将我们引向一个…

【LNMP(分布式)】

目录 一、LNMP是什么 二、实际步骤 1.启用虚拟机 1.1 启动三台虚拟机分别命名为nginx&#xff0c;mysql&#xff0c;php 1.2 分别配置基础环境 1.3 测试外网连通性 2.更新源 3.安装nginx并配置 3.1 下载nginx源码包并安装 3.2 配置nginx 4.安装mysql并配置 4.1 安装…

在.NET 6.0中自定义接口路由

在本文中&#xff0c;我们将讨论ASP.NET Core中的新路由。我们将了解什么是接口(endpoints)路由&#xff0c;它是如何工作的&#xff0c;它在哪里使用&#xff0c;以及如何创建自己的路由。 本文主题&#xff1a; 探索接口路由创建自定义接口创建更复杂的接口 名词定义&#…

029 - integer types 整数类型

MySQL支持SQL标准整数类型 INTEGER&#xff08;或INT&#xff09;和 SMALLINT。作为一个可扩展标准&#xff0c;MySQL也支持整数类型 TINYINT&#xff0c;MEDIUMINT和 BIGINT。下表显示了每种整数类型所需的存储空间和范围。 表11.1 MySQL支持的整数类型的必需存储和范围 类型…

日常问题——idea工具中SpringBoot使用@AutoWriter 爆红

&#x1f61c;作 者&#xff1a;是江迪呀✒️本文关键词&#xff1a;日常BUG、BUG、问题分析☀️每日 一言 &#xff1a;存在错误说明你在进步&#xff01; 一、问题描述 使用AutoWrited注解注入Bean时&#xff0c;变量下面有红线&#xff0c;但是不影响运行。 二…

【idea】点击idea启动没反应

RT 点击idea启动的时候没反应&#xff0c;接着百度报错&#xff0c;基本跟他们的也不一样。 首先我是做版本升级。其次&#xff0c;我之前是破解的。如果你也是跟我一样的话&#xff0c;那问题可能就处在破解上了 解决方式 首先&#xff0c;是跟大部分解决思路一样。先找到项…

【趋势检测和隔离】使用小波进行趋势检测和隔离研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

基于Java+SpringMVC+Mybaties+layui+Vue+elememt基于协同过滤的电影推荐系统的设计与实现

一.项目介绍 基于协调过滤的电影推荐系统的设计与实现 本系统分为普通用户以及管理员两类 普通用户&#xff1a; 登录系统查看最新推荐电影、收藏、评论、查看电影信息、 对电影进行评分、浏览电影资讯信息、查看个人信息以及浏览收藏…

【Python数据容器】--- 元组的基本使用

个人主页&#xff1a;平行线也会相交 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 平行线也会相交 原创 收录于专栏【Python小白从入门到精通】&#x1f388; 本专栏旨在分享学习Python的一点学习心得&#xff0c;欢迎大家在评论区讨论&#x1f48c; 元组…

系统学习Linux-Redis集群

目录 一、Redis主从复制 概念 作用 缺点 流程 二、Reids哨兵模式&#xff08;sentinel&#xff09; 概念 作用 缺点 结构 搭建 三、redis集群 概述 原理 架构细节 选举过程 实验环境模拟 一、Redis主从复制 概念 是指将一台Redis服务器的数据&#xff0c;复制…

linux查看进程绑定cpu核是否成功

运行top命令&#xff0c;可以看到进程以及进程cpu占有率 然后查看是否有P属性&#xff0c;这个属性用来查看进程绑定的cpu核 这里没有看到cpu占用核心 运行top后&#xff0c;按 " f "键进入top配置界面&#xff0c;然后按上下键选择P选项&#xff0c;此时可以看到P选…

(二)结构型模式:2、桥接模式(Bridge Pattern)(C++实现示例)

目录 1、桥接模式&#xff08;Bridge Pattern&#xff09;含义 2、桥接模式应用场景 3、桥接模式的UML图学习 4、C实现桥接模式的示例 1、桥接模式&#xff08;Bridge Pattern&#xff09;含义 桥接模式是一种结构型设计模式&#xff0c;它将抽象部分与实现部分分离&#…

不基于比较的排序:基数排序

本篇只是讨论桶排序的具体实现&#xff0c;想了解更多算法内容可以在我的博客里搜&#xff0c;建议大家看看这篇排序算法总结&#xff1a;排序算法总结_鱼跃鹰飞的博客-CSDN博客 桶排序的原理&#xff1a; 代码&#xff1a;sort1是一个比较二逼的实现方式浪费空间&#xff0c;s…

开源数据库Mysql_DBA运维实战 (DML/DQL语句)

DML/DQL DML INSERT 实现数据的 插入 实例&#xff1a; DELETE 实现数据的 删除 实例&#xff1a; UPDATE 实现数据的 更新 实例1&#xff1a; 实例2&#xff1a; 实例3&#xff1a; DQL DML/DQL DML语句 数据库操纵语言&#xff1a; 插入数据INSERT、删除数据DELE…

IT运维:使用数据分析平台监控PowerStore存储(进阶)

概述 本文基于《IT运维&#xff1a;使用鸿鹄监控PowerStore存储》&#xff08;以下简称原文&#xff09;文章进行了优化。主要优化部分包括存储日志进入到鸿鹄后&#xff0c;如何进行字段抽取&#xff0c;以及图表的展示。 字段抽取&#xff1a;由原来采用视图的方式&#xff0…

Rider无法识别Todo Comment

最近因为vs code很难识别到代码中的usage和definition&#xff0c;改用Rider了。 但是一开始就哪里有点不对&#xff0c; 比如我主题的颜色总是有些地方无法识别出来。比如我每次从Unity中点击脚本文件&#xff0c;都只能识别到某一个特定的文件夹&#xff0c;而不能打开整个…

机器人技术及其影响

目录 1.概念 2.发展 3.应用领域 4.对人类的益处 1.概念 机器人是指能够自主执行任务的机械设备或电子设备。它们通常具有一定的感知、决策和执行能力&#xff0c;能够接收和处理来自外部环境的信息&#xff0c;并做出相应的行动。 机器人的形态和功能各异&#xff0c;可以是…

Python接口测试- requests 发送 post 请求的几种方法

前言&#xff1a; POST 请求用于向服务器发送数据。与 get 相比更安全&#xff0c;同时 post 请求一般会带来数据的更改。 GET 请求不论我们怎么构造&#xff0c;最终都是通过 URL 向服务器传递数据&#xff0c;而 post 通过消息体&#xff08;报文主体&#xff09;发送请求。…

简单的职员管理系统 SpringBoot企业员工信息java jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 简单的职员管理系统 SpringBoot 系统有1权限&#xf…

海外电子商务源代码跨境系统开发,Java现成代码全开源

海外电子商务跨境系统的开发是一个复杂的过程&#xff0c;而利用现成的Java代码进行开发可以节省时间和成本。下面是海外电子商务跨境系统开发的全开源步骤。 第一步&#xff1a;需求分析和规划 在开发海外电子商务跨境系统之前&#xff0c;需要进行需求分析和规划。这包括确定…