Spring添加注解读取和存储对象

5大注解

@Controller 控制器

@Service 服务

@Repository 仓库

@Componet 组件

@Configuration 配置

五大类注解的使用

//他们都是放在同一个目录下,不同的类中 只不过这里粘贴到一起//控制器
@Controller
public class UserController {public void SayHello(){System.out.println("Hello");}
}//服务
@Service
public class UserService {public void doService(){System.out.println("Service");}
}//仓库
@Repository
public class UserRepository {public void DoRepository(){System.out.println("Repository");}
}//组件
@Component
public class UserComponent {public void doComponent(){System.out.println("Component");}
}//配置
@Configuration
public class UserConfiguration {public void doConfiguration(){System.out.println("userConfiguration");}
}

//启动类
public class App {public static void main(String[] args) {//获取spring上下文ApplicationContext context=new ClassPathXmlApplicationContext("Spring-config.xml");//获取Controller bean对象//使用注解默认是小驼峰UserController userController=context.getBean("userController",UserController.class);userController.SayHello();//获取Service bean对象UserService userService=context.getBean("userService",UserService.class);userService.doService();//获取Repository bean对象UserRepository userRepository=context.getBean("userRepository",UserRepository.class);userRepository.DoRepository();//获取Component bean对象UserComponent userComponent=context.getBean("userComponent",UserComponent.class);userComponent.doComponent();//获取Configuration bean对象UserConfiguration userConfiguration=context.getBean("userConfiguration",UserConfiguration.class);userConfiguration.doConfiguration();}
}

总结:Controller(控制器)、Service(服务)、Repository(仓库)、Configuration(配置)都是基于Component 他们的作用都是将Bean存储到Spring中

获取bean时,都需要将类的首字母小写

命名规则

默认情况下,使用5大类注解获取bean名称,要将首字母小写

特例:当首字母和第二个字母都是大写的时候,那么获取bean名称时,使用原名称即可

创建类时,如果要把类放入spring内管理,那么你的类名一定要遵守命名规则

1.首字母大写,后续小写

2.首字母大写,第二个字母也是大写

为什么要这样命名呢?

查看源码

ctrl+鼠标左键进入

    public static String decapitalize(String name) {if (name == null || name.length() == 0) {return name;}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 并且 字符串第二个字符串和首字符都是大写的时候,也返回源字符串

只有当这两个条件不成立的时候,就把字符串第一个数改为小写

测试

        //这个获取bean对象时,需要首字母小写String userComponent = "UserComponent";//这个首字母和第二个字母都是大写,获取bean对象时,使用源类名即可String sComponent = "SComponent";
        System.out.println(Introspector.decapitalize("UserComponent"));System.out.println(Introspector.decapitalize("SComponent"));

存储bean对象

创建一个普通类,创建一个输入数据类

这样就把User放入spring内管理,并且初始化,初始化的方法必须加Bean

为什么bean必须和五大类的其中一个配合用才可以呢?

性能原因,spring不可能把全部的类全加入到spring内管理,那太消耗性能了,所以必须先表名五大类其中一个,加了类注解,再类注解下加了bean 方法注解,才会把该类加入到spring内管理

Bean

Spring内管理的对象统称为Bean

方法的命名规则就是方法名

当多个类使用同一个方法名,并且对象都存入spring中时,可以给方法名起别名

起别名的方法有三种

 @Bean(name="UserBean")//取多个名称@Bean(name={"studentbean","stubean"})@Bean("StudentBean")//重命名方法名  获取bean对象时就之间写重命名的即可//当重命名后,原来的方法名就不能使用了

DI注入

DI注入时机取决于bean的作用域,比如默认情况bean的作用域为单例模式,当需要对象时,才会注入。

DI注入都是从Spring内获取,Spring内没有的就没法注入

对象注入有三种

  1. 属性注入 (Field Injection)
  2. Setter注入 (Setter Injection)
  3. 构造方法注入 (Constructor Injection)

@Autowired

属性注入(Field Injection)

@Autowired //添加注解private UserService userService;//获取userService对象public void SayHello(){userService.doService();//使用userService方法System.out.println("Hello");}

启动类内不能注入,因为static执行速度是非常快的,在属性还没注入时,main函数已经执行了。所以main执行时,获取不到从spring获取的对象。

优点

现简单,使用方便,注入之后即可使用

缺点

1.不能注入被final修饰的对象

原因:final关键字在Java中表示一个字段是不可变的,它必须在声明时或在构造函数中被初始化,并且之后不能被修改。

当你使用依赖注入时,注入的值通常是在运行时由容器设置的,这意味着属性的值是在对象创建之后才确定的。但是,由于final字段必须在构造函数中被初始化,这就产生了一个矛盾:你不能在构造函数中给final字段赋值,因为那时注入的值还没有确定。

除非直接赋值或在构造方法内赋值

2.通用性问题 只适用于IoC框架(容器)
3.更容易违背单一设计原则

单一职责原则指出,一个类应该只有一个引起变化的原因,即一个类应该只负责一项任务。当使用 @Autowired 进行属性注入时,可能会导致以下问题:

  1. 职责不清晰:如果一个类中有多个 @Autowired 注解的属性,那么这个类可能承担了多个职责。这违反了单一职责原则,因为如果这些依赖中的任何一个发生变化,这个类可能需要修改。
  2. 依赖过多:一个类如果依赖了太多的其他类,那么它就变得复杂,难以理解和维护。这可能导致类之间的耦合度增加,违反了高内聚低耦合的设计原则。

Setter注入(Setter Injection)

//setter注入 (setter Injection)private UserService userService;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}

优点

符合单一设计原则 (一个setter只针对一个对象)

缺点

1.不能注入一个不可变(final)的对象 (和属性注入一样)

原因:final关键字在Java中表示一个字段是不可变的,它必须在声明时或在构造函数中被初始化,并且之后不能被修改。

当你使用依赖注入时,注入的值通常是在运行时由容器设置的,这意味着属性的值是在对象创建之后才确定的。但是,由于final字段必须在构造函数中被初始化,这就产生了一个矛盾:你不能在构造函数中给final字段赋值,因为那时注入的值还没有确定。

2.注入对象可能会被改变 (致命问题) set方法可能会被调用多次 被调用就有被修改的风险

构造方法注入(Constructor Injection)

官方推荐做法

//构造方法注入(Constructor Injection)private UserService userService;@Autowiredpublic UserController(UserService userService){this.userService=userService;}

当当前类只有一个构造方法,那@Autowired可以省略

一个构造方法内可以注入多个对象

//构造方法注入(Constructor Injection)private UserService userService;private UserRepository userRepository;@Autowiredpublic UserController(UserService userService,UserRepository userRepository){this.userService=userService;this.userRepository=userRepository;}

一个类可以有多个构造方法,但是只允许一个构造方法有@Autowired注解(DI注入构造只允许有一个)

并且,构造方法的参数只允许有在spring内存储的,其他参数没有办法传入构造方法,所以会报错。

优点

1.可以注入final修饰的对象

final修饰的变量必须赋初始值

赋值只有两种方法

1.创建时直接赋值

2.在构造方法中赋值

构造注入刚好满足第二种需求,所以构造注入允许注入final的对象

2.注入对象不会被修改

构造方法只能执行一次,所以赋值完就不会再赋值

3.依赖对象在使用前会被完全初始化

使用前一定会被构造方法初始化

4.通用性更好,当不使用IoC容器时,构造方法依旧奏效

@Resource

也是实现对象注入

注入方式也是同样的属性注入、setter注入

但Resource不支持构造注入

方式也是一样的,只是注解不同

属性注入

//    属性注入
//读取spring中名为userService的对象,赋值给当前注入的对象
//有了这个name  所以即使下面的名称不一致,依靠上面的name依旧可以找到指定对象@Resource(name="userService")private UserService userService;

Resource可以指定注入对象的名称

Setter注入

    //setter注入private UserController userController;@Resourcepublic void setUserController(UserController userController) {this.userController = userController;}

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

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

相关文章

在51单片机里面学习C语言

在开始前我有一些资料,是我根据网友给的问题精心整理了一份「C语言的资料从专业入门到高级教程」, 点个关注在评论区回复“888”之后私信回复“888”,全部无偿共享给大家!!! 说出来你们可能都…

Oracle count的优化-避免全表扫描

Oracle count的优化-避免全表扫描 select count(*) from t1; 这句话比较简单,但很有玄机!对这句话运行的理解,反映了你对数据库的理解深度! 建立实验的大表他t1 SQL> conn scott/tiger 已连接。 SQL> drop table t1 purge…

C++ | Leetcode C++题解之第71题简化路径

题目&#xff1a; 题解&#xff1a; class Solution { public:string simplifyPath(string path) {auto split [](const string& s, char delim) -> vector<string> {vector<string> ans;string cur;for (char ch: s) {if (ch delim) {ans.push_back(mov…

QT+MYSQL数据库处理

1、打印Qt支持的数据库驱动&#xff0c;看是否有MYSQL数据库驱动 qDebug() << QSqlDatabase::drivers(); 有打印结果可知&#xff0c;没有MYSQL数据库的驱动 2、下载MYSQL数据库驱动&#xff0c;查看下面的文章配置&#xff0c;亲测&#xff0c;可以成功 Qt6 配置MySQL…

百面算法工程师 | 模型评价指标及优化策略

本文给大家带来的百面算法工程师是深度学习模型评价指标的面试总结&#xff0c;文章内总结了常见的提问问题&#xff0c;旨在为广大学子模拟出更贴合实际的面试问答场景。在这篇文章中&#xff0c;我们还将介绍一些常见的评价方案&#xff0c;并提供参考的回答及其理论基础&…

7 系列 FPGA 产品介绍及选型

目录 Spartan-7 FPGAsArtix-7 FPGAsKintex-7 FPGAsVirtex-7 FPGAsFPGA芯片命名规则DSP资源BRAM资源Transceivers 资源Transceivers 总带宽I/O 个数及带宽参考文档 Spartan-7 FPGAs Artix-7 FPGAs Kintex-7 FPGAs Virtex-7 FPGAs FPGA芯片命名规则 DSP资源 BRAM资源 Transceiver…

深入浅出JavaScript继承机制:解密原型、原型链与面向对象实战攻略

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 &#x1f525; 引言&#x1f9f1; 原型基础⛓️ 原型链的形成&#x1f504; 修改原型的影响&#x1f3c1; 原型链的尽头为什么null标志着结束&#xff1f;实际意义 &#x1f310; &#x1f504; 继承的实现方式1. 原型链继承…

数据库期末复习资料

考纲 选择 10分 简答题 25分 ER图建表 15分 建表以后的范式的分解、规范化 15分 Sql语句 35分 &#xff1a;关系代数&#xff0c;select&#xff0c;触发器 --------------------------------------数据库设计----------------------------------- 第一章&#xff1a; 1.数据…

我在洛杉矶采访到了亚马逊云全球首席信息官CISO(L11)!

在本次洛杉矶举办的亚马逊云Re:Inforce全球安全大会中&#xff0c;小李哥作为亚马逊大中华区开发者社区和自媒体代表&#xff0c;跟着亚马逊云安全产品团队采访了亚马逊云首席信息安全官(CISO)CJ Moses、亚马逊副总裁Eric Brandwine和亚马逊云首席高级安全工程师Becky Weiss。 …

安装docker镜像nginx1.26.0版本,与删除docker容器【灵异事件】

为了http3 的这个模块&#xff0c;所以需要升级nginx的版本&#xff0c;需要nginx1.26.0才有 –with-http_v3_module 这个模块 为什么记录一下&#xff1f;因为觉得奇怪 1&#xff1a;删除nginx镜像&#xff0c;显示镜像还被某个容器在使用 luichunluichun:~$ docker rmi ng…

文心一言 VS 讯飞星火 VS chatgpt (255)-- 算法导论18.3 1题

一、请说明依次从图18-8(f)中删除C、P和V后的结果。如果要写代码&#xff0c;请用go语言。 文心一言&#xff1a; 首先&#xff0c;让我们明确一点&#xff1a;由于您没有提供具体的图18-8(f)的内容&#xff0c;我只能假设它是一个数据结构&#xff08;可能是图、树或列表等&…

AI模型:windows本地运行下载安装ollama运行Google CodeGemma、gemma等可离线运行数据模型【自留记录】

AI模型&#xff1a;windows本地运行下载安装ollama运行Google CodeGemma可离线运行数据模型【自留记录】 CodeGemma 没法直接运行&#xff0c;需要中间软件。下载安装ollama后&#xff0c;使用ollama运行CodeGemma。 类似 前端本地需要安装 node.js 才可能跑vue、react项目 1…

应用层协议之 DNS 协议

DNS 就是一个域名解析系统。域名就是网址&#xff0c;类似于 www.baidu.com。网络上的服务器想要访问它&#xff0c;就得需要它对应的 IP 地址&#xff0c;同时&#xff0c;每个域名对对应着一个 / N个 IP 地址&#xff08;即对应多台服务器&#xff09;。 因此&#xff0c;为了…

会话劫持攻击就在我们身边,我们要如何防范

会话劫持攻击&#xff08;Session Hijacking&#xff09;是一种网络攻击方式&#xff0c;攻击者通过某种手段获取到用户的会话标识&#xff08;Session ID&#xff09;&#xff0c;然后使用这个会话标识冒充合法用户进行恶意操作。这种攻击方式允许攻击者以合法用户的身份访问受…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-15.4讲--ARM异常中断返回

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

智慧公厕解决什么问题?实现了什么样的价值?

公共厕所一直是城市管理的难题&#xff0c;常常面临着卫生条件不佳、管理不善以及使用体验差等问题。为了解决这些困扰城市的难题&#xff0c;智慧公厕应运而生。智慧公厕不仅应用了信息化和数字化技术&#xff0c;还通过全方位的智能化应用&#xff0c;彻底改变了传统公厕的面…

iframe的替代方案有吗?做页面嵌套界面套娃

UIOTOS可以了解下&#xff0c;uiotos.net&#xff0c;通过连线来代替脚本逻辑开发&#xff0c;复杂的交互界面&#xff0c;通过页面嵌套轻松解决&#xff0c;是个很新颖的思路&#xff0c;前端零代码&#xff01; 蓝图连线尤其是独创的页面嵌套和属性继承技术&#xff0c;好家…

韩顺平0基础学Java——第8天

p155-168 数组&#xff08;第六章&#xff09; 数组可以存放多个同一类型的数据&#xff0c;数组也是一种数据类型&#xff08;引用类型&#xff09;。 即&#xff0c;数组就是一组数据~ 例&#xff1a;double [] hens {1,2,3,4,5,6}; 新建了一组鸡&#xff0c;里面有6个。…

车载电子电器架构 —— 应用软件开发(上)

车载电子电器架构 —— 应用软件开发(上) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明…

学习记录:AUTOSAR R20-11的阅读记录(五)【CP(5.11-5.19)】完

接上回&#xff1a;学习记录&#xff1a;AUTOSAR R20-11的阅读记录&#xff08;四&#xff09;【CP&#xff08;5.6-5.10&#xff09;】 五、CP 11、General&#xff08;4个&#xff09; 5.11 File Name 说明 1 AUTOSAR_EXP_ LayeredSoftwareArchitecture.pdf 描述了AUTO…