【Spring】使用注解的方式获取Bean对象(对象装配)
目录
一、了解对象装配
1、属性注入
1.1、属性注入的优缺点分析
2、setter注入
2.1、setter注入的优缺点分析
3、构造方法注入
3.1、构造方法注入的优缺点
二、@Resource注解
三、综合练习
上一个博客中,我们了解了使用注解快速的将对象存储到Spring中,当然存储有简单方法,读取对象也可以使用注解的简单方法来实现,下面我们来了解一下,简单的获取对象的方法。
一、了解对象装配
获取Bean对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注入。
对象装配(对象注入)的实现方法有下面的三种方式
- 属性注入:会根据属性的类型,在容器种查找并获取对象,然后赋值给类的成员变量。
- 构造方法注入:通过构造方法将对象注入到对象中。
- Setter注入:通过setXXX 方法将对象注入到类中。
1、属性注入
属性注入只需要在需要注入对象的属性上加上@Autowired或者@Resource注解即可,这两个注解存在什么样的区别,我们在后面分析,这里我们以@Autowired注解来举例说明。
1️⃣容器中同类型的对象只有一个:直接将获取到的对象注入到当前属性上。
这里我们想让UserService类种获取到UserRepository类的对象,我们就需要在UserService类种设置一个类型是UserRepository的属性,给这个属性添加上@Autowired。表示的意思为从容器种获取这个属性类型的对象注入给这个属性。
首先给UserRepository类上添加类注解,将Bean存放在容器中。
package com.java.demo.dao;import org.springframework.stereotype.Repository;@Repository
public class UserRepository {public int add(){System.out.println("hello UserRepository");return 1;}
}
属性注入:将UserRepository在容器中的对象注入到UserService类中。
package com.java.demo.service;import com.java.demo.dao.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService {//1.属性注入(DI:依赖注入)@Autowiredprivate UserRepository userRepository;public int add(){System.out.println("do UserService add method");return userRepository.add();}}
上面两步完成之后,我们就可以在测试类中,通过获取上下文对象(容器对象)来获取到userService对象(也就是依赖查找的方式获取到userService对象),然后调用userService对象的add方法,就可以观察到执行了UserRepository类的add方法,此时说明属性注入获取对象成功,我们并没有手动的new 这个userRepository对象。这里设置这个类只是用来检测属性注入(依赖注入)获取对象是否成功。
package com.java.demo.test;import com.java.demo.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class App {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");UserService userService = context.getBean("userService",UserService.class);userService.add();}
}

容器中同类型的对象只有一个的情况,属性注入的时候根据类型在Spring中查找,找到对象之后,直接复制给这个类型的属性,但是如果容器中同类型的对象存在多个的情况,就需要给属性指定注入那个对象。如果不指定这程序就会报错。
2️⃣容器中同类型的对象存在多个:如果获取到多个同类型对象,会根据属性的名字来进行匹配。
我们通过下面的例子来了解容器中存在多个同类型对象,在获取对象是没有指定给属性指定注入那个对象,程序出现的错误。
创建一个普通实体类User,然后再Users类中使用@Bean的方式向Spring中添加多个对象,然后再UserService类中使用属性注入的方式获取User类的对象注入到属性中。
package com.java.demo.model;public class User {private int id;private String name;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;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';}
}package com.java.demo.model;import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;@Component
public class Users {@Bean("user1")public User user1(){User user = new User();user.setId(1);user.setName("张三");return user;}@Bean("user2")public User user2(){User user = new User();user.setId(2);user.setName("李四");return user;}
}package com.java.demo.service;import com.java.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService2 {@Autowiredprivate User user;public void sayHi(){System.out.println(user.toString());}
}package com.java.demo.test;import com.java.demo.service.UserService2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class App {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");UserService2 userService2 = context.getBean("userService2",UserService2.class);userService2.sayHi();}
}

上述的代码中由于获取到多个同类型的对象,不能直接根据类型将对象直接注入到当前类的属性中,需要根据属性的名称,将获取到的对象注入到属性中,但是属性的名称和对象名不相同的情况下,属性注入就会失败。想要解决这个问题,就需要设置对象名与属性名匹配,下面是三种解决这个问题的方法。
✨解决方案
1️⃣将属性的名字和Bean的名字对应上即可。

2️⃣ 也可以通过@Autowired注解和@Qualifier注解搭配使用,设置@Qualifier的参数为获取到的对象中的任意一个对象名即可,@Qualifier表示的意思就是根据参数筛选对象。

3️⃣属性上直接添加@Resource注解,这个注解的参数中存在name属性,我们可以将name的值设置获取到的对象中的某一个对象的名字。

1.1、属性注入的优缺点分析
1️⃣优点
属性注入的优点就是使用简单,直选哟添加一个@Autowired注解,就可以在不new对象的情况下,直接获取注入的对象了。
2️⃣缺点
🍂功能性问题:无法注入一个不可变的对象(被final修饰的对象),因为被final修饰的变量只能有两种初始化的方式,一种是直接复制,一种是通过构造方法赋值。就不能通过属性注入的方式获取到对象了。

🍂通用性问题:属性注入只能在IoC容器的前提下使用,脱离了IoC容器就不能使用了。
🍂设计原则问题:更容易违背单一设计原则,通俗来说就是属性注入的方式简单,滥用的概率就会很大。举个例子比如一个页面中不仅有用户的信息,也有用户请求的资源信息,那么后端写代码的时候在数据持久层的用户类中,本来就是针对用户注入相关的依赖,但是由于为了让程序的效率更高,有可能会在这个类中注入一些其他的信息相关的依赖。
2、setter注入
使用setter注入,在setXXX方法上添加一个@Autowired或者@Resource注解即可,当然setter注入也存在和属性注入一样的容器中相同类型的对象个数问题。这个问题的解决方法也和上述的属性注入时说的方法一样。
package com.java.demo.dao;import org.springframework.stereotype.Repository;@Repository
public class UserRepository {public int add(){System.out.println("hello UserRepository");return 1;}
}package com.java.demo.service;import com.java.demo.dao.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService3 {private UserRepository userRepository;@Autowiredpublic void setUserRepository(UserRepository userRepository) {this.userRepository = userRepository;}public void sayHi(){System.out.println("hello UserService3 .");userRepository.add();}
}package com.java.demo.test;import com.java.demo.service.UserService3;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class App {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");UserService3 userService3 = context.getBean("userService3",UserService3.class);userService3.sayHi();}
}

2.1、setter注入的优缺点分析
1️⃣优点
setter更符合单一设计原则,因为那个setter方法,只是针对一个属性进程赋值。
2️⃣缺点
🍂无法注入一个final修饰的变量,因为final修饰的变量初始化的时候只有两种方式要么直接初始化,要么通过构造方法初始化。
🍂注入的对象可被修改。因为setXXX是一个方法,所以他就可能别调用,这个时候就会导致注入的Bean对象被修改了。
3、构造方法注入
使用构造方法注入,标准的写法在构造方法上添加一个@Autowired注解或者在构造方法上不加注解也可以实现注入效果。当然构造注入也存在和属性注入一样的容器中相同类型的对象个数问题。这个问题的解决方法也和上述的属性注入时说的方法一样。这里构造方法不支持使用@Resource注解。
1️⃣标准的写法构造方法上添加@Autowired注解
package com.java.demo.dao;import org.springframework.stereotype.Repository;@Repository
public class UserRepository {public int add(){System.out.println("hello UserRepository");return 1;}
}package com.java.demo.service;import com.java.demo.dao.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService4 {private UserRepository userRepository;@Autowiredpublic UserService4(UserRepository userRepository) {this.userRepository = userRepository;}public void sayHi(){System.out.println("hello userService4 .");userRepository.add();}
}package com.java.demo.test;import com.java.demo.service.UserService2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class App {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");UserService4 userService4 = context.getBean("userService4",UserService4.class);userService4.sayHi();}
}

2️⃣不太标准的写法,构造方法上不加注解,这种写法是当前类中只有一个构造方法的时候可以使用的,如果有多个构造方法的时候,构造方法上的@Autowired注解是不可以省略的。


3.1、构造方法注入的优缺点
1️⃣优点
🍂可以注入不可变对象(被final修改的变量)

🍂注入的对象不会被修改,因为构造方法会随着JVM的启动而被加载,只会被加载一次。就像上面的例子userRepositoryd对象注入到UserService4这个类中,这个类实例化被存入容器的时候,构造方法只会执行一次。
🍂构造方法注入,可以保证注入对象完全初始化,因为构造方法是在对象创建之前执行的。
🍂构造方法注入的通用性最好的,因为一个类中使用了构造方法注入,当你要使用这个类的对象的时候你就不得不给构造方法中的参数(当前类的属性)注入一个对象。
2️⃣缺点
🍂构造方法注入的写法比属性注入复杂
🍂构造方法注入的写法无法解决循环依赖的问题
二、@Resource注解
@Resource注解和@Autowired注解的用法是相同的,都可以注入对象。

✨@Resource和@Autowired的区别
1️⃣出生不同:@Autowired来自于Spring,而@Resource来自于JDK的注解;
2️⃣支持参数不同:@Autowired的参数只有一个,而@Ressource支持更多的参数设置。


3️⃣使用上的区别:@Autowired可用于Setter注入、构造方法注入和属性注入,但是@Resource只能用于Setter注入和属性注入,不支持使用构造方法注入。
4️⃣idea兼容性支持不同:使用@Autowired在idea专业版下可能出现误报,@Resource不存在误报的问题。
三、综合练习
在 Spring 项⽬中,通过 main ⽅法获取到 Controller 类,调⽤ Controller ⾥⾯通过注⼊的⽅式调⽤ Service 类,Service 再通过注⼊的⽅式获取到 Repository 类,Repository 类⾥⾯有⼀个⽅法构建⼀ 个 User 对象,返回给 main ⽅法。Repository ⽆需连接数据库,使用伪代码即可。
这里需要注意的是,通过main方法获取Controller类,在main方法中不能使用依赖注入的方式获取对象,因为main方法为静态方法,静态方法的执行是在Spring框架之前的,所以我们需要使用依赖查找的方式获取容器对象,然后获取对象。
类的设置路径

package com.java.demo.model;public class User {private int id;private String name;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;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';}}
package com.java.demo.dao;import com.java.demo.model.User;
import org.springframework.stereotype.Repository;@Repository
public class UserRepository {//伪代码public User getUser(){User user = new User();user.setId(1);user.setName("王五");return user;}}
package com.java.demo.service;import com.java.demo.dao.UserRepository;
import com.java.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService {@Autowiredprivate UserRepository userRepository;public User getUser(){return userRepository.getUser();}
}
package com.java.demo.controller;import com.java.demo.model.User;
import com.java.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;@Controller
public class UserController {@Autowiredprivate UserService userService;public User getUser(){return userService.getUser();}
}
package com.java.demo;import com.java.demo.controller.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class App {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");UserController userController = context.getBean("userController",UserController.class);System.out.println(userController.getUser());}
}

相关文章:
【Spring】使用注解的方式获取Bean对象(对象装配)
目录 一、了解对象装配 1、属性注入 1.1、属性注入的优缺点分析 2、setter注入 2.1、setter注入的优缺点分析 3、构造方法注入 3.1、构造方法注入的优缺点 二、Resource注解 三、综合练习 上一个博客中,我们了解了使用注解快速的将对象存储到Spring中&#x…...
[webpack] 基本配置 (一)
文章目录 1.基本介绍2.功能介绍3.简单使用3.1 文件目录和内容3.2 下载依赖3.3 启动webpack 4.基本配置4.1 五大核心概念4.2 基本使用 1.基本介绍 Webpack 是一个静态资源打包工具。它会以一个或多个文件作为打包的入口, 将我们整个项目所有文件编译组合成一个或多个文件输出出去…...
模板学堂|SQL数据集动态参数使用场景及功能详解
DataEase开源数据可视化分析平台于2022年6月正式发布模板市场(https://dataease.io/templates/)。模板市场旨在为DataEase用户提供专业、美观、拿来即用的仪表板模板,方便用户根据自身的业务需求和使用场景选择对应的仪表板模板&a…...
Wlan——射频和天线基础知识
目录 射频的介绍 射频和Wifi 射频的相关基础概念 射频的传输 信号功率的单位 射频信号传输行为 天线的介绍 天线的分类 天线的基本原理 天线的参数 射频的介绍 射频和Wifi 什么是射频 从射频发射器产生一个变化的电流(交流电),通过…...
前端实习周记第三周周记
第二周总结 第二周主要是做了一些PC端细节内容。大的地方改的不多,但是小的细节蛮多。 值得一提的是,第二周做的微信小程序,改了很多逻辑。改逻辑需要与后端进行联调,收获很大,思路也愈发清楚。 记录做了什么是好习…...
Android 13 Launcher界面——移除Launcher的删除和卸载功能
目录 一.背景 二.将卸载功能进行屏蔽 三.将移除功能屏蔽 四.将Remove按钮与Uninstall按钮屏蔽...
深度学习:使用卷积神经网络CNN实现MNIST手写数字识别
引言 本项目基于pytorch构建了一个深度学习神经网络,网络包含卷积层、池化层、全连接层,通过此网络实现对MINST数据集手写数字的识别,通过本项目代码,从原理上理解手写数字识别的全过程,包括反向传播,梯度…...
docker search 镜像报错: connect: no route to host (桥接模式配置静态IP)
如下 原因 可能有多种: ① 没有开放防火墙端口 ② ip地址配置有误 解决 我是因为虚拟机采用了桥接模式,配置静态ip地址有问题。 先确认虚拟机采用的是 桥接模式,然后启动虚拟机。 1、打开命令行,输入下面指令,打开…...
【VUE】[Violation] Added non-passive event listener to a scroll-blocking...
环境 chrome: 115.0.5790.170vue: ^3.3.4element-plus: ^2.3.4vite: ^4.4.7 问题 [Violation] Added non-passive event listener to a scroll-blocking <某些> 事件. Consider marking event handler as passive to make the page more responsive. See <URL> …...
runit-docker中管理多个服务
runit-docker中管理多个服务 介绍Runit, systemctl和supervisor是三种不同的服务管理工具区别runit优点程序构成快速开始runit实现服务退出执行指定操作runit监管服务打印日志到syslogrunit监管服务后台运行runit监管服务一些错误总结 介绍 runit 是一个轻量级的、稳定的、跨平…...
Intune 应用程序管理
由于云服务提供了增强的安全性、稳定性和灵活性,越来越多的组织正在采用基于云的解决方案来满足他们的需求。这正是提出Microsoft Endpoint Manager等解决方案的原因,它结合了SCCM和Microsoft Intune,以满足本地和基于云的端点管理。 与 Int…...
Oracle DB 安全性 : TDE HSM TCPS Wallet Imperva
• 配置口令文件以使用区分大小写的口令 • 对表空间进行加密 • 配置对网络服务的细粒度访问 TCPS 安全口令支持 Oracle Database 11g中的口令: • 区分大小写 • 包含更多的字符 • 使用更安全的散列算法 • 在散列算法中使用salt 用户名仍是Oracle 标识…...
leetcode27—移除元素
思路: 参考26题目双指针的思想,只不过这道题不是快慢指针。 看到示例里面数组是无序的,也就是说后面的元素也是可能跟给定 val值相等的,那么怎么处理呢。就想到了从前往后遍历,如果left对应的元素 val时,…...
flask---》更多查询方式/连表查询/原生sql(django-orm如何执行原生sql)/flask-sqlalchemy
更多查询方式 #1 查询: filer:写条件 filter_by:等于的值 # 查询所有 是list对象 res session.query(User).all() # 是个普通列表 print(type(res)) print(len(res))# 2 只查询某几个字段 # select name as xx,email from user; res session.…...
Chromium内核浏览器编译记(三)116版本内核UI定制
转载请注明出处:https://blog.csdn.net/kong_gu_you_lan/article/details/132180843?spm1001.2014.3001.5501 本文出自 容华谢后的博客 往期回顾: Chromium内核浏览器编译记(一)踩坑实录 Chromium内核浏览器编译记(…...
LoRaWan网关设计架构介绍
LoRa 数据包转发器是在基于 LoRa 的网关(带或不带 GPS)主机上运行的程序。它将集中器(上行链路)接收到的 RF 数据包通过安全的 IP 链路转发到LoRaWAN 网络服务器( LNS )。它还通过相同的安全 IP 将 LNS(下行链路)发送的 RF 数据包传输到一台或多台设备。此外,它还可以传…...
vue 全局状态管理(简单的store模式、使用Pinia)
目录 为什么使用状态管理简单的store模式服务器渲染(SSR) pinia简介示例1. 定义一个index.ts文件2. 在main.ts中引入3. 定义4. 使用 为什么使用状态管理 多个组件可能会依赖同一个状态时,我们有必要抽取出组件内的共同状态集中统一管理&…...
ORACLE和MYSQL区别
1,Oracle没有offet,limit,在mysql中我们用它们来控制显示的行数,最多的是分页了。oracle要分页的话,要换成rownum。 2,oracle建表时,没有auto_increment,所有要想让表的一个字段自增,…...
tensorflow 1.14 的 demo 02 —— tensorboard 远程访问
tensorflow 1.14.0, 提供远程访问 tensorboard 服务的方法 第一步生成 events 文件: 在上一篇demo的基础上加了一句,如下, tf.summary.FileWriter("./tmp/summary", graphsess1.graph) hello_tensorboard_remote.py …...
Spring中Bean的循环依赖问题
1.什么是Bean的循环依赖? 简单来说就是在A类中,初始化A时需要用到B对象,而在B类中,初始化B时需要用到A对象,这种状况下在Spring中,如果A和B同时初始化,A,B同时都需要对方的资源&…...
电容是什么?一个“快充快放”的微型充电宝轮
一、前言:什么是 OFA VQA 模型? OFA(One For All)是字节跳动提出的多模态预训练模型,支持视觉问答、图像描述、图像编辑等多种任务,其中视觉问答(VQA)是最常用的功能之一——输入一张…...
如果给你10亿条id数据让你去重,你会怎么做?
如果给你10亿条id数据让你去重,你会怎么做? 最近在刷一些其他题库的题,发现遇到一些类似的问题甚至是相同的题还是会卡住,我觉得我需要转变一下思路,总结一下一类题的算法,而不是每天写一道题的解题思路&am…...
营销自动化数据驱动 - 多源数据 OLAP 架构演进诖
1. 流图:数据的河流 如果把传统的堆叠面积图想象成一块块整齐堆叠的积木,那么流图就像一条蜿蜒流淌的河流,河道的宽窄变化自然流畅,波峰波谷过渡平滑。 它特别适合展示多个类别数据随时间的变化趋势,尤其是当你想强调整…...
MySql(基础操作符--查找学校是北大的学生信息)
9.现在运营想要筛选出所有北京大学的学生进行用户调研,请你从用户信息表中取出满足条件的数据,结果返回设备id和学校。示例:user_profileiddevice_idgenderageuniversityprovince12138male21北京大学Beijing23214male复旦大学Shanghai36543fe…...
深入 Hadoop 高可用:Leader、Follower 、Observer」角色详解
在 Hadoop 高可用(HA)架构中,Leader 选举是保障集群稳定的核心机制 —— 我们常听说 Leader(主节点)和 Follower(从节点),但很少有人深入聊第三种关键角色:Observer&…...
别把 Contract C1 当成一个小开关,它决定了你的 ABAP 接口能不能活过下一轮升级
项目里最容易把人拖进泥潭的,往往不是一段代码写不出来,而是一个原本跑得好好的扩展,在系统升级之后突然开始失稳。昨天还能用的自定义逻辑,今天因为标准对象的参数变了、字段被改了、关联目标被挪了,整个流程从查询层一直碎到服务层。到了 ABAP Cloud 和 Clean Core 这条…...
WebPShop终极指南:让你的Photoshop完美支持WebP格式
WebPShop终极指南:让你的Photoshop完美支持WebP格式 【免费下载链接】WebPShop Photoshop plug-in for opening and saving WebP images 项目地址: https://gitcode.com/gh_mirrors/we/WebPShop 还在为Photoshop无法原生支持WebP格式而烦恼吗?&am…...
焊接机器人数据采集物联网解决方案
方案背景 在汽车制造领域,焊接机器人作为车身焊接、零部件焊接、汽车总装的自动化生产设备,发挥着至关重要的作用。它们能够精确、高效地完成各种焊接任务,确保焊接质量稳定可靠,焊接强度、焊缝外观等关键指标符合严格的标准要求。…...
Qwen3-4B-Thinking模型重装系统后快速恢复AI开发环境指南
Qwen3-4B-Thinking模型重装系统后快速恢复AI开发环境指南 重装系统,对开发者来说,有时候就像一场“数字大扫除”,清爽是清爽了,但看着空空如也的桌面和终端,要重新搭建起那个熟悉的AI开发环境,头就开始疼了…...
在Windows 10/11上部署ArcGIS 10.2开发环境:ArcEngine SDK for .NET配置详解
在Windows 10/11上构建ArcGIS 10.2开发环境:从零开始打造GIS应用 当你第一次尝试在Visual Studio中调用ArcEngine的类库时,是否遇到过令人抓狂的"未找到引用"错误?或是明明按照教程一步步操作,却在运行时遭遇神秘的许可…...
