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.2 Bean 命名规则

1.4 方法注解 @Bean

 1.4.1 ⽅法注解要配合类注解使⽤

 1.4.2 重命名 Bean

2.获取 Bean 对象(对象装配)

2.1 属性注入

2.2 构造方法注入

2.3 Setter 注入

2.4 三种注入优缺点分析

2.5 @Resource:另⼀种注⼊关键字

@Autowired 和 @Resource 的区别

2.6 同⼀类型多个 @Bean 报错

总结


在 Spring 中想要更简单的存储和读取对象的核⼼是使⽤注解,也就是我们接下来要学习 Spring 中的相关注解,来存储和读取 Bean 对象。

1.存储 Bean 对象

之前我们存储 Bean 时,需要在 spring-config 中添加⼀⾏ bean 注册内容才⾏,如下图所示:

⽽现在我们只需要⼀个注解就可以替代之前要写⼀⾏配置的尴尬了,不过在开始存储对象之前,我们先要来点准备⼯作。

 1.1 前置⼯作:配置扫描路径

注意:想要将对象成功的存储到 Spring 中,我们需要配置⼀下存储对象的扫描包路径,只有被配置的包下的所有类,添加了注解才能被正确的识别并保存到 Spring 中。
在 spring-config.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="org.example"></content:component-scan>
</beans>
即使添加了注解,如果不是在配置的扫描包下的类对象,也是不能被存储到 Spring 中的。

1.2 添加注解存储 Bean 对象

想要将对象存储在 Spring 中,有两种注解类型可以实现:
  1. 类注解:@Controller、@Service、@Repository、@Component、@Configuration。
  2. ⽅法注解:@Bean。
接下来我们分别来看。

1.2.1 @Controller(控制器存储)

使⽤ @Controller 存储 bean 的代码如下所示:
@Controller // 将对象存储到 Spring 中
public class UserController {public void sayHi(String name) {System.out.println("Hi," + name);}
}
此时我们先使⽤之前读取对象的⽅式来读取上⾯的 UserController 对象,如下代码所示:
public class App {public static void main(String[] args) {// 1.得到 spring 上下⽂ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");// 2.得到 beanUserController userController = (UserController) context.getBean("userController");// 3.调⽤ bean ⽅法userController.sayHi("zhangsan");}
}

1.2.2 @Service(服务存储)

使⽤ @Service 存储 bean 的代码如下所示:
@Service
public class UserService {public void sayHi(String name) {System.out.println("Hi," + name);}
}
读取 bean 的代码:
public class App {public static void main(String[] args) {// 1.得到 spring 上下⽂ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");// 2.得到 beanUserService userService = (UserService) context.getBean("userService");// 3.调⽤ bean ⽅法userService.sayHi("lisi");}
}

1.2.3 @Repository(仓库存储)

使⽤ @Repository 存储 bean 的代码如下所示:
@Repository
public class UserRepository {public void sayHi(String name) {System.out.println("Hi," + name);}
}
读取 bean 的代码:
public class App {public static void main(String[] args) {// 1.得到 spring 上下⽂ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");// 2.得到某个 beanUserRepository userRepository = (UserRepository) context.getBean("userRepository");// 3.调⽤ bean ⽅法userRepository.sayHi("zhangsan");}
}

1.2.4 @Component(组件存储)

使⽤ @Component 存储 bean 的代码如下所示:

@Component
public class UserComponent {public void sayHi(String name) {System.out.println("Hi," + name);}
}
读取 bean 的代码:
public class App {public static void main(String[] args) {// 1.得到 spring 上下⽂ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");// 2.得到某个 beanUserComponent userComponent = (UserComponent) context.getBean("userComponent");// 3.调⽤ bean ⽅法userComponent.sayHi("lisi");}
}

1.2.5 @Configuration(配置存储)

使⽤ @Configuration 存储 bean 的代码如下所示:
@Configuration
public class UserConfiguration {public void sayHi(String name) {System.out.println("Hi," + name);}
}
读取 bean 的代码:
public class App {public static void main(String[] args) {// 1.得到 spring 上下⽂ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");// 2.得到某个 beanUserConfiguration userConfiguration = (UserConfiguration) context.getBean("userConfiguration");// 3.调⽤ bean ⽅法userConfiguration.sayHi("Bit");}
}

1.3 为什么要这么多类注解?

这和为什么每个省/市都有⾃⼰的⻋牌号是⼀样的?⽐如陕⻄的⻋牌号就是:陕X:XXXXXX,北京的⻋牌号:京X:XXXXXX,⼀样。甚⾄⼀个省不同的县区也是不同的,⽐如⻄安就是,陕A:XXXXX,咸阳:陕B:XXXXXX,宝鸡,陕C:XXXXXX,⼀样。这样做的好处除了可以节约号码之外,更重要的作⽤是可以直观的标识⼀辆⻋的归属地。
那么为什么需要怎么多的类注解也是相同的原因,就是让程序员看到类注解之后,就能直接了解当前类的⽤途,⽐如:
  • @Controller:表示的是业务逻辑层;
  • @Servie:服务层;
  • @Repository:持久层;
  • @Configuration:配置层。
程序的⼯程分层,调⽤流程如下:

 1.3.1 类注解之间的关系

查看 @Controller / @Service / @Repository / @Configuration 等注解的源码发现:
其实这些注解⾥⾯都有⼀个注解 @Component,说明它们本身就是属于 @Component 的“⼦类”。

1.3.2 Bean 命名规则

通过上⾯示例,我们可以看出,通常我们 bean 使⽤的都是标准的⼤驼峰命名,⽽读取的时候首字母小写就可以获取到 bean 了,如下图所示:

 但是,当我们⾸字⺟和第⼆个字⺟都是⼤写时,就不能正常读取到 bean 了,如下图所示:

这个时候,我们就要查询 Spring 关于 bean 存储时⽣成的命名规则了。
我们可以在 Idea 中使⽤搜索关键字“beanName”可以看到以下内容:

 顺藤摸⽠,我们最后找到了 bean 对象的命名规则的⽅法:

 它使⽤的是 JDK Introspector 中的 decapitalize ⽅法,源码如下:

public static String decapitalize(String name) {if (name == null || name.length() == 0) {return name;}// 如果第⼀个字⺟和第⼆个字⺟都为⼤写的情况,是把 bean 的⾸字⺟也⼤写存储了if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&Character.isUpperCase(name.charAt(0))){return name;}// 否则就将⾸字⺟⼩写char chars[] = name.toCharArray();chars[0] = Character.toLowerCase(chars[0]);return new String(chars);
}

1.4 方法注解 @Bean

类注解是添加到某个类上的,⽽⽅法注解是放到某个⽅法上的,如以下代码的实现:
public class Users {@Beanpublic User user1() {User user = new User();user.setId(1);user.setName("Java");return user;}
}
获取 bean 对象中的 user1 
public class App2 {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");User user = (User) context.getBean("user1");System.out.println(user.toString());}
}
然⽽,当获取 bean 对象中的 user1 时却发现,根本获取不到:

 1.4.1 ⽅法注解要配合类注解使⽤

在 Spring 框架的设计中,⽅法注解 @Bean 要配合类注解才能将对象正常的存储到 Spring 容器中,如下代码所示:
@Component
public class Users {@Beanpublic User user1() {User user = new User();user.setId(1);user.setName("Java");return user;}
}
再次执⾏以上代码,运⾏结果如下:

 1.4.2 重命名 Bean

可以通过设置 name 属性给 Bean 对象进⾏重命名操作,如下代码所示:
@Component
public class Users {@Bean(name = {"u1"})public User user1() {User user = new User();user.setId(1);user.setName("Java");return user;}
}
此时我们使⽤ u1 就可以获取到 User 对象了,如下代码所示:
class App {public static void main(String[] args) {// 1.得到 spring 上下⽂ApplicationContext context =new ClassPathXmlApplicationContext("spring-config.xml");// 2.得到某个 beanUser user = (User) context.getBean("u1");// 3.调⽤ bean ⽅法System.out.println(user);}
}
重命名的 name 其实是⼀个数组,⼀个 bean 可以有多个名字;
并且 name={} 可以省略。

2.获取 Bean 对象(对象装配)

获取 bean 对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注⼊。
对象装配(对象注⼊)的实现⽅法以下 3 种:
  1. 属性注⼊
  2. 构造⽅法注⼊
  3. Setter 注⼊
下⾯我们按照实际开发中的模式,将 Service 类注⼊到 Controller 类中。

2.1 属性注入

属性注⼊是使⽤ @Autowired 实现的,将 Service 类注⼊到 Controller 类中。
Service 类的实现代码如下:
@Service
public class UserService {/*** 根据 ID 获取⽤户数据** @param id* @return*/public User getUser(Integer id) {// 伪代码,不连接数据库User user = new User();user.setId(id);user.setName("Java-" + id);return user;}
}
Controller 类的实现代码如下:
@Controller
public class UserController {// 注⼊⽅法1:属性注⼊@Autowiredprivate UserService userService;public User getUser(Integer id) {return userService.getUser(id);}
}
获取 Controller 中的 getUser ⽅法:
public class UserControllerTest {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");UserController userController = context.getBean(UserController.class);System.out.println(userController.getUser(1).toString());}
}
最终结果如下:

2.2 构造方法注入

构造⽅法注⼊是在类的构造⽅法中实现注⼊,如下代码所示:
@Controller
public class UserController2 {// 注⼊⽅法2:构造⽅法注⼊private UserService userService;@Autowiredpublic UserController2(UserService userService) {this.userService = userService;}public User getUser(Integer id) {return userService.getUser(id);}
}

如果只有⼀个构造⽅法,那么 @Autowired 注解可以省略

但是如果类中有多个构造⽅法,那么需要添加上 @Autowired 来明确指定到底使⽤哪个构造⽅法,否则程序会报错

2.3 Setter 注入

Setter 注⼊和属性的 Setter ⽅法实现类似,只不过在设置 set ⽅法的时候需要加上 @Autowired 注
解,如下代码所示:
@Controller
public class UserController3 {// 注⼊⽅法3:Setter注⼊private UserService userService;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}public User getUser(Integer id) {return userService.getUser(id);}
}

2.4 三种注入优缺点分析

属性注⼊

  • 优点是简洁,使⽤⽅便;
  • 缺点是只能⽤于 IoC 容器,如果是⾮ IoC 容器不可⽤,并且只有在使⽤的时候才会出现 NPE(空指针异常)。不能注入一个final修饰的属性。

构造⽅法注⼊

  • 优点是可以注入final修饰的属性,注入的对象不会被修改,依赖对象在使用前一定会被完全初始化,通用性好
  • 缺点是如果有多个注⼊会显得⽐较臃肿,但出现这种情况你应该考虑⼀下当前类是否符合程序的单⼀职责的设计模式了

Setter 注入

  • 优点是方便再类实例之后,重新对该对象进行配置或注入
  • 不能注入一个final修饰的属性;注入对象可能会被改变,因为setter方法可能会被多次调用,就有被修改的风险

补充:

final修饰的属性,需要具备下列两个条件之一:

2.5 @Resource:另⼀种注⼊关键字

在进⾏类注⼊时,除了可以使⽤ @Autowired 关键字之外,我们还可以使⽤ @Resource 进⾏注⼊,如下代码所示:
@Controller
public class UserController {// 注⼊@Resourceprivate UserService userService;public User getUser(Integer id) {return userService.getUser(id);}
}

@Autowired 和 @Resource 的区别

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

2.6 同⼀类型多个 @Bean 报错

当出现以下多个 Bean,返回同⼀对象类型时程序会报错,如下代码所示:
@Component
public class Users {@Beanpublic User user1() {User user = new User();user.setId(1);user.setName("Java");return user;}@Beanpublic User user2() {User user = new User();user.setId(2);user.setName("MySQL");return user;}
}
在另⼀个类中获取 User 对象,如下代码如下:
@Controller
public class UserController4 {// 注⼊@Resourceprivate User user;public User getUser() {return user;}
}

 报错的原因是,⾮唯⼀的 Bean 对象。

同⼀类型多个 Bean 报错处理
解决同⼀个类型,多个 bean 的解决⽅案有以下两个:
  • 使⽤ @Resource(name="user1") 定义。
  • 使⽤ @Qualifier 注解定义名称。
① 使⽤ @Resource(name="XXX")
@Controller
class UserController4 {// 注⼊@Resource(name = "user1")private User user;public User getUser() {return user;}
}
② 使⽤ @Qualifier
@Controller
public class UserController5 {// 注⼊@Autowired@Qualifier(value = "user2")private User user;public User getUser() {return user;}
}

总结

1. 将对象存储到 Spring 中:
        a. 使⽤类注解:@Controller、@Service、@Repository、@Configuration、@Component【它们之间的关系】
        b. 使⽤⽅法注解:@Bean【注意事项:必须配合类注解⼀起使⽤】
2. Bean 的命名规则:⾸字⺟和第⼆个字⺟都⾮⼤写,⾸字⺟⼩写来获取 Bean,如果⾸字⺟和第⼆个字⺟都是⼤写,那么直接使⽤原 Bean 名来获取 Bean。
3. 从 Spring 中获取对象:
        a. 属性注⼊
        b. Setter 注⼊
        c. 构造函数注⼊(推荐)
4. 注⼊的关键字有:
        a. @Autowired
        b. @Resource
5. @Autowired 和 @Resource 区别:出身不同; 使⽤时设置参数不同 @Resource ⽀持更多的参
数,⽐如 name。
6. 解决同⼀类型多个 Bean 的报错:
        a. 使⽤ @Resource(name="")
        b. 使⽤ @Qualifier(value="")

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

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

相关文章

C++---string

String C语言中的字符串和C中的string类标准库中的string类string类的常用接口string类对象的常见构造string类对象的容量操作string类对象的访问及遍历操作 C语言中的字符串和C中的string类 在C语言中&#xff0c;字符串是一个字符数组&#xff0c;它以空字符\0结尾&#xff…

【数据结构】朴素模式匹配 KMP算法

&#x1f387;【数据结构】朴素模式匹配 & KMP 算法&#x1f387; &#x1f308; 自在飞花轻似梦,无边丝雨细如愁 &#x1f308; &#x1f31f; 正式开始学习数据结构啦~此专栏作为学习过程中的记录&#x1f31f; 文章目录 &#x1f387;【数据结构】朴素模式匹配 & K…

【数据架构】Data Fabric 架构是实现数据管理和集成现代化的关键

D&A 领导者应该了解数据编织架构的关键支柱&#xff0c;以实现机器支持的数据集成。 在日益多样化、分布式和复杂的环境中&#xff0c;数据管理敏捷性已成为组织的任务关键优先事项。为了减少人为错误和总体成本&#xff0c;数据和分析 (D&A) 领导者需要超越传统的数据…

MyBatis操作数据库

1.MyBatis是什么&#xff1f; MyBatis 是⼀款优秀的持久层框架&#xff0c;它⽀持⾃定义 SQL、存储过程以及⾼级映射。MyBatis 去除了⼏乎所有的 JDBC 代码以及设置参数和获取结果集的⼯作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接⼝和 Java POJO&#xf…

【机器学习】吃瓜教程 | 西瓜书 + 南瓜书 (1)

文章目录 一、绪论1、什么是机器学习&#xff1f;2、基本术语3、假设空间4、归纳偏好5、发展历程 二、模型评估与选择A、一种训练集一种算法2.1 经验误差 与 过拟合2.2 评估方法a) 留出法b) 交叉验证法c) 自助法d) 调参与最终模型 2.3 性能度量a) 错误率与精度b) 查准率、查全率…

matlab dot()函数求矩阵内积,三维 ,多维 详解

matlab dot()函数求矩阵内积&#xff0c;三维 &#xff0c;多维 详解 Cdot(A,b,X)&#xff0c;这个参数X 只能取1,或者2。1 表示按列&#xff0c;2表示按行&#xff0c;如果没有参数。默认按列。 1&#xff09;按列优先计算 Cdot(A,B)dot(A,B,1)[a1*b1a4*b4 ,a2*b2a5*b5 ,a…

视频拼接得AI三维生成方案-开端(一)

想使用二维得图像生成三维得空间图像&#xff0c;英伟达有完整得方案&#xff0c;开源&#xff0c;但是三维拼接不一样&#xff0c;只需要二维&#xff0c;并且要实时&#xff0c;如何生成是我每天都在思考得东西。 cnn 提取特征器和自编码 在训练细胞神经网络时&#xff0c;问…

大数据分析案例-基于LightGBM算法构建乳腺癌分类预测模型

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

jmeter软件测试实验(附源码以及配置)

jmeter介绍 JMeter是一个开源的性能测试工具&#xff0c;由Apache软件基金会开发和维护。它主要用于对Web应用程序、Web服务、数据库和其他类型的服务进行性能测试。JMeter最初是为测试Web应用程序而设计的&#xff0c;但现在已经扩展到支持更广泛的应用场景。 JMeter 可对服务…

AcWing 244. 谜一样的牛—树状数组、二分

题目链接 AcWing 244. 谜一样的牛 题目描述 分析 这道题挺巧妙的&#xff0c;感觉树状数组方面的题就是比较难想&#xff0c;先分析一下样例&#xff0c;样例中每头牛前面比自己低的牛的数量分别为 0 1 2 1 0牛的高度是1~n的排列&#xff0c;如何分析出每头牛的高度呢&…

API Testing 一个基于 YAML 文件的开源接口测试工具

目录 前言&#xff1a; 如何使用&#xff1f; 本地模式 服务端模式 文件格式 后续计划 前言&#xff1a; API Testing 是一个基于 YAML 文件的开源接口测试工具&#xff0c;它可以帮助开发者快速地进行接口测试。 在选择工具时&#xff0c;可以从很多方面进行考量、对比…

【历史上的今天】7 月 20 日:人类登上月球;数据仓库之父诞生;Mac OS X Lion 发布

整理 | 王启隆 透过「历史上的今天」&#xff0c;从过去看未来&#xff0c;从现在亦可以改变未来。 今天是 2023 年 7 月 20 日&#xff0c;在 2005 年的今天&#xff0c;时任微软全球副总裁的李开复加盟谷歌担任谷歌全球副总裁及中国区总裁。谷歌公司在发布聘请李开复消息的同…

LiveNVR监控流媒体Onvif/RTSP功能-拉转Onvif/RTSP/RTMP/FLV/HLS直播流流媒体服务视频广场页面集成视频播放集成说明

LiveNVR拉转Onvif/RTSP/RTMP/FLV/HLS直播流流媒体服务视频广场页面集成视频播放集成说明 1、视频页面集成1.1、关闭接口鉴权1.2、视频广场页面集成1.2.1、隐藏菜单栏1.2.2、隐藏播放页面分享连接 1.3、其它页面集成 2、播放分享页面集成2.1、获取 iframe 代码2.2、html 集成ifr…

ThreadPoolExecutor自定义线程池|拒绝策略|线程工厂|统一捕获异常

线程池的7大参数含义介绍 corePoolSize&#xff1a;池中一直保持的线程的数量。 maximumPoolSize&#xff1a;池中允许的最大的线程数。 keepAliveTime&#xff1a;当线程数大于核心线程数的时候&#xff0c;线程在最大多长时间没有接到新任务就会终止释放&#xff0c; 最终…

Python 集合 union()函数使用详解,Python合并集合

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;小白零基础《Python入门到精通》 union函数使用详解 1、合并多个集合2、合并其他类型2.1、合并字符串2.2、合并列表…

Linux超详细的了解

文章目录 前言Linux的简介不同应用领域的主流操作系统Linux系统历史Linux系统各版本 Linux的安装安装方式介绍安装Linux网卡设置安装SSH连接工具finalShell连接虚拟机Linux和Windows目录结构对比Linux目录介绍 Linux常用命令Linux命令初体验文件目录命令ls命令cd命令cat命令mor…

Hbase基本原理剖析

一、基本原理 数据存储使用HBase来承接&#xff0c;HBase是一个开源的、面向列&#xff08;Column-Oriented&#xff09;、适合存储海量非结构化数据或半结构化数据的、具备高可靠性、高性能、可灵活扩展伸缩的、支持实时数据读写的分布式存储系统。更多关于HBase的信息&#…

html 解决css样式 缓存 ---css引入添加时间戳

通过js 对引入的css添加时间戳 <script type"text/javascript">document.write("<link relstylesheet typetext/css href./style/base.css?v" new Date().getTime() ">");document.write("<link relstylesheet typetext…

IDEA: 将第三方依赖打入jar包

文章目录 一、添加自定义的jar包到lib目录下二、将自定义依赖包打入jar包方式1、使用springboot自带的插件 一、添加自定义的jar包到lib目录下 参考往期文章&#xff1a;IDEA中Java项目创建lib目录(添加依赖jar包代替maven依赖) 二、将自定义依赖包打入jar包 方式1、使用spr…

windows系统安装异构虚拟机arm版的银河麒麟服务器

下载qemu UEFI&#xff08;BIOS的替代方案&#xff09;的下载地址&#xff1a;http://releases.linaro.org/components/kernel/uefi-linaro/16.02/release/qemu64/QEMU_EFI.fd QEMU 软件的下载地址&#xff1a;https://qemu.weilnetz.de/w64/2021/qemu-w64-setup-20210505.exe …