【Spring】使用注解读取和存储Bean对象

这篇具有很好参考价值的文章主要介绍了【Spring】使用注解读取和存储Bean对象。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

 哈喽,哈喽,大家好~ 我是你们的老朋友:保护小周ღ  【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解


谈起Java 圈子里的框架,最年长最耀眼的莫过于 Spring 框架啦,本期给大家带来的是: 将对象存储到 Spring 中、Bean 对象的命名规则、从Spring 中获取bean 对象、注入的关键字、@Autowired 与 @Resource 的区别、解决@Bean 方法注解注入多个同类型 Bean 对象的报错。本文将为大家讲解,一起来看看叭~


本期收录于博主的专栏:JavaEE_保护小周ღ的博客-CSDN博客

适用于编程初学者,感兴趣的朋友们可以订阅,查看其它 “JavaEE基础知识”。

更多精彩敬请期待:保护小周ღ *★,°*:.☆( ̄▽ ̄)/$:*.°★* ‘


 一、上期回顾

我们已经实现了最基本的 Spring 的读取和存储 Bean 对象的操作了,使用 Spring 配置文件(.xml)对Bean 对象进行存储,使用 ApplicationContext 或 BeanFactory 接口获取Spring 上下文对象,上下文对象就管理着 Spring 中的 Bean 对象,然后调用 getBean() 方法获取指定的Bean 对象  ,该方法是一个重载方法,获取Bean 对象主要有三种方式:

1. 根据 bean 对象的 id (标志)来获取 

2. 根据对象类型来获取 Bean 

3 .根据 bean 对象的 id (标志)+ 类型 获取 bean

前两种重载获取指定Bean对象的方式各有缺陷,我们推荐使用第三种。


经过前面的学习,我们虽然实现了 Spring的基本获取和存储,但是在操作的过程中比较繁琐。

存储 Bean 对象需要我们手动的往 Spring 配置文件中添加配置。

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

取出 Bean 对象,首先需要我们获取上下文对象,其次需要调用 getBean() 方法根据参数来获取,搞来搞去感觉还不如我们传统的做法,只是多了一个(依赖反转)的思想。

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

所以接下来我们需要学习更简单的操作 Bean 对象的方法——使用注解。

使用Spring 中的相关注解,来存储和读取 Bean 对象。

详细内容:【Spring 】项目创建和使用_保护小周ღ的博客-CSDN博客


二、Spring 存储 Bean 对象

之前我们存储 bean 对象需要在Spring 配置文件(.xml)添加一行 bean 标签才行,如上图所示。

现在我们需要学习的是如何通过注解来代替之前添加 Bean 对象要手动写一行 bean 配置的尴尬

注解(Annotation)是一种Java语言中的元数据(metadata),提供了一种代码级别的标记机制,用来表示程序中的一些结构化信息以及对这些结构进行解释说明。注解可以用于类、字段、方法、参数等各种Java程序元素上,并可以通过反射机制来获取注解信息。

简单理解 :

注解就像是一些标签,我们可以将它们添加在程序的代码中,用来给代码添加一些额外的信息和说明。这些信息可以帮助程序自动化地完成某些操作,比如代码生成、配置管理、文档生成等等。

举个例子,比如我们想要在类中添加一些配置信息,通常我们需要在代码中手写一些配置代码,然后在程序中进行解析和加载。但是,如果我们使用了注解,我们就可以通过在类上添加一些特定的注解,来让程序自动化地完成配置的加载和解析工作。这样可以节省很多时间和代码量。

总之,注解就是一种用来给程序添加额外信息的工具,可以帮助我们更加方便地管理和自动化完成程序的各种操作。


 2.1 配置扫描路径

之前我们是在 Spring 配置文件(.xml)中手动添加 Bean 对象,如果使用注解的方法存储我们就只需要配置一下 bean 对象(还未实例)所在的包路径,当 Spring 启动时,上下文对象会根据Spring 配置文件配置的路径进行扫描,只有路径(包)添加了注解的 类、方法才能被正确的识别并实例到 Spring 中。

Spring 配置文件(.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="animal"></content:component-scan>
</beans>

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

如果说添加注解的类或方法不在配置扫描的包底下,也是无法被存储到 Spring 中的。


2.2 添加注解存储 Bean 对象

想要将 Bean 对象更简单的存储到 Spring 中,使用注解有两种注解类型:

1. 类注解:顾名思义就是用来修饰类的注解,表示需要将被修饰的类实例并存储到 Spring 容器中。五大类注解:下文详细介绍这些注解的含义

@Controller【控制器】、@Service【服务】、@Repository【仓库】、@Component【组件】、

@Configuratio【配置】。

2. 方法注解:一个类的中的方法可以实例另一个类嘛,此时将该方法的返回值设置为实例后的类对象再使用 @Bean 方法注解同样可以将该对象(bean对象)存储到 Spring 容器中。

在Spring 中五大类注解都可以将 Bean 对象存储到 Spring 中,没有太多的说法,但是在后面的框架的学习当中,每个注解分层修饰类,他们的含义就大有讲究,此时,我们主要学习如何使用注解存取 Bean 对象,其他知识点后期再给大家展开。


2.2.1 @Controller (控制器) 将Bean 对象存储到 Spring 中

先定义一个学生类:

public class Student {
    // 属性
    private String id;
    private String name;
    private String sex;
    private int age;

    // 行为
    public void homework() {
        System.out.println(name + "在做作业~");
    }

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

    public String getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

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

给 Student 类添加 @Controller 注解将 Student 对象(运行时自动)存储到 Spring 中

1. Spring 配置文件设置一下扫描路径

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

2. 给 Student 类添加注解

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

非常的酷,就一个注解 + 设置一下扫描路径搞定啦~ Spring 启动的时候就会自动的将 Student 类实例并添加到 Spring 中。

此时我们可以使用之前获取对象的方法来尝试获取从 Spring 中获取 Student 类的对象。

ApplicationContext 接口获取上下文对象,再调用 getBean() 方法来获取指定的 Bean 对象。

public class App {
    public static void main(String[] args) {
        //1. 得到 Spring 的上下文对象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-test.xml");
        //2. 调用 getBean() 方法获取指定的 Bean 对象
        Student student = context.getBean("student",Student.class);

        //3. 使用 Bean 对象
        student.setId("1");
        student.setName("张三");
        student.setSex("男");
        student.setAge(20);

        student.homework();
        System.out.println(student.toString());
    }
}

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解


2.2.1 @Service (服务) 将Bean 对象存储到 Spring 中

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

其余的三个注解 @Repository【仓库】、@Component【组件】、@Configuratio【配置】。      在 Spring 中并没有太大的含义,都是存储 Bean 对象,这里也不给大家演示了结果都一样。感兴趣的老铁可以自己演示一下。


2.3 为什么需要这么多的类注解?

由上述事例所示,五大类注解的功能都可以将 Bean 对象存储到 Spring 当中,功能都一样的情况下,为啥还需要这么多的类注解呢???

每个注解的具体应用场景及其含义:

1. @Controller注解:【控制器】验证前端传输的参数【安全检验】

Controller层是MVC(Model-View-Controller)设计模式中的一部分,负责处理用户请求和控制应用程序的流程。它是应用程序中的一个组件,用于接收来自用户界面(View)的请求,协调其他组件(如Service层和Repository层)的工作,并返回相应的结果给用户界面。

2. @Service 注解:【服务层】

主要用于处理业务逻辑和执行具体的业务操作。它位于应用程序的中间层,位于控制层和数据访问层之间,用于实现业务逻辑的封装和处理。

3. @Repository注解:【仓库(数据仓库)】可以理解为直接操作数据库

Repository层是软件开发中的一种设计模式,用于处理数据的存取和持久化。在Java应用程序中,Repository层通常是数据访问层的一部分,与数据库或其他数据存储介质进行交互。

4. @Component 注解:【组件】通用化的工具类

Component层是Java应用程序中的一个组件化层,主要用于组件的管理和组装。它负责将各个功能模块或组件进行组合,提供应用程序的整体功能。Component层通常位于应用程序的顶层,作为应用程序的入口点。

5. @Configuration注解:【配置】此处有项目的所有配置

@Configuration注解被Spring Framework用于传统的XML配置之外,为了更好的支持Java配置,它表示一个配置类,被加上此注解后可以当做Bean定义来使用。通过@Configuration注解,可以很方便地配置Spring容器中的Bean组件。

举个例子:

我们每一个人国人都有一个唯一的18 位的身份证号,身份证号包含了:地区号码,生日、顺序码和校验码。同一个省份 / 市 的群众身份证号的前几位都是一样的,例如:湖北省新生代的身份证号码都是 “42XXXX” 开头的。其中,XXXX 是具体的地区码,用来表示湖北省内不同的行政区划。是我们可以用一个String 类型 region 变量来描述地区码,从而直观的看出这个群众是来自那个地区,用 birthday 变量可以用来描述一个出生日期……把一个完整的身份证号拆分开来,就可以更加直观的表示这个人的基本信息,一看 region 变量描述的是地区,42 开头这个老铁是湖北的,,其中类注解就是这样的道理,不同 “层次” 的类我用不同的注解描述,是不是就很直观,例如:@Repository注解 按照标准,用来修饰操作数据库的类,就很方便维护。

综上所述,虽然这五大类注解的功能都可以将 Bean 对象存储到 Spring 当中,但它们的使用场景和语义略有差异,这样可以更好地满足不同的需求和场景。也正因如此,Spring框架中涉及的注解种类才这么多,以应对不同的业务场景和复杂的需求。

程序的工程分层,调用流程图:

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解


2.3.1 类注解之间的关系

查看 @Controller / @Service / @Repository / @Configuration 这些注解的源码发现:

ctrl + 鼠标单击注解即可查看。

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

这些注解的内部都有一个 @Component注解, 说明这些注解可以认为是 @Component 的子类.


2.4 Bean 对象的命名规则

上面我们通过使用注解的方式存储 Bean 对象,就是在 Spring 配置文章中设置Bean 对象所在的路径(包),当Spring 容器启动时,会根据配置文件中的路径扫描,将有注解的类实例化到容器中。我们如果使用之前的老方法获取 Bean 对象,需要先获取 Spring 上下文对象(管理Bean),有两种方式【ApplicationContext 接口】(Spring 3.x 版本后官方推荐),【BeanFactory 接口】

得到上下文对象后,我们需要调用 getBean() 方法获取具体的 Bean 对象,因为 getBean() 方法有种重载,所以主要有三种获取方法:
1. 根据 Bean 对象ID ,我们手动取得名字(缺点,:返回值是 Object 所以需要进行强制类型转换 )

2. 跟根据 Bean 对象得类型 (缺点:有多个同类型得 Bean 存储在容器中此时会抛出异常)

3. 根据 Bean 对象的 ID 和 Bean 对象的类型 (推荐)

此时我们通过类注解的方式添加 Bean对象,那获取 Bean对象的方法又该做出什么样的调整呢?

通常情况下 Bean (类)使用的就是标准的大驼峰命名,而读取的时候首字母小写就可以获取 Bean对象:

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解


当类名首字母和第二个字母都是大写时,此时利用默认的首字母小写就不能正常地读取到 Bean :

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解


关于这个获取 Bean 对象的默认ID ,我们就要了解Spring 关于 Bean 对象存储时生成的命名规则

双击 shift 键,打开全局搜索: 输入 AnnotationbeanName

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

 规则使用的是 JDK introspector 中的 decapitallze 方法,源码如下:

public static String decapitalize(String name) {
        if (name == null || name.length() == 0) {
            return name;
        }
        // 1. 如果第一个字母和第二个字母都为大写的情况,不做任何处理直接返回,也是就是id 是类名
        if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
                        Character.isUpperCase(name.charAt(0))){
            return name;
        }
        // 2. 否则就将首字母小写
        char chars[] = name.toCharArray();
        chars[0] = Character.toLowerCase(chars[0]);
        return new String(chars);
}

总结:

当使用五大类注解注册 bean对象时,默认情况下获取(getBean() 方法) bean 对象,只需要将类名的首字母小写,作为 getBean() 方法的参数即可;当 类的首字母和第二个首字母都是大写的时候,此时我们需要将原类名作为 getBean() 方法的参数才能获取到 bean 对象。

我们也可以在类注解上针对 bean 对象手动进行命名操作:

【类注解】(value = "name")

下面是一种简洁的写法:

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

拓展:如果项目中没有目录,所有的类都在 java 的根目录下怎么存,取 bean 对象???

<content:component-scan base-package="**"></content:component-scan>

我们可以在 Spring 配置文件中将文件路径替换成通配符 “**” ,使用通配符的意思就是 Spring 启动后会从根目录开始扫描查找那些被类注解修饰的类,然后将这些类实例到容器中,然而这样的结果就会导致执行的速度变慢慢,效率非常低,所以我们建议是给项目添加合适的路径。 


2.5 方法注解 @Bean

类注解是添加到某个类上面的,顾名思义,方法注解就是用来修饰方法的,使用方法注解(@Bean)的前提条件是需要配合类注解才能将对象正常的存储到 Spring 容器中,且该方法的返回值需要与预期存储 Bean 对象的类型一样

@Component
public class StudentDemo {
    @Bean
    public Student getStu() {
        //1. 创建对象
        Student student = new Student();
        //2. 初始化对象
        student.setId("1");
        student.setName("李小四");
        student.setSex("男");
        student.setAge(18);
        //3. 返回对象
        return student;
    }
}

以上代码的功能是 Spring 启动后扫描到了 @Component 注解修饰的 StudengDemo 类,自然而然需要将其实例化到 Spring 容器中,在实例化的过程中,发现一个 @Bean 注解,意思就是,如果你想实例 StudengDemo 类,那你得先将 @Bean 修饰得 getStu() 方法返回的 Student 对象(Bean 对象)注册的到 Spring 中。执行结果如下:

此时我们可以稍作修改,给 StudentDemo 类 和 Student 类各自提供一个构造方法,由此可以判断谁那个类先加载? 注意:我们要先将 Student 类上面的类注解去掉,不然就会存储两个 bean 对象到 Spring 中,关于存储多个同类型的 bean 对象下文讲述……

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

注意:通过方法注解的方式存储 Bean 对象默认情况下是没有默认 ID 的,所以我们通过类型获取,可以手动的给 Bean 对象设置 ID (name)。

结论:方法注解 @Bean 也可以将对象注册到 Spring 中,前提是需要配合类注解的使用。

上述代码中,@Bean 方法注解注册的 Student bean 对象需要依赖于 StudentDemo 类的实例,当我们启动 Spring , 首先会加载StudentDemo 类,执行构造方法, 在加载的过程中发现一个需要执行 getStu() 方法(设置属性),所以呢优先去实例 Student ,再实例 StudentDemo ,这一块涉及到 JVM 加载类的五个阶段—— Bean 对象的生命周期,下篇博客再给大家讲述~~

A 类依赖于 B类,所以首先将 B类实例到 Spring 中,现在还没涉及到注解动态的将 Bean对象取出,所以这个例子不大恰当。后面再讲述~~~


2.5.1 bean 对象重命名

@Bean 注解可以通过设置name 属性给 bean 对象进行命名操作:

 @Bean(name = "***")

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

name 其实是一个数组, 所以一个 bean 对象可以有多个名称存在:

@Bean(name = {"student", "李小四"})

 name = {} 也是可以省略的:

 @Bean({"student", "李小四"})

注意:当我们给 Bean 取了名字之后,默认的使用的名称就无法使用了!!!

以上便是 使用注解的方式将 bean 对象存储到 Spring 中的全部内容,如有不妥之处欢迎批评指正


三、Spring 获取 bean 对象

获取 bean 对象也叫 “对象装配”,“对象注入”, 意思就是把对象取出来放到某个类中。

对象装配(对象注入)的实现有以下三种方法:

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

接下来博主将围绕着3种方式展开来给大家讲述Spring 如何实现动态注入 bean 对象(运行时动态的将 bean 对象注入到某个类中)。

3.1 属性注入

属性注入需要使用到 @Autowired 注解实现。接下来给大家举一个例子:

有一个学生类(学生信息的组织),假设对应数据库中的学生表,有一个Service 层的 StuService类,这类可以从数据库中读取学生数据(增删查改),实例成一个完整的学生对象,有一个 StuController 类,他可以针对学生数据进行实际的使用(调用处理),所以 StuController 类在运行中需要获取到 StuService 类的实例对象来操作数据库中的学生表。当然这里不会给大家真的用数据库,写伪代码来模拟一下真实的环境。

@Service
public class StuService {
    /**
     * 根据学生id从数据库中获取学生信息
     * @param id
     * @return
     */
    public Student getStu(String id) {
        //伪代码,链接数据库,查找学生信息
        Student stu = new Student();
        stu.setId(id);
        stu.setName("张三");
        stu.setAge(18);
        stu.setSex("男");
        return stu;
    }
}
@Controller
public class StuController {
    //1. 属性注入,从Spring 中取出 StuService 类型的bean 对象并注入到类引用中
    @Autowired
    private StuService stuService;

    //2. 调用注入的 bean 对象执行查询操作
    public Student getStu(String id) {
        return stuService.getStu(id);
    }
}

获取 Controller 中的 getStu 的方法:正常情况下我们就将 Student 学生的信息转换为 json 格式由前端发请求,服务器做出响应,将数据(http协议)给到前端,前端利用数据构建页面。

package school.student2;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import school.student.Student;

public class App {
    public static void main(String[] args) {
        //1. 得到 Spring 的上下文对象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-test.xml");
        //2. 调用 getBean() 方法获取指定的 Bean 对象
        StuController stuController = context.getBean("stuController", StuController.class);
        //3. 使用bean 对象
        Student student = stuController.getStu("1");
        System.out.println(student.toString());
    }
}

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

 属性注入的核心:

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解


3.2 构造方法注入

构造方法注入是在类的构造方法中实现注入:同样使用 @Autowired 注解

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

 如果只有一个构造方法,那么 @Autowired 注解可以省略不写:

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

如果类中出现多个构造方法,那么需要添加上 @Autowired 来明确指定到底使用哪个构造方法,否则程序会报错。


3.3 Setter 注入

Setter 本质上就是使用自定义方法来代替构造方法注入,也是需要在 set 方法上添加 @Autowired 注解:

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

注意:使用 Setter 注入一定要添加@Autowired 注解


3.4 三种注入优缺点分析

3.4.1 属性注入

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

优点:实现起来比较简单,只需要一个@Autowired 注解

缺点:

1. 不能注入不可变的(final)的对象

final 修饰的引用,只能在创建的时候进行初始化赋值操作,或在构造方法中初始化。

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

 2. 只能适用于 loC 容器

属性注入通常与IoC(控制反转)容器紧密相关,并且在大多数情况下,它更常用于IoC容器中。IoC容器通过管理对象的生命周期、依赖关系和对象创建等任务,将控制权交给框架,以实现解耦和可扩展性。总体而言,属性注入与IoC容器密切相关,并且在通过IoC容器管理对象时,属性注入是一种常用的依赖注入方式,能够帮助实现代码的解耦和可配置性。然而,在非IoC场景下,属性注入的使用可能会受到一些限制,并且可能不如其他依赖注入方式适用。

3. 更容易违背单一设计原则(针对类)

属性注入在某些情况下可能会违背单一设计原则(Single Responsibility Principle,SRP)。SRP的目标是确保一个类对于变化的原因只有一个,以便提高代码的可维护性和灵活性。它强调职责的划分和分离,使每个类专注于单一的功能或关注点

以下是属性注入可能导致违背SRP的一些情况:

  1. 依赖过多:属性注入可能导致一个类具有过多的依赖关系。如果一个类依赖过多的其他类或组件,那么它可能承担过多的职责。这样的类可能会变得庞大而难以理解和维护。

  2. 责任扩散:属性注入可能导致一个类承担不应该由它承担的额外职责。当一个类注入了许多属性时,特别是来自不同领域的属性,它可能参与多个责任和业务逻辑,从而违反SRP。

  3. 耦合度增加:属性注入可能导致类之间的耦合度增加。如果一个类对其依赖项的实例化和配置有太多控制权,它与这些依赖项之间的耦合度会增加。这使得类的扩展和修改变得更加困难。

虽然属性注入在一些情况下可能会违背SRP,但这并不意味着属性注入本身是错误的或应该完全避免的。合理使用属性注入,可以通过分割类的职责、解耦依赖关系和保持代码的可维护性来避免违背SRP。在设计和实现过程中,应该谨慎选择注入的属性和依赖项,确保它们与类的职责和关注点保持一致,避免过度复杂化和耦合。


3.4.2 构造方法注入

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

优点:

1. 可以注入一个不可变(final修饰)对象,构造方法可以为其赋值。

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

 2. 注入的对象不会被修改

  • 可以被 final 的修饰(只有一个实例)
  • 构造方法伴随着类加载只执行一次

3. 通用性更好

通过构造方法注入,类的依赖关系可以明确地表达出来,构造方法注入允许依赖关系在类的实例化阶段就被传递进来。这意味着在类的实例化过程中,可以清楚地看到类所依赖的对象是哪些,而不是在方法调用时才进行依赖注入。

缺点:

没有属性注入实现简单。

需要注意的是,构造方法注入并不适用于所有情况,特别是当所依赖的对象较多时,会出现构造方法参数列表冗长的问题。在这种情况下,可以考虑使用其他形式的依赖注入方式,如属性注入或方法注入,来提供更灵活的注入方式。选择合适的依赖注入方式,取决于具体的情况和项目需求。

构造方法注入是 Spring 官方推荐的注入方法。


3.4.3 Setter 方式注入(普通方法注入)

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

Setter 方法是 Spring 早期版本推荐的注入方式,。

优点:比较符合单一设计原则(SRP),方法嘛,针对的是方法级别的,虽然在通用性上没有构造方法强,Setter方法注入也有其适用的场景,比如可选的依赖项或动态变化的依赖关系。在这些情况下,setter方法注入可能更为灵活和方便。选择合适的依赖注入方式,需要根据具体需求和设计原则进行权衡和判断。

缺点:

1. 不能注入不可变(final)的对象;

final 修饰的引用,只能在创建的时候进行初始化赋值操作,或在构造方法中初始化。

2. 注入对象可以被修改

set 方法是普通的方法,可以被重复调用,在调用时就存在被修改的风险。Spring 现版本已经推荐使用构造方法注入的方式来进行类注入。


3.5 @Resource 注入

在 Java 里面在进行类注入时,除了使用 @Autowired 注解,还可以使用 @Resource 注解:
【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

 @Autowired 和 @Resource 都是在 Java 中用于进行依赖注入的注解,但它们有一些不同之处。


3.5.1 @Autowired 和 @Resource 的区别

  1. 出生不同:@Autowired 注解出自于Spring框架(非官方),  @Resource 注解出自于 JDK(官方)。
  2. 功能支持不同:@Autowired 可用于属性注入,构造方法注入,和 Setter(普通方法) 注入.而 @Resoure 只能用于 Setter 注入和属性注入, 不能用于构造方法注入(意味着不能注入不可变对象).
  3. 参数支持不同:  @Resource 支持更多的参数设置, 例如: 对Bean 取一个名字(name), 而 @Autowired 只能设置 required 参数。required 是 @Autowired 注解的一个可选属性,默认值为 true。它用于指定依赖注入是否是必需的。当 required 属性设置为 true 时,如果找不到匹配的依赖对象,则会抛出 NoSuchBeanDefinitionException 异常。

示例:

@Autowired(required = true)
private MyDependency myDependency;

当 required 属性设置为 false 时,如果找不到匹配的依赖对象,则会将依赖对象设置为 null,即允许依赖注入的可选性。

示例:

@Autowired(required = false)
private MyDependency myDependency;

尽管 required 默认值为 true,但是在某些情况下,我们可能使用 @Autowired(required = false) 来标记可选的依赖注入,以便在没有匹配的依赖对象时不抛出异常。这在需要可选依赖或动态注入的场景下非常有用。


3.6 @Bean 注入多个同类型的 bean 对象报错处理

当我们使用 @Bean 方法注解往 Spring 中注入多个同类型的 Bean 对象时,就会报错。

注意:以往的例子我们需要在 Spring 配置文件中将路径注释一下,不然启动的时候Spring 容器中会注册多个同类型的 bean对象(stu)。

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

@Component
public class StudentDemo {
    StudentDemo() {
        System.out.println("StudentDemo 执行");
    }
    @Bean
    public Student getStu() {
        //1. 创建对象
        Student student = new Student();
        //2. 初始化对象
        student.setId("1");
        student.setName("李小四");
        student.setSex("男");
        student.setAge(18);
        //3. 返回对象
        return student;
    }

    @Bean
    public Student getStu2() {
        //1. 创建对象
        Student student = new Student();
        //2. 初始化对象
        student.setId("2");
        student.setName("王小五");
        student.setSex("男");
        student.setAge(20);
        //3. 返回对象
        return student;
    }
}

在另一个类中获取 Student 对象:

public class StudentApp {
    public static void main(String[] args) {
        //1. 得到 Spring 的上下文对象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-test.xml");
        //2. 调用 getBean() 方法获取指定的 Bean 对象
        StudentController stuController = context.getBean(StudentController.class);

        //3. 利用 stuController 对象的 getStudent()获取 bean 对象
        Student student = stuController.getStudent();
        System.out.println(student.toString());
    }
}

@Controller
class StudentController {

    //1. 注入 student 对象,在StudentDemo 类中我们使用 @Bean 注入了两个stu 对象
    @Autowired
    private Student student;

    //2. 返回
    public Student getStudent() {
        return student;
    }
}

以上程序执行结果:

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

同一类型多个 Bean 报错处理: 

  • 使用Resoure(name = "FunctionName") 进行类注入的时候只能指定获取@Bean注解修饰方法的名字,如此一来,问题迎刃而解~
  • 使用@Qualifier 注解定义名称,可以跟@Autowired 注解配合使用(Autowired 注解不可以指定name 注入)。

1. 使用 @Resource(name = "XXXXX") 定义

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

2. 使用 @Qualifier 

@Qualifier注解 用于帮助指定特定的依赖注入或自动装配。它通常与依赖注入框架(如Spring)一起使用,以解决多个候选对象的歧义性。在依赖注入中,当存在多个相同类型的bean时,可以使用@Qualifier注解来标识要使用的具体bean。通过在@Qualifier注解中指定一个唯一的标识符(name),可以告诉依赖注入框架,注入哪个具体的bean。

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解


 四、总结

1. 将对象存储到 Spring 中:

  • 古老一点的做法是在 Spring 配置文件的 <Beans> </Beans> 标签下直接添加注解。

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

不好的一点是比较麻烦,每个 Bean 对象都需要我们手动的添加,对此我们有了注解的方式。

  • 使用类注解:@Controller 、@Service、@Repository、@Configuration、@Component这些其他注解的内部都有一个 @Component注解, 说明这些注解可以认为是 @Component 的子类.

使用类注解:需要在Spring 配置文件中设置包扫描路径,当Spring 启动时,会根据包路径下的类注解将修饰的类实例到 Spring 当中,类直接需要配合扫描路径使用,不然无法成功注入(此处是单例模式,一个类只有一份实例)。

  • 使用方法注解 @Bean 【注意事项:必须配合类注解一起使用】

2. Bean 对象的命名规则

类首字母大写和类首字母小写及第二个字母小写,都是默认都是通过首字母小写作为name 来获取 Bean ;如果类首字母和第二个字母都是大写,那么直接使用原类名作为name 来获取 Bean 。

3. 从Spring 中获取bean 对象:

  • 属性注入 
  • 构造方法注入(官方推荐)
  • Setter 注入

 4. 注入的关键字:

@Autowired 和 @Resource

5. @Autowired 与 @Resource 的区别:

  • 出生不同:Autowired 出自Spring  ,Resource 出自 JDK
  • 参数不同:@Resource 支持更多的参数,例如可以在获取的时候给 Bean 对象取名字
  • 功能的不同:@Autowired 支持属性注入,构造方法注入和 Setter 方法注入,@Resource 只支持属性注入和 Setter 方法注入。
  • @Autowired 先根据Bean 对象的类型查找, 之后再根据名称查找, @Resource 先根据名称查找,再根据类型查找

6. 解决@Bean 方法注解注入多个同类型 Bean 对象的报错:

  • 使用 @Resource(name= " 方法名")
  • 使用 @Qualifier (value = "方法名")

好了,到这里,【Spring】使用注解读取和存储Bean对象 博主已经分享完了,希望对大家有所帮助,如有不妥之处欢迎批评指正。 

【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解

下期预告:Bean 的作用域和生命周期

感谢每一位观看本篇文章的朋友,更多精彩敬请期待:保护小周ღ *★,°*:.☆( ̄▽ ̄)/$:*.°★* 

遇见你,所有的星星都落在我的头上……【Spring】使用注解读取和存储Bean对象,JavaEE,spring,java,注解文章来源地址https://www.toymoban.com/news/detail-533946.html

到了这里,关于【Spring】使用注解读取和存储Bean对象的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring使用注解存储和读取对象

    之前我们存储Bean时,需要在spring-config.xml中添加bean注册才行,这样的方式并不简单。我们要想 更简单的存储和读取对象的核心是使用注解 1.使用类注解(五大类注解): @Controller:控制器,验证用户请求的数据正确性(安保系统) @Service:服务层,编排和调度具体执行方法的(客服

    2023年04月19日
    浏览(44)
  • 【JavaEE】Spring中注解的方式去获取Bean对象

    【JavaEE】Spring的开发要点总结(3) 在前面的代码里,我们获取Bean对象也比较麻烦: 本文章就是为了更方便地去获取Bean对象~ 对象装配 也叫 对象注入 那么有没有对应的注解去实现这个功能呢? Spring提供的三种实现方法: 属性注入 构造方法注入 Setter注入 而这种非明文获取

    2024年02月15日
    浏览(38)
  • Spring 更简单的读取和存储对象、使用注解存取对象

    我们知道物件都会随着时代的发展,越变越简单的。Spring 框架也不意外;我们在之前存储Bean对象是在配置文件中添加 bean/bean 来存入Bean对象到Spring当中的,使用那个类对象就要存入那个,一个两个类对象还好,如果需要的对象多了,就会非常麻烦。现在,随着 Spring 发展不用

    2024年02月11日
    浏览(47)
  • Spring中Bean对象的存储与读取

    在项目的 pom.xml 中添加 Spring 支持 如何选定版本环境:打开官网,点击github图标 jdk8最后一个Spring版本是5.3.x,Spring6.0.x最低需要jdk17 版本冲突问题Maven自己处理 version : 可以选择带有 RELEASE结尾或者纯数字结尾,这样的版本更稳定 项目下创建一个main方法的启动类 存储 Bean 之前

    2024年01月24日
    浏览(35)
  • Spring更简单的存储和读取Bean对象

    目录 1.第一个Spring项目 2.存储Bean对象 2.1 准备工作 2.2 五大类注解 2.3 方法注解@Bean 2.4 Bean对象的默认命名规则 3. 读取Bean对象 3.1 属性注入 3.2 setter注入 3.3 构造方法注入 3.4 注入异常问题 3.5 注入方式优缺点 3.6 @Autowired和@Resource的区别 在学习更简单的方式来读取和存储Bean对象

    2024年02月03日
    浏览(50)
  • 【JavaEE进阶】Spring 更简单的读取和存储对象

    配置扫描路径是使用注解之前的前置工作,是非常重要的,是必须的操作项.只有被配置的包下的所有类,添加了注解才能被正确的识别并保存到 Spring 中. 首先创建一个Spring项目.创建好后,第一步就是配置扫描路径:在 resources 目录中创建一个 spring-config.xml 文件.然后在 spring-config.

    2024年02月12日
    浏览(42)
  • 从 Spring 的创建到 Bean 对象的存储、读取

    目录 创建 Spring 项目: 1.创建一个 Maven 项目:  2.添加 Spring 框架支持: 3.配置资源文件: 4.添加启动类: Bean 对象的使用: 1.存储 Bean 对象: 1.1 创建 Bean: 1.2 存储 Bean 到容器内: 2.获取 Bean 对象: 2.1 创建 Spring 上下文: 2.2 获取指定 Bean 对象: ApplicationContext 和 BeanFactor

    2024年02月06日
    浏览(40)
  • JavaEE 突击 5 - Spring 更简单的读取和存储对象(2)

    大家新年快乐 , 祝大家新的一年如图 这个专栏给大家介绍一下 Java 家族的核心产品 - SSM 框架 JavaEE 进阶专栏 Java 语言能走到现在 , 仍然屹立不衰的原因 , 有一部分就是因为 SSM 框架的存在 接下来 , 博主会带大家了解一下 Spring、Spring Boot、Spring MVC、MyBatis 相关知识点 并且带领

    2024年02月19日
    浏览(53)
  • 【JavaEE】DI与DL的介绍-Spring项目的创建-Bean对象的存储与获取

    Spring的开发要点总结 Spring的初步了解博客:【JavaEE】JavaEE进阶:框架的学习 - Spring的初步认识_s:103的博客-CSDN博客 就不带大家回顾了~ 从框架获取的对象称为获取【Bean对象】! Java是咖啡,Bean就是\\\"咖啡豆\\\",也就是“对象” Spring项目开发就是 开业 , 放咖啡豆到罐子里 , 后

    2024年02月16日
    浏览(39)
  • 3. Spring 更简单的读取和存储对象(五大类注解 & 方法注解)

    目录 1. 存储 Bean 对象 1.1 配置扫描路径 1.2 添加注解存储 Bean 对象 1.2.1 @Controller(控制器存储) 1.2.2 @Service(服务存储) 1.2.3 @Repository(仓库存储) 1.2.4 @Component(组件存储) 1.2.5 @Configuration(配置存储) 1.3 使用多个类注解的原因 1.3.1 五大注解之间的关系 1.3.1 Bean 的命名

    2024年02月15日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包