一文带你了解Spring中存入Bean和获取Bean的方式

0. Spring中的五大注解

在这里插入图片描述
上图中就是五大类注解对应的层,通过源码可以看到其他四个注解都基于@Conponent

1. 存入 Bean

Spring既然是一个包含众多工具方法的IoC容器,它是一个控制反转的容器,所以就需要将Bean对象存入到容器中,需要用的时候从容器中获取Bean对象,下面我们来介绍下存入Bean对象。

1.1 在 xml 中存入 Bean 对象

<?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">

   // 这句代码中, id 就是给 这个要注入的对象取个名字, class就是 要存入的 Bean 的类型是哪一个
    <bean id = "user" class="com.java.demo.User"></bean>

</beans>

在这里插入图片描述

1.2 通过配置 Bean 扫描路径 + 类注解 实现 Bean 的存储

<?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>

</beans>

配置了 Bean 的扫描路径,只有当前目录下的类才会被扫描是否加了类注解,如果加了类注解后,就会将 所有加了类注解的类 存入到 IoC 容器中。

@Component
public class User {
    public void say(){
        System.out.println("Hello User...");
    }
}

类注解存Bean需要注意几点

  • 如果类名为大驼峰命名规则,那么获取 Bean 的默认名称,就是 类名首字母小写
  • 如果不满足首字母大写,第二个字母小写,那么 Bean 的名称,就是原类名,这点可以看源码知道
    在这里插入图片描述

1.3 通过配置 Bean 扫描路径 + 方法注解 实现 Bean 的存储

<?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>

</beans>
public class Student {
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
@Component
public class User {

    @Bean
    public Student student(){
        Student student = new Student();
        student.setName("张三");
        student.setAge(18);
        return student;
    }
    public void say(){
        System.out.println("Hello User...");
    }
}

在上述代码中,我们可以通过 在方法上 加上 @Bean 注解 将该方法存入到 IoC 容器中,并且可以直接获取到该对象。
在这里插入图片描述


在使用 @Bean 注解的时候,需要注意几点

  • @Bean 注解必须配合 五大类注解一块使用
  • @Bean 注解的默认命名 = 方法名称
  • 如果使用 @Bean(“xxxx”)方式,那么名称就是 xxxx, 并且 @Bean({“xxx”,“xxxxx”,“xxxxxx”}),里面可以类似和数组一样多个名称
  • 如果@Bean重命名后,那么默认的方法名就没用,获取Bean的时候就不能写默认方法名
  • 如果多个 Bean 使用相同的名称,则不会报错,只会存储第一个 Bean对象,之后相同名称的不会存入,会自动忽略

2. 获取 Bean

2.1 依赖查找(DF)

依赖查找(依赖Bean的名称),有两种方式,一种是 ApplicationContext, 一种是 BeanFactory。这两种都是容器管理对象,都可以获取到 Bean对象

2.11 ApplicationContext

public class App {
    public static void main(String[] args) {

        // 1. 获取 Spring 上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        // 2。获取 Bean 对象
        Student student = (Student) context.getBean("student");
        System.out.println(student);
    }
}

2.12 BeanFactory

    public static void main(String[] args) {
        // 1. 得到 spring 上下文对象
        BeanFactory context = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
        // 2. 获取 Bean 对象
        //Student student = (Student)context.getBean("user");

        Student student = (Student)context.getBean("student");
        System.out.println(student.toString());
    }

2.13 Application VS BeanFactory

ApplicationContextBeanFactory
ApplicationContext是BeanFactory的子类,其拥有更多功能(国际化支持、资源访问支持、事件传播)BeanFactory是ApplicationContext的父类
ApplicationContext加载Bean:一次性加载所有Bean对象BeanFactory加载Bean:懒加载,按需加载(使用一个加载一个)

在这里插入图片描述

2.2 依赖注入(DI)

在 spring 中实现依赖注入的常见方式有3种:

  • 1.属性注入
  • 2.setter注入
  • 3.构造方法注入

2.21 属性注入

@Controller
public class UserController {

    /**
     * 属性注入
     */
    @Autowired
    private UserService userService;

    // 此处 main方法里面,必须使用依赖查找的方式,先获取到UserController
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        UserController userController = (UserController) context.getBean("userController");
        userController.userService.say();
    }
}

属性注入:

优点: 实现简单、使用简单,只需要在属性上加一个注解@Autowired,就不需要自己new一个对象,直接获得注入的对象。

缺点:

  1. 无法注入一个用 final 修饰的对象在这里插入图片描述
    因为在Java语法中,final修饰的对象(不可变),要么一开始就赋值,要么在构造方法里面赋值。而上述使用属性注入,注入final修饰的对象,就不符合规范,所以不行。

  1. 只能适用于 IoC 容器:如果将这些代码放到其他非IoC容器中,那么代码就会失效
  2. 设计原则:更容易违背单一原则,因为属性注入比较简单,那么可能就会在一个类中注入多个对象,这就可能不符合程序的单一职责问题。

2.22 Setter注入

@Controller
public class UserController2 {

    private UserService userService;
    /**
     * setter注入
     */
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

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

}

优点:似乎没什么优点,而且比属性注入更加麻烦,要说唯一可能有用的就是,完全符合单一职责设计原则,每个 setter 只针对一个对象。Setter注入 也适用于非IoC容器
缺点:

  1. 不能注入 final 对象
    在这里插入图片描述
  2. 由于是 Setter 注入,提供了 set 方法,那么注入的对象可以随时被更改

2.23 构造方法注入(Spring4.x之后推荐的)

@Controller
public class UserController3 {

    private final UserService userService;

    /**
     * 构造方法注入
     */
    
    // @Autowired 此处如果构造方法参数只有一个的时候,该注解可有可无
    public UserController3(UserService userService) {
        this.userService = userService;
    }

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        UserController3 userController3 = (UserController3) context.getBean("userController3");
        userController3.userService.say();
    }
}

优点:

  1. 可以注入 被final 修饰的对象在这里插入图片描述

  2. 注入对象不会被更改,因为是在构造方法注入的,构造方法在对象创建的时候只会创建一次

  3. 注入的对象会被完全初始化

  4. 通用性会更好,无论在 IoC容器 还是 非 IoC容器中都能用

缺点:

  1. 写法更加复杂
  2. 使用构造方法,无法解决循环依赖的问题

Spring官方推荐的是构造方法的注入,可以注入不可变对象,通用性更好;如果想要注入可变对象,那么可以使用 Setter 注入。

3. 解决同一类型多个 Bean 的报错问题

在这里插入图片描述
上述代码,可以看到报错,出现了多个同一类型的多个Bean报错,需要1个,找到了2个。如何解决呢

  • 1.@Autowired 配合 @Qualifier(value = “xxx”)一起使用,里面参数加方法名字在这里插入图片描述
  • 2.使用@Resource(name = “xxxx”)在这里插入图片描述

3. @Resource 和 @Autowired

  • 出身不同:@Resource来自于JDK,@Resource来自于Spring

  • 支持参数不同:@Resource支持更多的参数在这里插入图片描述
    @Autowired只支持一个参数设置

  • 使用上的区别:@Resource不支持构造方法的注入
    在这里插入图片描述

  • 兼容性问题:@Autowired在社区版 IDEA可能会误报;


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

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

相关文章

Vue中值的传递(父传子,子传父,子父同步)

1.父组件->子组件传递数据 ①父组件通过 v-bind: 属性绑定的形式&#xff0c;把数据传递给子组件 如果不需要动态绑定&#xff0c;则可以直接写number“张三” ②子组件中&#xff0c;通过props接收父组件传递过来的数据 2.子组件->父组件传递数据 1.在子组件中&#xf…

举例说明基于线性回归的单层神经网络网络(以梯度下降算法来求解权重的过程)...

我们将通过一个简单的例子来说明基于线性回归的单层神经网络&#xff0c;以及如何使用梯度下降算法来求解权重。 假设我们有以下数据集&#xff0c;表示学生的学习时间&#xff08;小时&#xff09;与他们的考试分数&#xff1a; 学习时间&#xff08;X&#xff09;&#xff1a…

使用NVIDIA FX Composer验证多纹理合成效果

最近项目上有一个需求&#xff0c;需要将4张带透明通道纹理合成为一张&#xff0c;并且每张纹理指定一个全局透明度。由于纹理过多&#xff0c;合成效果无法保证&#xff0c;为了减少项目的风险&#xff0c;领导希望我先快速验证一下我们讨论的方法是否能完成项目的要求。因此我…

Mybatis-Plus(二)--Mybatis-Plus方法大全

通用CRUD大全&#xff08;Mybatis-Plus为我们提供了哪些操作&#xff09; 还有在mybatis中遇到列名和属性名不一致等等的情况&#xff0c;在mybatis中xml中声明解决&#xff0c;在mybatis-plus中也都有对应的解决。 1.插入操作 //插入一条记录 //参数entity是实体对象 int ins…

基于单片机的智能点滴速度输液液体检测

目 录 摘 要...................................................................................................................... I ABSTRACT.......................................................................................................... II 第…

【机器学习】吴恩达课程1-Introduction

一、机器学习 1. 定义 计算机程序从经验E中学习&#xff0c;解决某一任务T&#xff0c;进行某一性能P&#xff0c;通过P测定在T上的表现因经验E而提高。 2. 例子 跳棋程序 E&#xff1a;程序自身下的上万盘棋局 T&#xff1a;下跳棋 P&#xff1a;与新对手下跳棋时赢的概…

离线数据仓库

一、数据仓库 1.数据仓库的概念 1)数据仓库的特点: 面向主题的:对数据进行整合、分析和归类的抽象集成的:将不同数据源的数据(业务数据、外部系统数据、埋点日志)经过统一编码、规范命名、字段类型转换等操作,整合到仓库相对稳定的:根据业务场景实时更新、一般会被长…

C语言-ubuntu下的命令

目录 linux命令 【1】打开关闭终端 【2】终端 【3】ls命令 【4】cd 切换路径 【5】新建 【6】删除 【7】复制 【8】移动 【9】常用快捷键 【10】vi编辑器 【11】简单编程步骤 任务&#xff1a; linux命令 【1】打开关闭终端 打开终端&#xff1a; 1. 直接点击 …

代码随香录day21

235. 二叉搜索树的最近公共祖先 本题思路&#xff1a; 还是要利用二叉搜索树的特性&#xff0c;中序遍历为有序数组。如果pq两个节点都小于root&#xff0c;那么最近公共祖肯定是在他的左子树&#xff0c;如果都大于那么&#xff0c;肯定就在右子树。然后直接return root 代码…

Sentinel的线程隔离和熔断降级

上一节整理了Sentinel的限流&#xff0c;限流可以降低微服务的负载&#xff0c;避免因为高并发而故障&#xff0c;进而传递给其他相关服务而引发服务雪崩。以上仅为避免服务故障&#xff0c;而当某个服务真正故障时&#xff0c;如何处理才能防止服务雪崩&#xff1f; ⇒ Sentin…

Azure Kinect DK 在设备管理器找不到此设备

参考 Azure Kinect DK 在设备管理器找不到此设备_Thomas_yx的博客-CSDN博客 type-c------------------type-c 接电脑&#xff0c;数据传输 圆------------------usb 电脑线

Spark(29):Spark内存管理

目录 0. 相关文章链接 1. 堆内和堆外内存规划 1.1. 堆内内存 1.2. 堆外内存 2. 内存空间分配 2.1. 静态内存管理 2.2. 统一内存管理 3. 存储内存管理 3.1. RDD 的持久化机制 3.2. RDD的缓存过程 3.3. 淘汰与落盘 4. 执行内存管理 4.1. Shuffle Write 4.2. Shuffl…

【STM32】使用HAL库对ULN2003控制28BYJ-48步进电机

步进电机是将电脉冲信号转变为角位移或线位移&#xff0c;通过控制施加在电机线圈上的电脉冲顺序、频率和数量&#xff0c;可以控制步进电机的转向、速度和旋转角度。 配合以直线运动执行机构(螺纹丝杆)或齿轮箱装置&#xff0c;更可以实现更加复杂、精密的线性运动控制要求。…

HTTP进化史:从HTTP1的简单到HTTP3的强大

文章目录 &#x1f4c8;I. HTTP1⚡A. 基本特点⚡B. 特点⚡C. 优缺点 &#x1f4c8;II. HTTP2⚡A. 基本特点⚡B. 特点⚡C. 优缺点 &#x1f4c8;III. HTTP3⚡A. 基本特点⚡B. 特点⚡C. 优缺点 &#x1f4c8;IV. 总结&#x1f4c8;附录&#xff1a;「简历必备」前后端实战项目&am…

【动手学深度学习】pytorch-参数管理

pytorch-参数管理 概述 我们的目标是找到使损失函数最小化的模型参数值。 经过训练后&#xff0c;我们将需要使用这些参数来做出未来的预测。 此外&#xff0c;有时我们希望提取参数&#xff0c;以便在其他环境中复用它们&#xff0c; 将模型保存下来&#xff0c;以便它可以在…

回归预测 | MATLAB实现WOA-CNN鲸鱼算法优化卷积神经网络的数据多输入单输出回归预测

回归预测 | MATLAB实现WOA-CNN鲸鱼算法优化卷积神经网络的数据多输入单输出回归预测 目录 回归预测 | MATLAB实现WOA-CNN鲸鱼算法优化卷积神经网络的数据多输入单输出回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 回归预测 | MATLAB实现WOA-CNN鲸鱼算法优化卷积…

matlab重名函数调用踩坑记录

我新安装了matlab的robotics toolbox&#xff0c;然而调用的rotx不是我想要的函数。 我上网查了一下资料&#xff0c;知乎和csdn有相关的回答&#xff0c;但是我试了一下还是不行。它们的方法是移除路径再添加路径避免函数的冲突。相关方法放在文末的相关参考1 2。这里建议先用…

上门服务小程序|上门家政小程序开发

随着现代生活节奏的加快和人们对便利性的追求&#xff0c;上门家政服务逐渐成为了许多家庭的首选。然而&#xff0c;传统的家政服务存在着信息不透明、服务质量不稳定等问题&#xff0c;给用户带来了困扰。为了解决这些问题&#xff0c;上门家政小程序应运而生。上门家政小程序…

Zookeeper集群

Zookeeper集群 一、Zookeeper 概述Ⅰ、Zookeeper 定义&#xff1a;Ⅱ、Zookeeper 工作机制Ⅲ、Zookeeper 特点Ⅳ、Zookeeper 数据结构Ⅴ、Zookeeper 应用场景Ⅵ、Zookeeper 选举机制 二、部署 Zookeeper 集群Ⅰ、安装前准备Ⅱ、安装Zookeeper 三、部署kafka 集群Ⅰ、下载安装包…

设计模式07-责任链模式

责任链模式属于行为设计模式&#xff0c;常见的过滤器链就是使用责任链模式设计的。 文章目录 1、真实开发场景的问题引入2、责任链模式讲解2.1 核心类及类图2.2 基本代码 3、利用构建者模式解决问题4、责任链模式的应用实例5、总结5.1 解决的问题5.2 使用场景5.3 优缺点 1、真…