Spring基于注解读取和存储对象

news2024/11/23 14:59:30

目录

一. 存储 Bean 对象 

1. 前置工作:配置扫描路径

2. 使用五大类注解存储Bean对象

@Controller 

 命名规则

@Service

@Repository

@Compoent

@Configuration

五大类注解之间的关系

 3. 使用方法注解存储Bean对象

 二. 获取 Bean 对象

1. 属性注入

优点分析

缺点分析 

2. Setter 注入 

优点分析

缺点分析 

3. 构造方法注入

优点分析


通过前面的学习,我们学习实现了基本的 Spring 读取和存储对象,但在日常的开发中,往往采用更简单的方式,也就是利用注解来进行读取和存储Bean对象。

一. 存储 Bean 对象 

1. 使用五大类注解:

  1. @Controller
  2. @Service
  3. @Repository
  4. @Component
  5. @Configuration

2. 使用方法注解 @Bean 

1. 前置工作:配置扫描路径

为了让对象成功的存储在Spring中,就必须配置一下存储对象的扫描路径,通过扫描路径来决定是要对哪个路径下的对象进行存储到Spring容器中。同时,并不是在扫描路径下的所有类都会被保存到Spring中。只有在扫描路径下,同时添加了注解,才能被正确的识别并保存到Spring中。   也就是说,即使添加了注解,如果不是在配置的扫描包下的类对象,也是不能被存储到 Spring 中的。

配置扫描路径,就需要在spring配置文件中,添加语句:

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

base-package字段就表示要扫描的路径。添加扫描路径后,扫描的范围不止该路径本身,还会包括该路径的所有子路径。

2. 使用五大类注解存储Bean对象

 添加注解后,扫描路径内的类就会作为Bean对象存储于Spring容器中了。

@Controller 

这个注解可以理解为是一个 "控制器",用来验证用户请求的数据正确性。

这个注解也可以传入参数,这个参数可以作为这个Bean对象的名称。

// @Controller("stu")
@Controller // 将当前类存储到 spring 中
public class StudentController {
    public static void say(){
        System.out.println(" do student controller ");
    }
}

 用代码进行演示:

 命名规则

当注解里没有带有参数的时候,那么会有默认的命名规则,此处的名称指的是 getBean()方法中的第一个参数id。这里先总结一下再进行分析:

Bean 命名规则:

1. 默认情况下是首字母变为小写。例如:Student 这个类就对应为 student,StudentName 就对应为 studentName;

2. 如果类名首字母和第二个字母都为大写的情况下,那么对应的 Bean名称就为原类名。例如:CStudent 就对应为 CStudent,SController 就对应为 SController;

 从源码分析:

 

也可以对这个方法进行运行一下:

@Service

 这个注解可以理解为是 "服务层",用于调度具体的执行方法。

@Repository

这个注解可以理解为是"数据持久层",用于与数据库进行交互。 

@Compoent

这个注解可以理解为是"组件层",用于存放一些工具类。

@Configuration

这个注解可以理解为是"配置层",用于存放项目中的一些配置。

五大类注解之间的关系

实际上,五大类注解的作用都是一样的,之所以需要分五大注解,是基于软件开发模型的,为了让程序员看到类注解后,就能直接了解到当前类的用途。这种作用就类似于广东省内的车牌分为粤A,粤B,粤C等,A,B,C...的加入可以让我们一看车牌就知道是广州,深圳,珠海的车。 

在 JavaEE 中,标准分层至少分为三层: 

 通过观察 @Controller,@Service,@Repository,@Configuration等注解的源码可以看出,他们都属于 @Component 的子类。

 3. 使用方法注解存储Bean对象

类注解是添加到某个类上的,⽽⽅法注解是放到某个⽅法上的。

1. 先新建一个User类:


public class User {
    public int id;
    public String name;
    public int age;

    public int getId() {
        return id;
    }

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

    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;
    }
}

 2. 给方法添加注解

注意:

1. 此方法必须有返回值,方法的返回值就作为Bean对象存储到Spring容器中。

2. 添加方法注解 @Bean 必须是在五大类注解的基础上添加!!!

    这样是为了提高效率,只有被五大类注解作用的时候,并且是在扫描路径范围内,才会去将对应被修饰 @Bean 的方法进行扫描,从而将返回的Bean对象存储至Spring容器中。

3. 通过方法注解 @Bean 存储到Spring中的Bean对象默认名称为方法名。

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

此外,还可以在 @Bean 注解当中指定参数 name 或者 value,来作为存储Bean对象的名称。可以指定一个名称,也可以指定多个。

@Bean(name = {"hello","helloUser"})

注意: 当 @Bean 使用了重命名之后,那么默认的使用方法名获取对象的方式就不能再使用了,也就是说 getBean() 参数中的 id 就不能为方法名了,只能为重命名后的名称。

 3. 使用getBean获取对象

getBean() 方法的名称,在不加参数 name 的情况下,默认为方法名。加了参数 name 之后,就以参数 name 的指定名称为准。 

补充:在方法注入的时候,还可以通过注解 @order(int i) 来控制注入的顺序,i 的值越小,权重就越高,就越早注入。如果是Bean对象名称相同的情况,就有可能会发生覆盖的问题。

 二. 获取 Bean 对象

在上述我们讲解了如何去利用 五大类注解 方法注解 的方式来更加简单的存储Bean对象,那么接下来就讲解如何来更加简单的从 Spring 容器中来获取 Bean 对象。主要有三种方式:

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

1. 属性注入

通过 @Autowired 注解进行实现:

通过 @Autowired 对一个属性进行注解,就会从 Spring 中去查找是否有跟这个属性相对应的Bean对象,如果有,就将这个Bean对象赋值给对应的属性。 

例如:先在Spring容器中存储一个Bean对象:       

@Service
public class UserService {
    public int age = 10;
    public void sayHi() {
        System.out.println("do userService sayHi() -> " + age);
    }
}

 然后再在 UserController 类中,对 UserService 进行注入,并存储在Spring容器中:

@Controller
public class UserController {
    // 1. 属性注入
    @Autowired
    private UserService userService;

    public void sayHi(){
        System.out.println(userService.age);
    }
}

最后在main方法中运行得到结果:

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

可以得出 在 UserController 对象中已经成功注入了 UserService 对象。 

优点分析

属性注入使用起来简单方便,只需要给对应的属性添加注解 @Autowired ,就可以注入从Spring获得的Bean对象。 

缺点分析 

1. 属性注解存在一个问题:使用 @Autowired 注解给属性注入对象的时候, 要求 Spring 容器中有且仅有一个和 @Autowired 注入的属性相同的 Bean 对象。

例如,给Spring容器中存储两个 User对象,此时用属性注入来获取对象,就会报错。

2. 属性注入无法注入一个不可变对象,也就是被 final 修饰过的对象。而这也跟Java的语法知识是相关联的,Java中的 final 对象,要么直接赋值,要么通过构造方法赋值,所以当使用属性注入 final 对象时,它不符合 Java 中 final 的使用规范,所以就不能注入成功了。

3. 兼容性问题:使用属性注入的方式只适用于 IoC 框架。

4. 由于使用方法的简单,所以可能会违背了单一设计原则。

2. Setter 注入 

@Controller
public class UserController {
    // 2. Setter注入
    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void sayHi(){
        System.out.println(userService.age);
    }
}

优点分析

通过Setter注入的方式,相比于属性注入,它更符合于单一设计原则,因为每一个Setter只针对一个对象。

缺点分析 

1. 依旧是无法注入一个被 final 修饰的对象;

2. 由于Setter注入是通过set方法实现的,那么就有可能 set 方法被执行多次从而改变注入的对象。

3. 构造方法注入

构造方法注入是官方最推荐的一种使用方式。 将 @Autowired注解放于构造方法上。

@Controller
public class UserController {
    // 3. 构造方法注入
    private UserService userService;

    @Autowired
    public UserController(UserService userService){
        this.userService = userService;
    }
    public void sayHi(){
        System.out.println(userService.age);
    }

}

当只有一个构造方法的时候,作用在构造方法上的 @Autowired 注解是可以省略的,但是如果类中有多个构造⽅法,那么需要添加上 @Autowired 来明确指定到底使⽤哪个构造⽅法,否则程序会报错。

优点分析

1. 可注入不可变对象:使用构造方法注入,就可以注入一个被 final 修饰的对象了; 

2. 注入对象不会被修改:与 Setter注入相比,构造方法只会执行一次,也就不会再存在像 Setter注入中 set方法被调用多次从而改变注入对象;

3. 完全初始化:由于注入对象是在构造方法中执行的,而构造方法是在对象创建之初执行的,因此被注入的对象在使用之前,就会被完全初始化。

4. 通用性更好:构造方法注入可适用于任何环境,无论是 IoC 框架还是非 IoC 框架,构造方法注入的代码都是通用的,所以它的通用性更好。

补充说明:静态类的加载顺序是高于Spring的,因此在启动类 main 方法中获取对象注入,就还是采用老方法,而不采用注解。

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

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

相关文章

详解C语言string.h中常用的14个库函数(二)

本篇博客继续讲解string.h中的库函数。在上一篇博客中&#xff0c;我介绍了strlen, strcpy, strcat, strcmp这4个字符串操作函数&#xff0c;本篇博客会继续介绍strncpy, strncat, strncmp这3个类似的函数。 strcpy, strcat, strcmp这3个函数是长度不受限制的字符串操作函数&a…

预算约束下营销效果优化的端到端框架(快手)

目录 翻译&#xff1a;预算约束下营销效果优化的端到端框架 1介绍 2 .相关工作 2.1预算分配 2.2梯度估计 3我们的端到端框架 3.1符号 ​3.2两阶段范式 3.3 Marketing Goal as a Regularizer 3.4梯度估计 ​3.5训练 4实验结果 4.1数据集 4.2评价指标 4.3实现细节 …

Windows环境下NVM安装后Node/NPM命令无法使用

问题&#xff1a;Windows环境下安装nvm后&#xff0c;使用nvm安装node&#xff0c;无法使用node相关命令。 解决方案&#xff1a;注意安装的时候有两个路径&#xff0c;第一个是nvm所在的路径&#xff0c;第二个是nodejs所在的路径&#xff0c;大家需要在对应的目录下找到路径…

基于SSM的电影订票管理系统

有需要请私信或看评论链接哦 可远程调试 基于SSM的电影订票管理系统 一 介绍 基于SSM的电影订票管理系统&#xff0c;本项目分为前台和后台&#xff0c;登录角色分为普通用户和管理员。用户可注册登录&#xff0c;个人中心&#xff0c;搜索电影&#xff0c;选座购票&#xff…

机器学习——损失函数(lossfunction)

问&#xff1a;非监督式机器学习算法使用样本集中的标签构建损失函数。 答&#xff1a;错误。非监督式机器学习算法不使用样本集中的标签构建损失函数。这是因为非监督式学习算法的目的是在没有标签的情况下发现数据集中的特定结构和模式&#xff0c;因此它们依赖于不同于监督…

QMS-云质说质量 - 5 解决中小企业质量问题的钥匙在哪里?

云质QMS原创 转载请注明来源 作者&#xff1a;王洪石 引言 一个小小的质量问题可能引发蝴蝶效应 日常生活中&#xff0c;我们每天都会遇到各种各样的问题&#xff0c;并随着它们喜怒哀乐。企业也不例外&#xff0c;即使有很好的管理体系以及非常高素质的员工&#xff0c;一些错…

XGBoost模型详解

1.什么是XGBoost&#xff1f; GBDT&#xff0c;它是一种基于boosting增强策略的加法模型&#xff0c;训练的时候采用前向分布算法进行贪婪的学习&#xff0c;每次迭代都学习一棵CART树来拟合之前 t − 1 t-1 t−1 棵树的预测结果与训练样本真实值的残差。XGBoost对GBDT进行了一…

C/C++每日一练(20230424)

目录 1. 只出现一次的数字 &#x1f31f; 2. 有效的括号 &#x1f31f;&#x1f31f; 3. 递归反序正整数 &#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 只出现一次…

《站在巨人的肩膀上学习Java》

Java从诞生距今已经有28年了&#xff0c;在这段时间里&#xff0c;随着Java版本的不断迭代&#xff0c;Java新特性的不断出现&#xff0c;使得Java被使用的越来越广泛。在工程界Java语言一直是大家最喜欢的语言之一&#xff0c;Java一直排行在编程语言热门程度的前3名。 可想而…

ora_scm0导致主机负载高

今天不知道了&#xff0c;几个12.2 RAC出问题&#xff0c;有现场反馈主机负载高&#xff0c;之前连接过该环境&#xff0c;知道是12.2环境&#xff0c;直接top查看&#xff0c;发现ora_scm0经常cpu使用率100%了&#xff0c;查看hydb1主机负载正常 直接上mos文档 12.2 RAC DB B…

字节和阿里,谁的管理模式更先进?

有人说&#xff0c;字节跳动的成功&#xff0c;是商业模式和管理模式的成功。不无道理&#xff0c;相比阿里巴巴以KPI绩效考核、强制淘汰的组织管理模式来说&#xff0c;字节的模式有其先进的地方。 在商业模式上&#xff0c;字节用算法的方式&#xff0c;10倍速地提升了信息分…

2023.04.24 c++第六讲

作业&#xff1a; 1. 手动实现顺序栈&#xff0c;要求实现数据结构中&#xff0c;所有栈的相关操作 #include <iostream> #define MAXSIZE 20 //宏定义&#xff0c;栈的最大容量 using namespace std;template <typename T> class stacklink { pri…

ESXi8.0安装Windows10系统教程

本篇教程主要教大家怎么在ESXi虚拟机上安装Windows10系统&#xff0c;首先安装Windows10需要准备一个ISO系统镜像文件&#xff0c;我们可以去MSDN或者是微软官网下载。 镜像下载教程&#xff1a; 下两种方法都可以下载ISO镜像文件&#xff0c;任选其一下载即可 方法一&#xf…

BDD110 HNLP205879R1设备控制、监视、报警及打印报表等管理功能

​ BDD110 HNLP205879R1设备控制、监视、报警及打印报表等管理功能 基于ABB AC500系列PLC的水泥生产线控制系统 随着中国经济的迅速发展&#xff0c;各行各业对水泥的需求日益增加。目前国内外各大水泥企业纷纷在华兴建大型干法旋窑水泥生产线&#xff0c;这为水泥行业的发展提…

【SWAT水文模型】ArcSWAT安装

SWAT水文模型-ArcSWAT安装 安装ArcSWAT1.1 下载ArcSWAT1.2 安装ArcSWAT1.3 加载ArcSWAT 参考 SWAT水文模型原理及数据库简介可参见另一博客文章-【水文模型】SWAT水文模型原理及数据库简介。 本博客主要介绍ArcSWAT的安装。 安装ArcSWAT 1.1 下载ArcSWAT 安装之前&#xff0…

广域通信网 - 差错控制(停等 ARQ 协议、选择重发 ARQ 协议、后退 N 帧 ARQ 协议)

文章目录 1 概述2 差错控制的办法2.1 停等 ARQ 协议2.2 选择重发 ARQ 协议2.3 后退 N 帧 ARQ 协议 3 扩展3.1 流量控制3.2 网工软考真题 1 概述 #mermaid-svg-ju8w1gQxodkcBbaB {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#me…

【应急响应】后门攻击检测指南Rookit内存马权限维持WINLinux

文章目录 Windows实验常规后门&#xff1a; 网络对外连接查看 自启动测试&#xff1a;隐藏账户映像劫持屏保&登录 Linux实验常规后门&#xff1a;Rootkit后门&#xff1a;GScan rkhunter权限维持后门&#xff1a;GScan rkhunter Web层面&#xff1a;通用系统层面 主机层面后…

网络设备发现工具

什么是网络设备发现 网络设备发现是识别和映射网络基础架构&#xff08;如路由器、交换机、集线器、防火墙、无线接入点、服务器、虚拟机等&#xff09;中存在的设备和接口的过程。网络发现是网络管理的第一步&#xff0c;也是成功监控解决方案的关键。该过程不仅涉及发现网络…

【超算/先进计算学习】日报6

目录 今日已完成任务列表遇到的问题及解决方案任务完成详细笔记传统性能优化从体系结构角度理解四种计算优化途径-主频/缓存/流水线/超标量优化途径的有效适用条件存储墙与层次式存储结构数据局部性与cache循环合并循环展开循环交换循环分布循环不变量外提循环分块循环分裂 优化…

zabbix环境准备

zabbix基础设置(运维笔记) 准备三台主机配置主机名hostnamectl set-hostname --static zabbixserver.cluster.comvi /etc/hosts192.168.126.143 zabbixserver.cluster.com 192.168.126.142 agent1.cluster.com 192.168.126.141 agent2.cluster.com三台机器同步时间 ntpdate…