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

news/2024/5/21 5:34:41

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.mrgr.cn/p/26885526

相关文章

智启蒸汽时代:数字孪生锅炉的革新之旅

数字孪生,就是通过数字技术为物理世界中的物体创建一个数字化的“双胞胎”。对于蒸汽工厂锅炉来说,数字孪生系统能够实时模拟锅炉的运行状态,预测可能出现的问题,并通过数据分析和智能决策为工人提供精准的操作建议。在飞速发展的工业4.0时代,数字孪生技术已经深入到我们生…

python数据分析——数据预处理

数据预处理 前言一、查看数据数据表的基本信息查看info()示例 查看数据表的大小shape()示例 数据格式的查看type()dtype()dtypes()示例一示例二 查看具体的数据分布describe()示例 二…

35岁自学编程有必要吗

在当今这个快速发展的数字化时代,学习编程已经不再局限于特定年龄层。对于35岁的人来说,自学编程不仅有必要,而且可能开启职业生涯的全新篇章。首先,编程技能是通往高科技行业的一把钥匙,能够为个人职业发展拓宽道路&a…

服务器(Linux系统)清除缓存

echo 1> /proc/sys/vm/drop_caches -- 清空系统缓存; cat /proc/29127/status -- 查看指定进程的状态信息;

Oracle Linux环境执行脚本

executeOracleSql.sh #!bin/bash# system:oracle的用户名;xxx:oracle的密码 # 后面追加要执行的sql脚本路径即可 sqlplus -s system/oracle@127.0.0.1:1521/xxx <<EOF @/home/mjtabu/basedb_init.sql exit; EOFecho "Please double check!!!";I have a dream…

js实现复制功能

/*** 复制* param {*} val 要复制的内容* returns*/ export const copyToClipboard async val > {try {// 使用现代 API 尝试复制if (navigator.clipboard && navigator.permissions) {await navigator.clipboard.writeText(val)return // 如果成功&#xff0c;直接…

kafka的名词解释

1.Replica(副本):在 Kafka 中,每个分区都有多个副本,用于提供数据的冗余备份和高可用性。副本可以分为两种类型:领导者副本(leader replica)和追随者副本(follower replica)。 领导者副本:每个分区都有一个领导者副本,它负责处理与客户端的所有读写请求,是分区的主…

vue3打开页面后文本框自动获得焦点

字符串写法 <script setup> import { ref, onMounted } from vue import ./index.cssconst input ref(null)onMounted(() > {input.value.focus() }) </script><template><div class"m-home-wrap"><input ref"input" />…

FPGA+炬力ARM实现VR视频播放器方案,3D眼镜显示

3D眼镜显示&#xff1a; FPGA炬力ARM方案&#xff0c;单个视频源信号&#xff0c;同时驱动两个LCD屏显示&#xff0c;实现3D 沉浸式播放 客户应用&#xff1a;VR视频播放器 主要功能&#xff1a; 1.支持多种格式视频文件播放 2.支持2D/3D 效果实时切换播放 3.支持TF卡/U盘文…

亚信安慧AntDB:解锁数智化的新时代

亚信安慧AntDB的融合实时的特性使得它在数据库领域独树一帜。传统的数据库系统往往只能追求数据的准确性和一致性&#xff0c;但在实际的业务场景中&#xff0c;这些特性并不能满足企业的需求。AntDB的出现打破了传统束缚&#xff0c;为企业带来了全新的数据处理方式&#xff0…

计算机基础-网络

一、网络设备 a.网卡(无线、有线) 物理层:提供物理地址,也叫MAC地址 b.网线(双绞线)、光缆 c.交换机、集线器 arp链路层:提供局域网内计算机与路由器之间建立端口映射,mac与IP的链路绑定 d.路由器 网络层:为局域网内计算机分配IP地址、防火墙、上网限制、网速控制登录 …

压力测试

压力测试压力测试 本文来自博客园,作者:{咏南中间件},转载请注明原文链接:https://www.cnblogs.com/hnxxcxg/p/18184743

预约咨询小程序源码搭建/部署/上线/运营/售后/更新

包含在线咨询、视频咨询、电话咨询、面询多种咨询方式&#xff0c;适用于心理、法律、宠物等预约咨询问诊场景 分类预览&#xff1a;小程序提供清晰的分类选项&#xff0c;使用户能够迅速找到所需的咨询服务类型&#xff0c;如法律咨询、心理咨询、医疗咨询等。预约时间选择&a…

实验四

一、实验题目 :代码审查 二、实验目的 1、熟悉编码风格,利用开发环境所提供的平台工具对代码进行自动格式审查; 2、根据代码规范制定代码走查表,并按所制定的审查规范互审代码。 三、实验内容 1、IDEA环境和PyCharm环境二选一; IDEA环境 (1)预先准备在IDEA环境下实现对输…

【redis学习】Redis-IO多路复用

为什么要有IO多路复用 大家印象中的redis都是单线程的,没有加锁的操作,因此才会是redis这么快的原因其中之一。先暂且不说redis究竟是不是单线程,即便是单线程的,作为服务提供方,面对成百上千的客户端连接请求,读写操作,单线程是怎么做到高效的处理这些请求?单线程处理…

h5使用js拉起微信支付

近期,业务需求对接了微信支付,做个总结。web网页想要拉起微信支付,有两种方法: H5下单支付 , JSAPI支付 。首先纯前端做不了微信支付,必须配合后端才能通过微信的下单请求。接下来说说这两种方法的区别。 H5微信下单支付 这种支付方式是用户在浏览器端打开网页,通过下单等…

Android studio 新版本 NewUI toolbar显示快捷按钮

新版本的Android studio 启用新的界面&#xff0c;以前许多快捷按键位置有变化 文章目录 设置始终显示主菜单设置ToolBar快捷按钮显示设置右下角显示分支 设置始终显示主菜单 原本要点击左上角几个横向才显示的菜单 设置始终显示&#xff0c;View -> Appearance -> Main…

C#开发的网络速度计 - 开源研究系列文章 - 个人小作品

上次发布了一个获取网络速度的例子( https://www.cnblogs.com/lzhdim/p/18167854 )&#xff0c;就是为了这次这个例子。用于在托盘里显示网络速度的图标&#xff0c;并且能够显示网络速度。下面就介绍一下这个小应用的源码。 1、 项目目录&#xff1b; 2、 源码介绍&#xff1b…

[muduo网络库]——muduo库的Reactor模型(剖析muduo网络库核心部分、设计思想)

一、前言 在学习 C 服务端的过程中&#xff0c;必不可少的一项就是熟悉一个网络库&#xff0c;包括网络库的应用和其底层实现。我们熟知的网络库有 libevent、libev、muduo、Netty 等&#xff0c;其中 muduo 是由陈硕大佬个人开发的 TCP 网络库&#xff0c;最近跟着课程正在深…

任天堂Switch全部记录

NS SWTICH大气层制作新的SD卡,解决部分大气层及固件问题。 原先的SD卡(128G)快全部放满游戏了,需要新的内存卡用于存放新的游戏。 有几张闲置的内存卡,可是容量最大只有64G, 无法通过直接全部复制+粘贴的办法,来启用新的小内存卡,涉及制作新的NS Switch SD卡有什么用 s…