• 基于Spring更简单的读取和存储对象


    在spring的创建和使用这篇博客中有讲到关于Spring存储和读取Bean对象的操作,但是细心的朋友有没有发现那些操作没有想象中的简单呢?所以呀,我今天要给朋友分享的是更简单的存储和读取Bean对象的方法,快来看看吧~

     

    在Spring中想要更简单的存储和读取对象的核心就是使用注解,这就是我接下来要给朋友讲的啦

    讲注解之前,先要在配置文件中添加扫描路径.

    目录

    1、存储Bean对象

    1.1 配置扫描路径

    1.2 添加注解存储Bean对象

    1.2.1 @Controller(控制器存储)

    1.3 各类注解的含义

    1.4 方法注解

    1.4.1 方法注解需要配合类注解使用

    1.4.2 重命名Bean

    2. 获取Bean对象

    2.1 属性注入

    2.2 setter注入

    2.3 构造方法注入

    2.4 @Resource


    1、存储Bean对象

    想要将对象成功的存储到Spring中,我们需要先配置一下存储对象的扫描包路径,只有被配置了的包下的所有类,添加注解后才能被正确的识别并保存到Spring中.

    1.1 配置扫描路径

    在 spring-config.xml (此文件为resources目录下自己创建的一个xml文件)中添加如下配置:

     这一步很重要,因为即使添加了注解,但如果不是在配置的扫描包下的类对象,仍然是不能被存储到Spring中的.例如上图,只要是在com.zl包下的加了注解的类的对象都可以被存储到Spring中.

    1.2 添加注解存储Bean对象

    若想将Bean对象成功存储到Spring中,有两种类型的注解可以实现:

    • 类注解:@Controller,@Service,@Repository,@Component,@Configuration.
    • 方法注解:@Bean

    1.2.1 @Controller(控制器存储)

    使用@Controller存储bean的代码如下所示:

    读取并使用Bean:

    运行APP类,得到一下结果:

     以上是五大类注解中@Controller的使用方法,其他四大注解的使用方法与之相同.在这里就不一一演示了.但是现在可能朋友你就要问了,为什么使用方法一样,用一个就好了呀,但是要有这么多类注解呢,接下来我们来看.

    1.3 各类注解的含义

    为什么要有这么多种类注解,这就和自己的身份证号的前两位一样,比如北京市的身份证号前两位就是11,河北省的前两位是13,湖北省的前两位42等,每个省的身份证号的其两位都不同,这样做的最大的作用就是可以直观的标识这个身份证所处的归属地.

    同样这也是为什么需要这么多类注解一样,就是为了方便程序员看到类注解之后,就能直接了解当前类的用途,以下是这些类注解所要传达给程序员的信息:

    @Controller:控制类,业务逻辑层,主要验证前端发过来的参数

    @Servie:服务类,服务层,数据的处理和接口的调用

    @Repository:仓库类,持久层,主要是对数据库的操作,也叫作Dao类

    @Configuration:配置类,一些主要负责配置信息的类

    @Component:组件类,一些外部实现的工具类

    程序的工程分层,调用流程如下:

     注:@Component是其他四类类注解的"父类".

    1.4 方法注解

    类注解是添加在某个类上的,而方法注解是添加到某个方法上的,以下是代码实现:

    然后我们在主函数上调用一下bean对象中的user方法,代码如下:

    运行一下代码,发现报错,为什么呢?我们来看一下报错信息:

     通过报错信息我们可以发现,user找不到,为什么呢,是因为UserController这个类对象没有添加类注解,所以就没有存储到Spring中,所以自然就不能调用这个对象的方法了,所以,我们还要在类上添加一个类注解. 

    1.4.1 方法注解需要配合类注解使用

    在Spring框架的设计中,方法注解@Bean需要结合类注解才能将对象正常的存储到Spring容器中,如下图代码所示:

    我们再来运行一下,得到以下结果:

    这样就达到了我们的预期结果.

     通过以上例子我们得出一个小小的结论:类注解需要与方法注解搭配使用.

    1.4.2 重命名Bean

    可以通过name属性给Bean对象进行重命名操作,如下代码所示:

    然后我们使用user1就可以获取到User对象了,如以下代码所示:

    另外,这个重命名的name其实是一个数组,一个bean可以有多个名字,代码如下:

    以上写法的话,不论我们是用 user1 还是 user2 都可以获取到User对象了,但是一旦重命名后,就不能写原来的user了.

    补充:重命名时,name={}是可以省略的,就像这样:

    @Bean("user1")
    @Bean({"user1","user2"})

    以上两种重命名的格式都是对的

    2. 获取Bean对象

    获取Bean对象也叫装配,是把对象取出来放到某个类中,也叫作对象注入.

    对象注入的实现方法有以下3种:

    • 属性注入
    • 构造方法注入
    • Setter注入

    下面我将仔细讲解一下这三种注入方式,按照实际开发中的模式,将 Service 类注入到 Controller 类中

    2.1 属性注入

    属性注入是用 @Autowired 实现的,将 Service 类注入到 Controller 类中.

    Service 类的实现代码如下:

     

    Controller 类的实现代码如下:

     获取Controller中的getUser方法:

     运行结果如下:

     

     属性注入的核心实现为:

    属性注入的优缺点分析:

    优点: 写法精简,可读性高

    缺点: 首先官方就不推荐使用, 专业版 IDAE 会报警告提示.

    • 功能方面: 无法注入一个被 final 修饰的对象;容易引起空指针异常​​​​​​     
    • 通用性方面: 只适用于 IoC 容器
    • 设计原则方面: 更加容易违背单一设计原则

    无法注入一个被 final 修饰的对象​​​​​​ :

    这与java中的语法有关,因为对于被final修饰的对象,只有两种方式对其进行赋值,

    • 在声明时直接赋值
    • 通过构造方法赋值

    容易引起空指针异常:

     只适用于 IoC 容器:

    属性注入的方式只适用于 IoC 容器,  在非 IoC 框架中使用不了, 可移植性不高, 所以属性注入的通用性不是很好.

     更加容易违背单一设计原则:

    因为属性注入的写法相对来说较为简单,就容易引起这种注入方式的滥用,所以更容易违背单一性原则.但是并不是说一定会违背,只是有这个可能.

    2.2 setter注入

    setter注入的核心实现为:

    Setter注入优缺点分析:

    优点:Setter 注入完全符合单一设计原则, 一个 Setter 方法只针对一个对象.

    缺点:

    • 不能注入final修饰的对象
    • 注入的对象有被修改的风险

    不能注入final修饰的对象:

    原因和属性注入一样,final修饰的对象要么直接赋值,要么在构造方法中赋值.

    注入的对象有被修改的风险:

    因为 Setter 注入提供了 setXXX() 方法, 就意味着 setXXX() 可以被调用,  既然能被调用, 则 Setter 注入的对象随时都有被修改的风险.

    2.3 构造方法注入

    构造方法注入的核心实现为:

    注意:如果只有一个构造方法,则@Autowired可以省略.如果有多个构造方法,则必须在需要注入的构造方法上加入@Autowired表明哪一个是需要被注入的.另外只能注入一个构造方法,因为在普通程序中,我们创建new一个对象时,会根据参数调用其中一个构造方法.

    构造方法优缺点分析:

    优点:首先它是当前Spring的推荐写法

    1. 可以注入不可变对象
    2. 注入的对象不会被修改
    3. 依赖对象在使用前一定会被完全初始化
    4. 通用性更好

    缺点:写法较为复杂,如果注入对象很多,则代码看起来更臃肿.

    可以注入不可变对象:

    上面有讲到,被final修饰的属性可以通过构造方法赋值,故在构造方法注入时,可以给final对象赋值

    注入的对象不会被修改:

    构造方法注入, 在程序执行的时候, 它只会执行一次, 所以不会像 Setter 注入那样被调用多次, 也就不存在被修改的情况.

    依赖对象在使用前一定会被完全初始化:

    因为我们要注入的对象是在构造方法中实现的,构造方法的执行比类的创建要早, 所以我们要使用的注入的对象, 一定是被完全初始化的.

    通用性更好:

    构造方法是 JDK 支持的,  往往越底层的框架, 它的可移植性就越好, 所以换做其他任何框架都是适用的.

    2.4 @Resource

    在进⾏类注⼊时,除了可以使⽤ @Autowired 关键字之外,我们还可以使⽤ @Resource 进⾏注⼊,如 下代码所示:

     @Autowired 和 @Resource 的区别:

    • 来源不同:@Autowired 来⾃于 Spring,⽽ @Resource 来⾃于 JDK 的注解;
    • 使用时设置的参数不同:相⽐于 @Autowired 来说,@Resource ⽀持更多的参数设置,例如 name 设置,根据名称获取 Bean.
    • @Autowired 可⽤于 Setter 注⼊、构造函数注⼊和属性注⼊,⽽ @Resource 只能⽤于 Setter 注 ⼊和属性注⼊,不能⽤于构造函数注⼊。

    同一类型对应多个Bean时,如何注入自己想要的Bean?

    比如当出现以下多个Bean,返回同一对象类型时程序会报错,如下代码所示:

     

    在另一个类中获取User对象,如下:

     

     

    执行以上程序:

    报错原因:非唯一的Bean对象。

    那怎么解决呢?有以下两种方法:

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

    • 使⽤ @Resource(name="user1") 定义。
    • 使⽤ @Qualifier 注解定义名称

    1)、使⽤ @Resource(name="user1") 定义:

     2)、使⽤ @Qualifier(需要搭配@Autowired)

     两者的运行结果都是:

    这样问题就解决了~


     好啦,到这里就结束啦,回顾一下,五大类注解分别是什么以及他们之间各自起到的标识作用是什么,怎样存储对象、从Spring中获取对象的方式有哪几种,分别怎么获取,这几种方式的优缺点又是什么呢?相信认真看完这篇博客的朋友你应该知道了吧,要是回答不上来,那就再看一下吧

     

    还有,有什么不理解的地方或建议或错误都欢迎指出哦,评论区私信都可~~~

     

     

     

  • 相关阅读:
    chrome 开启HEVC硬件解码
    第二章 基于模型的系统工程 P1|系统建模语言SysML实用指南学习
    C++ primer plus--输入、输出和文件
    Java项目:springboot电影推荐网站
    GPT-4 等大语言模型(LLM)如何彻底改变客户服务
    视频编码原理及Gstreamer 硬编码代码实现
    iOS性能监控及自动化测试辅助工具对比-tidevice、py-ios-device(pyidevice)、sonic-ios-bridge(sib)
    深度学习遥感数据集
    ThingsBoard教程(二八):详细讲解在tb平台下 mqtt协议下的 rpc 遥测,客户端rpc,服务的rpc的使用 ,与node-red联动
    2022-08-26
  • 原文地址:https://blog.csdn.net/m0_63039919/article/details/128018310