【JavaEE进阶】使用注解存储对象

在这里插入图片描述

使用注解存储对象


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

问题引入:如果想在Spring 中能够更简单的进行对象的存储和读取,该怎么办呢?

问题解答:实现在Spring中更简单地进行对象的存储和读取操作的核心是使用注解来实现。

也就是我们接下来要学习Spring 中的相关注解,来进行存储和读取Bean对象。


1,五大类注解

1.1,类注解介绍及使用

1)类注解使用前置工作

类注解使用时的前置工作为配置扫描路径,这一步至关重要。该步需要在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="com.java.example"></content:component-scan>
</beans>

如果想成功地将对象存储到Spring 中,这时我们需要配置一下存储对象的扫描包路径。

只有处于被配置的扫描包路径下的所有类对象,添加类注解之后才能被正确的识别并保存到Spring中。

也就是说,即使类对象添加了类注解,但该类对象不处于被配置的扫描包路径下,也是不能被正确的识别并保存到Spring中。

其中标红的一行为注册扫描的包,如下图所示:

image-20230708192854468

2) @Controller(控制存储)

使用 @Controller 存储 bean对象 操作流程代码:

import org.springframework.stereotype.Controller;
@Controller
public class StudentController {public void sayHi(){System.out.println("do student controller sayHi()");}
}

读取Bean对象并使用的总操作流程代码:

import com.java.example.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {public static void main1(String[] args) {//1,获取Spring上下文ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");//2,得到Bean对象StudentController studentController =applicationContext.getBean("studentController",StudentController.class);//3,使用Bean对象studentController.sayHi();}
}

读取Bean对象并使用的总操作流程代码执行结果:

image-20230708201007881

3)@Service(服务存储)

使用 @Service 存储 bean对象 操作流程代码:

import org.springframework.stereotype.Service;
@Service
public class StudentService {public void sayHi(){System.out.println("do student service sayHi()");}
}

读取Bean对象并使用的总操作流程代码:

import com.java.example.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {public static void main2(String[] args) {//1,获取Spring上下文ApplicationContext applicationContext =new ClassPathXmlApplicationContext("spring-config.xml");//2,得到Bean对象StudentService studentService =applicationContext.getBean("studentService",StudentService.class);//3,使用Bean对象studentService.sayHi();}
}

读取Bean对象并使用的总操作流程代码执行结果:

image-20230708200934766

4)@Repository(仓库存储)

使用 @Repository 存储 bean对象 操作流程代码:

import org.springframework.stereotype.Repository;
@Repository
public class StudentRepository {public void sayHi(){System.out.println("do student repository sayHi()");}
}

读取Bean对象并使用的总操作流程代码:

import com.java.example.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {public static void main(String[] args) {//1,获取Spring上下文ApplicationContext applicationContext =new ClassPathXmlApplicationContext("spring-config.xml");//2,得到Bean对象StudentRepository studentRepository =applicationContext.getBean("studentRepository",StudentRepository.class);//3,使用Bean对象studentRepository.sayHi();}
}

读取Bean对象并使用的总操作流程代码执行结果:

image-20230708200837802

5)@Component(组件存储)

使用 @Component 存储 bean对象 操作流程代码:

import org.springframework.stereotype.Component;
@Component
public class StudentComponent {public void sayHi(){System.out.println("do student component sayHi()");}
}

读取Bean对象并使用的总操作流程代码:

import com.java.example.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {public static void main4(String[] args) {//1,获取Spring上下文ApplicationContext applicationContext =new ClassPathXmlApplicationContext("spring-config.xml");//2,得到Bean对象StudentComponent studentComponent =applicationContext.getBean("studentComponent",StudentComponent.class);//3,使用Bean对象studentComponent.sayHi();}
}

读取Bean对象并使用的总操作流程代码执行结果:

image-20230708201046813

6)@Configuration(配置存储)

使用 @Controller 存储 bean对象 操作流程代码:

import org.springframework.context.annotation.Configuration;
@Configuration
public class StudentConfiguration {public void sayHi(){System.out.println("do student configuration sayHi()");}
}

读取Bean对象并使用的总操作流程代码:

import com.java.example.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {public static void main5(String[] args) {//1,获取Spring上下文ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");//2,得到Bean对象StudentConfiguration studentConfiguration = applicationContext.getBean("studentConfiguration",StudentConfiguration.class);//3,使用Bean对象studentConfiguration.sayHi();}
}

读取Bean对象并使用的总操作流程代码执行结果:

image-20230708201154639

思考:配置信息为何不直接写在配置文件里,而要专门使用配置注解呢?

配置文件是用于提供全局性的配置,可以集中管理和调整各种应用程序的属性和行为。 配置文件具有灵活性,可以在部署环境或实际运行时进行修改,而无需重新编译代码。通过配置文件,可以实现对整个应用程序的配置和调整。

配置注解则更多地用于代码层面的配置和定制。 通过在代码中添加特定的注解,可以实现更精确和定制化的配置。配置注解可以用于声明、配置和管理各种类、组件、服务、Bean等,以实现各种不同的行为和功能,以及使得代码更具可维护性和可读性。

总结:配置文件和注解在Spring Boot项目中是相互补充的。配置文件用于整体性的配置外部化,而注解用于在代码层面进行具体的配置和定义。


1.2,类注解存在的原因

这五大类注解的功能:处于被配置的扫描包路径下的所有的类对象,经添加类注解之后就能被正确的识别并保存到Spring 容器中。

既然这五大类注解的功能是⼀样的,为什么需要这么多的类注解呢?

之所以需要这么多的类注解,是因为想起到程序员看到类注解之后,就能直接知道当前类的作用和功能的效果。

  1. @Controller:表示控制层,用于验证用户参数的正确性,相当于安保系统。
  2. @Service:表示服务层,用于编排和调度具体执行方法,相当于客服中心。
  3. @Repository:表示持久层,用于和数据库进行交互操作,相当于执行者。
  4. @Component:表示组件,用于标识工具类。
  5. @Configuration:表示配置层,用于标识配置类。

1.3,类注解之间的关系

1)@Controller 底层实现

image-20230708204157804

2)@Service 底层实现

image-20230708204331173

3)@Repository 底层实现

image-20230708204302395

4)@Configuration 底层实现

image-20230708204115246

5)五大类注解之间关系总结

从上述查看@Controller /@Service /@Repository /@Configuration 这些类注解的源代码不难发现:

这些类注解里面都有一个注解@Component,说明它们本身就是属于@Component 的子类。


1.4,类注解Bean命名规则

查看Bean命名规则的源代码方式流程:

1,在搜索框中输入BeanName,点击标记的方法

image-20230708210220490

2,点击标记的方法,就可以查看到对应的命名规则源代码

image-20230708210309036

3,对Bean命名规则的源代码进行分析image-20230708210942815

4,根据上述源代码可以总结出Bean对象命名规则为:

在默认情况下,Bean名称为首字母小写的类名,但如果类名首字母和第二个字母都为大写,Bean名称为原类名。

1.5,类注解使用注意问题

1)<bean> 标签 能否和<content:component-scan> 标签一起使用?

解答:<bean> 标签 能和<content:component-scan> 标签一起使用,<bean>可以是对<content:component-scan> 的补充。

  1. 使用<context:component-scan>标签扫描指定的包,并自动注册相应注解标识的类作为Bean
  2. 使用<bean>标签定义和配置一些需要详细控制的特定Bean

2)五大类注解可以不在<content:component-scan> 标签内设置的指定包路径下使用吗?

解答:五大类注解不可以在<content:component-scan> 标签内设置的指定包路径以外的路径下使用。

理由:五大类注解(@Component@Controller@Service@Repository等)需要在<context:component-scan>标签内设置的指定包路径下使用,以便Spring能够正确扫描并注册这些类。

3)在<content:component-scan> 标签内设置的包路径下,如果没有添加五大类注解,能将Bean对象存储到Spring中吗?

解答:即使类在<content:component-scan> 标签内设置的包路径下,若没有添加五大类注解,也是不能把当前类对象存储到Spring。

4)如果存在相同的类对象在<content:component-scan> 标签内设置的扫描包的不同子包路径下,会发生异常么?

解答:若没有对相同的类对象添加别名,会发生BeanDefinitionStoreException异常。

image-20230709094608793

解决上述情况的方法:通过导入指定的包进行区分或者添加别名的方式进行区分,推荐使用后者(导包容易出现导错的情况)。

image-20230709095157206

上述问题核心总结:为了确保Spring能够正确使用这些注解,需要将相关注解的使用限定在<context:component-scan>标签内设置的指定包路径下的类中。若在其他包路径下的类中使用这些注解,需要通过显式的<bean>标签进行定义和配置,进行手动注册。


2,方法注解@Bean

2.1,方法注解介绍及使用

类注解是添加到某个类上的,而方法注解是放到某个方法上的,方法注解@Bean的使用流程:

1)创建一个Student实体类

创建一个Student实体类操作代码:

public class Student {private int studentId;private String StudentName;public int getStudentId() {return studentId;}public void setStudentId(int studentId) {this.studentId = studentId;}public String getStudentName() {return StudentName;}public void setStudentName(String studentName) {StudentName = studentName;}
}

2)在其它类中使用@Bean存储对象

在其它类中使用@Bean存储对象操作代码:

import com.java.example.org.Student;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
@Controller
public class StudentBeans {@Beanpublic Student student(){Student student1 = new Student();student1.setStudentId(1);student1.setStudentName("小样");return student1;} 
}

3)在启动类中检测是否成功存储对象

在启动类中检测是否成功存储对象操作代码:

import com.java.example.*;
import com.java.example.org.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {public static void main(String[] args) {//1,获取Spring上下文ApplicationContext applicationContext =new ClassPathXmlApplicationContext("spring-config.xml");//2,得到Bean对象Student student =applicationContext.getBean("student",Student.class);//3,使用Bean对象System.out.println(student.getStudentName());}
}

注意:@Bean命名规则和五大类注解的命名规则不同,默认情况下,@Bean存储的对象名称就是方法名。

在启动类中检测是否成功存储对象操作代码执行结果:

image-20230709101815353


2.2,方法注解Bean重命名

方法注解Bean重命名可以使用两种字段进行,分别为 name 属性和 value 属性。

@Bean重命名的两种方式分别为:

image-20230709103003212

注意: namevalue 的本质是⼀个数组,可以存放多个值,也就是说⼀个 bean 可以有多个名字,并且 name={} 可以省略。


2.3,方法注解使用注意问题

1)@Bean 注解必须要与五大类注解配合使用,如果不搭配五大类注解使用会抛出如下异常:

image-20230709104719402

2)当@Bean对象进行重命名之后,默认地使用方法名获取对象的方式就不能使用了,若使用,则会抛出如下异常:

image-20230709105112999


核心总结

类注解的使用相关介绍?

1,类注解存在的原因:起到程序员看到类注解之后,就能直接知道当前类的作用和功能的效果。

2,@Controller /@Service /@Repository /@Configuration这四个类注解都属于@Component的子类。

3,Bean命名规则:在默认情况下,Bean名称为首字母小写的类名,但如果类名首字母和第二个字母都为大写,Bean名称为原类名。

4,类注解的功能:处于被配置的扫描包路径下的所有的对象方法,经添加注解之后就能被正确的识别并保存到Spring 容器中。

类注解的使用注意事项?

1,<bean> 标签 能和<content:component-scan> 标签一起使用,<bean>可以是对<content:component-scan> 的补充。

2,五大类注解不可以在<content:component-scan> 标签内设置的指定包路径以外的路径下使用。

3,即使类在<content:component-scan> 标签内设置的包路径下,若没有添加五大类注解,也是不能把当前类对象存储到Spring。

4,若没有对相同的类对象添加别名,会发生BeanDefinitionStoreException异常。

方法注解的使用相关介绍?

1,方法注解使用的核心流程:在其它类中使用@Bean注解存储对象。

2,@Bean命名规则和五大类注解的命名规则不同,默认情况下,@Bean存储的对象名称就是方法名。

3,方法注解Bean重命名可以使用两种字段进行,分别为name属性和value属性,本质是⼀个数组,可以存放多个值。

方法注解的使用注意事项?

1,@Bean 注解必须要与五大类注解配合使用,如果不搭配五大类注解使用会抛出异常。

2,当@Bean对象进行重命名之后,默认地使用方法名获取对象的方式就不能使用了,若使用,则会抛出异常。


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

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

相关文章

Tomcat工作原理

一、Tomcat架构 ### 说明&#xff1a; Server&#xff1a;表示整个 Tomcat Catalina servlet 容器&#xff0c;Server 中可以有多个 Service。&#xff08;可以通过telenet 8005后连接后输入“SHUTDOWN” 注意这里是大写&#xff0c;来关闭服务&#xff09;Service&#xff1…

JavaScript中的 map, forEach 无法跳出循环, return和 break不起作用,可以使用every 和 some方法

在我们平时使用习惯中&#xff0c;for循环里要跳出整个循环是使用break&#xff0c;但在数组中用forEach循环或者map如要退出整个循环使用break会报错&#xff0c;使用return也不能跳出循环&#xff0c;以下我们就来探索一下正确的跳出循环方案 一、先看一下案例 1、forEach函…

通信算法之176: 基于Matlab的OFDM通信系统关键基带算法设计6-流程

一. 接收算法流程 粗同步&#xff08;分组检测&#xff09; 载波同步&#xff08;精细频偏估计&#xff09; 精同步&#xff08;OFDM起始&#xff0c;符号同步&#xff09; 1.4 信道估计&#xff08;长序列&#xff09; 1.5 信道均衡&#xff08;所有数据OFDM符号&#xff…

存css实现动态时钟背景

代码实现 <!DOCTYPE html> <html lang"en"> <head><meta http-equiv"Content-Type" content"text/html; charsetUTF-8"><title>Title</title><meta name"referrer" content"no-referrer…

全球仅他一家!对甲方无情说“不”的顶尖效果图工作室,到底有多牛?

这个建筑&#xff0c;相信上海的小伙伴和喜欢看戏剧表演的朋友肯定不陌生。没错&#xff0c;它就是“上海大歌剧院”。它最大的亮点就是那座通天的旋转楼梯&#xff0c;如同一把展开的扇子&#xff0c;具有浓厚的东方美学特色。 歌剧院的设计构思固然巧妙&#xff0c;但同样离不…

数字化时代:虚拟数字人的智能进化与生活变革

我们需要实现对人工智能的有效监管。政府应该与科技公司合作&#xff0c;建立监管框架&#xff0c;确保人工智能的发展能够在保护人类利益的基础上进行。人工智能的快速发展带来了巨大的机遇&#xff0c;但同时也伴随着一些潜在的风险。如果没有适当的监管措施&#xff0c;人工…

【c++修行之路】智能指针

文章目录 前言为什么用智能指针智能指针简单实现unique_ptrshared_ptr 循环引用和weak_ptr的引入循环引用weak_ptr 定制删除器 前言 大家好久不见&#xff0c;今天来学习有关智能指针的内容~ 为什么用智能指针 假如我们有如下场景&#xff1a; double Div() {int x, y;cin …

STM32+PWM+输入捕获测频

外部时钟&#xff0c;主频64M 定时器1 通道1发出PWM波 频率1K 定时器2 通道1输入捕获&#xff0c;上升沿触发 串口 /* USER CODE BEGIN 0 */ uint32_t time_up_num0;//上升沿计数 float time_frequency;//频率 /* USER CODE END 0 */ 初始换打开定时器 /* USER CODE BEGIN 2 …

mapBox 绘制多边形无法设置 边框宽度 解决方法

目录 一、问题 二、解决方法 三、总结 tips:如嫌繁琐&#xff0c;直接看有颜色的文字即可&#xff01; 一、问题 1.使用mapBox在地图上绘制点、线、面。绘制多边形的时候发现 直接用 zh(一家提供地图引擎的公司),提供的绘制多边形的方法无法设置边框颜色和边框宽度。很是离…

Linux登录时,下游回显非常慢

目录 问题现象 原因分析 解决方法 源码等资料获取方法 问题现象 登录linux时&#xff0c;远程连接正常&#xff0c;[root...]回显非常慢&#xff0c;在执行脚本时&#xff0c;很容易导致命令下发错乱 原因分析 家目录下的.bash_history文件太大&#xff0c;导致每次登陆时读…

SQLSERVER的truncate和delete有区别吗?

一&#xff1a;背景 1. 讲故事 在面试中我相信有很多朋友会被问到 truncate 和 delete 有什么区别 &#xff0c;这是一个很有意思的话题&#xff0c;本篇我就试着来回答一下&#xff0c;如果下次大家遇到这类问题&#xff0c;我的答案应该可以帮你成功度过吧。 二&#xff1…

特斯拉降价阴影下,智己如何「登高」?

作者 | 刘然 来源 | 洞见新研社 都说背靠大树好乘凉&#xff0c;但背靠上汽集团的智己汽车&#xff0c;反而水深火热。 2021年&#xff0c;在智己正式向外界公布了“豪华纯电智能轿车”智己L7之后&#xff0c;其CEO刘涛曾放出豪言&#xff1a;“我们在未来的很多年后再回顾今…