【Spring框架全系列】方法注解@Bean的使用

news2024/11/19 1:45:30

📬📬哈喽,大家好,我是小浪。上篇博客我们介绍了五大类注解的使用方法,以及如何解决Spring使用五大类注解生成bean-Name的问题;那么,谈到如何更简单的读取和存储对象,这里我们还需要介绍另外一个"方法注解@Bean"的使用,快来一起学习叭!🛳🛳

📲目录

一、如何使用方法注解

二、同一类型的对象注入多次的问题

1、精准的描述bean的名称(将注入的名称写对)

2、使用@Resource设置name的方式来重命名注入的对象;

3、使用@AutoWired+@Qualifier来筛选bean对象;

对象注入的三种方法

1、属性注入

2、构造方法注入

3、Setter方法注入

属性注入和构造方法注入以及 Setter 注入的区别是什么?

@Resource VS @Autowired?


一、如何使用方法注解

🌃1、前面介绍过,类注解是写到类上面的,那么方法注解是写到对应的方法上的;

    @Bean(name = "user1") 
    public User getUser1() {
        User user = new User();
        user.setId(1);
        user.setName("张三");
        return user;
    }

2、方法注解的话是不能够单独使用的,如果我们只给一个方法注解@Bean的话,看是否能运行;

 ApplicationContext context= new ClassPathXmlApplicationContext("spring-config.xml");
 User user = context.getBean(User.class);//只使用类属性
 System.out.println(user);

运行结果:

6b10299ea7a04d3a9d1dc8ced9646992.png

如何解决?我们只需要在方法注解的类中添加一个类注解即可;

887ef81e144847ccb2e749d6c50baa23.png

再次运行:

91c3018dc0df43f8972d1b31be2ca865.png

注意Bean 的命名规则,当没有设置 name 属性时,那么 bean 默认的名称就是方法名,当设置了 name 属性之后,只能通过重命名的 name 属性对应的值来获取,也就是说重命名之后,再使用方法名就获取不到 bean 对象;

比如已经给bean重命名了,我们在启动类App中通过方法名来获取Bean对象;

7f7bcc809f0945e3981d10756c22c023.png

看运行结果:

2f5341d04adf49ed87b55fa725772cda.png

二、同一类型的对象注入多次的问题

1、在UserBeans类中写两个对象注解;

@Component
public class UserBeans {
    @Bean(name = "user1") // 【注意事项:只使用一个 @Bean 是无法将对象存储到容器中的】
    public User getUser1() {
        User user = new User();
        user.setId(1);
        user.setName("张三");
        return user;
    }

    @Bean(name = "user2") // 【注意事项:只使用一个 @Bean 是无法将对象存储到容器中的】
    public User getUser2() {
        User user = new User();
        user.setId(2);
        user.setName("李四");
        return user;
    }

2、通过启动类来获取对象;

ApplicationContext context= new ClassPathXmlApplicationContext("spring-config.xml");
User user = context.getBean(User.class);//只使用类属性
System.out.println(user);

运行结果:

9d11f93964b14f7496cad85c3d4aaac9.png

翻译过来的意思就是:没有可用的“com.User”类型的合格bean:应为单个匹配bean,但找到2:user1,user2;

那么,如何解决呢?这里我们提供了三种解决方案;

1、精准的描述bean的名称(将注入的名称写对)

比如我们在启动类中使用id+class的形式来取对象;

ApplicationContext context= new ClassPathXmlApplicationContext("spring-config.xml");
User user = context.getBean("user1",User.class);//只使用类属性
System.out.println(user);

运行结果:没有问题;

a95764c8b2994e24b7719b05c6a2a250.png

2、使用@Resource设置name的方式来重命名注入的对象;

1、这里我们通过UserController类来进行演示;注意我们添加的注解@Resource,下面新写了一个对象user1;

package com;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Controller;

import javax.annotation.Resource;

@Controller
public class UserController {
    @Resource
    private User user1;
    public void sayHi(){
        System.out.println("User"+user1);
    }
}

启动类App中代码:

ApplicationContext context= new ClassPathXmlApplicationContext("spring-config.xml");
UserController userController = context.getBean(UserController.class);
userController.sayHi();

运行结果:

c3427d0324524f45a5b33326909721b0.png

3、使用@AutoWired+@Qualifier来筛选bean对象;

UserController代码:

package com;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Controller;

import javax.annotation.Resource;

@Controller
public class UserController {
    @Autowired
    @Qualifier(value = "user2")
    private User user2;
    public void sayHi(){
        System.out.println("User"+user2);
    }
}

运行结果:

7dfeb12369de4c22a18d8fa934dc987a.png

对象注入的三种方法

1、属性注入

属性注⼊是使⽤ @Autowired 实现的,将 Service 类注⼊到 Controller 类中。
package com;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import javax.annotation.Resource;
/**
 * 根据属性实现 bean 对象的注入
 */
@Controller
public class UserController2 {
    // 对象注入方式1:属性注入
    @Autowired
    private UserService userService;
    public void sayHi() {
        userService.sayHi();
    }

}

启动类App:

ApplicationContext context= new ClassPathXmlApplicationContext("spring-config.xml");
UserController2 userController2 = context.getBean(UserController2.class);
userController2.sayHi();

运行结果:

9e0802c7718e4f1890216f6f47e8e847.png

2、构造方法注入

package com;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

/**
 * 使用构造方法实现 bean 注入
 */
@Controller
public class UserController3 {

    private UserService userService;

    // 构造方法注入(官广推荐写法)
    @Autowired
    public UserController3(UserService userService) {
//        userService = new UserService(); // 传统的写法
        this.userService = userService;
    }
    
    public void sayHi() {
        userService.sayHi();
    }

}

注:如果当前类只存在一个构造方法,那么@Autowired注解可以省略;

启动类App:

ApplicationContext context= new ClassPathXmlApplicationContext("spring-config.xml");
UserController3 userController3 = context.getBean(UserController3.class);
userController3.sayHi();

运行结果:

2c933cecf82e437c9f62bbdfb0d0a68b.png

3、Setter方法注入

package com;

import org.springframework.stereotype.Controller;

import javax.annotation.Resource;

/**
 * 使用 Setter 实现 bean 注入
 */
@Controller
public class UserController4 {

    private UserService userService;

    @Resource
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void sayHi() {
        userService.sayHi();
    }

}

启动类App:

ApplicationContext context= new ClassPathXmlApplicationContext("spring-config.xml");
UserController4 userController4 = context.getBean(UserController4.class);
userController4.sayHi();

运行结果:

36282f832a3b4bfa8814fb3273fce9be.png

属性注入和构造方法注入以及 Setter 注入的区别是什么?

🚈1、属性注入:特点写法简单。但是通用性不好,它只能运行在 IoC 容器下,如果是非 IOC 容器就会出现问题。
🚅2、Setter 注入:早期 Spring 版本推荐的写法,Setter 注入通用性没有构造方法注入通用。
🚄3、构造方法注入: 通用性更好、它能确保在使用注入对象之前,此注入对象一定初始化过了。当构造方法注入参数过多时,此时开发者就要检查自己所写的代码是否符合单一设计原则的规范了,此注入方式也是 spring后期版本中推荐的注入方式。

注意:@Resource注解只支持属性注入和Setter注入,不支持构造方法注入;

2b1a4d07fd2a49428158192fccddc3d1.gif

@Resource VS @Autowired?

🎑出身不同: @Resource 来着与 JDK (Java 亲儿子) ,@Autowired 是 Spring 框架提供的。

🏚2、用法不同: @Autowired 支持属性注入、构造方法注入和 Setter 注入,而 @Resource 不支持构造方法注入。

🏫3、支持的参数不同: @Resource 支持更多的参数设置,比如 name、type 设置;@Autowired 只支持required 参数设置。

873be796b39a4549af4f525d1f34d2ed.jpeg

💡💡OK,今天的学习内容就到这里啦,至此,Spring更简单的读取和存储对象就已经更新完毕了,下篇博客我们会继续更新"bean的作用域和生命周期",欢迎阅读,感谢订阅!!

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

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

相关文章

如何防止系统发生异常时,别人传递过来的关键数据不丢失?(AOP + xxlJob)

需求 在开发中,客户每天需要定时调用我们的api去上传一些数据到数据库中,当数据库发生异常或者系统发生异常,上传的一些数据会丢失不做入库操作,现想防止数据库或系统发生异常,数据能不丢失,同时&#xff…

TryHackMe-AD证书模板

AD Certificate Templates SpecterOps 完成并作为白皮书发布的研究表明,可以利用配置错误的证书模板进行权限提升和横向移动。根据错误配置的严重性,它可能允许 AD 域上的任何低特权用户只需单击几下即可将其权限提升为企业域管理员的权限! …

C语言宏使用

C语言宏 编译一个C语言程序的第一步骤就是预处理阶段,这一阶段就是宏发挥作用的阶段,编译完之后宏对二进制代码不可见。 使用 1. 宏常量 #define PI 3.142. 宏语句 #define Print printf("hello,world!\r\n")3. 宏函数 使用宏来定义函数&#xff0c…

基于灰狼算法的极限学习机(ELM)回归预测-附代码

基于灰狼算法的极限学习机(ELM)回归预测 文章目录 基于灰狼算法的极限学习机(ELM)回归预测1.极限学习机原理概述2.ELM学习算法3.回归问题数据处理4.基于灰狼算法优化的ELM5.测试结果6.参考文献7.Matlab代码 摘要:本文利用灰狼算法对极限学习机进行优化,并…

[stable-diffusion-art] 指北-3 inpainting

https://stable-diffusion-art.com/inpainting_basics/https://stable-diffusion-art.com/inpainting_basics/inpainting的应用主要是重绘,目前的模型换衣主要还是通过lora训练特定衣服来实现的。 模型权重: !wget https://huggingface.co/runwayml/sta…

一、spring Cloud Alibaba概述

spring Cloud Alibaba学习,第一篇spring Cloud Alibaba概述篇。 微服务是一种架构思想,spring Cloud Alibaba是微服务的系列化实现方式之一。 一、架构演变过程 架构粒度更加精细,拆分成不同的服务,每个服务直接互不影响&#…

基于海鸥算法的极限学习机(ELM)回归预测-附代码

基于海鸥算法的极限学习机(ELM)回归预测 文章目录 基于海鸥算法的极限学习机(ELM)回归预测1.极限学习机原理概述2.ELM学习算法3.回归问题数据处理4.基于海鸥算法优化的ELM5.测试结果6.参考文献7.Matlab代码 摘要:本文利用海鸥算法对极限学习机进行优化,并…

【LeetCode股票买卖系列:309. 最佳买卖股票时机含冷冻期 | 暴力递归=>记忆化搜索=>动态规划】

🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…

C/C++笔记-分析带有Q_OBJECT继承QObject的类make流程

此篇博文记录到个笔记时间2023-02-15,发表到网上的时间是2023-05-03。 这里以Qt5.5.1为例,操作系统是centos 7.5版本。 代码如下: MOCQtConsole.pro QT coreTARGET MOCQtConsoleSOURCES main.cpp \Test.cppHEADERS Test.hTest.h …

Threejs进阶之十二:Threejs与Tween.js结合创建动画

tween.js介绍 Tween.js是一个可以产生平滑动画效果的js库,其官方地址为:https://github.com/tweenjs/tween.js/,可以将源码下载后,可以在tween.js/dist/文件夹下找到相应的js代码,在HTML中进行引用;也可以…

配置KylinV10

配置KylinV10 文章目录 配置KylinV10设置“root”登录密码允许通过图像界面登录到“root”开机自动登录到“root”关闭“麒麟安全授权认证”关闭自动睡眠挂载“Windows”下共享目录到虚拟机安装“Docker”到“KylinV10”B/S安装“Maven-3.6.3”安装“Gradle-4.4.1”安装“Jdk-8…

UG NX二次开发(C++)-建模-创建基准坐标系(NXOpen方法)

文章目录 1、前言2、UG NX中根据菜单来创建基准坐标系2.1 打开UG NX2.2 打开基准坐标系创建界面2.3 根据两个轴和原点创建基准坐标系 3、采用NXOpen方法来创建基准坐标系3.1 创建创建基准坐标系的方法3.2 在do_it方法中添加调用代码3.3 生成dll,并用NXOpen执行来测试…

spring boot原理分析

总体流程 prepareEnvironment里会生成基本的propertySource列表,当然后续还可能会改,比如apollo会在refreshContext时添加自己的propertySource。 prepareContext里会调initializer初始化ApplicationContext,接着加载bean定义。 refreshCo…

深入源码理解redis数据结构(一)

文章目录 一. 动态字符串SDS二. IntSet三. Dict 一. 动态字符串SDS 我们都知道Redis中保存的Key是字符串,value往往是字符串或者字符串的集合。可见字符串是Redis中最常用的一种数据结构。不过Redis没有直接使用C语言的字符串,因为C语言字符串存在着很多…

LVS负载均衡集群--DR模式

一、LVS-DR集群介绍 LVS-DR(Linux Virtual Server Director Server)工作模式,是生产环境中最常用的一 种工作模式。 1、LVS-DR 工作原理 LVS-DR 模式,Director Server 作为群集的访问入口,不作为网关使用&#xff0…

《程序员面试金典(第6版)》面试题 16.11. 跳水板

题目描述 你正在使用一堆木板建造跳水板。有两种类型的木板,其中长度较短的木板长度为shorter,长度较长的木板长度为longer。你必须正好使用k块木板。编写一个方法,生成跳水板所有可能的长度。 返回的长度需要从小到大排列。 示例 1 输入&a…

Request和Response应用

ServletRequest应用 ServletRequest应用非常广泛,下面是一些例子: 获取请求参数:可以使用HttpServletRequest的getParameter()方法获取请求参数。 获取请求头信息:可以使用HttpServletRequest的getHeader()方法获取请求头信息。…

数据结构(六)—— 二叉树(3)

文章目录 题1 589 N 叉树的前序遍历2 226 翻转二叉树递归迭代 3 101 对称二叉树递归迭代 4 104 二叉树的最大深度层序遍历直接解决递归 5 111 二叉树的最小深度层序遍历递归 6 222 完全二叉树的节点个数递归遍历 7 110 平衡二叉树递归 题 递归三部曲 1、确定递归函数的参数和返…

如何使用 PyTorch 进行半精度、混(合)精度训练

https://featurize.cn/notebooks/368cbc81-2b27-4036-98a1-d77589b1f0c4 nvidia深度学习加速库apex简单介绍 NVIDIA深度学习加速库Apex是一个用于PyTorch的开源混合精度训练工具包,旨在加速训练并减少内存使用。Apex提供了许多用于混合精度训练的工具,…

【Python基础入门学习】Python函数与变量的使用

python语法 1. 函数的快速体验2. 函数的基本使用2.1 函数的定义2.2 函数的调用2.3 第一个函数演练2.4 PyCharm 的调试工具2.5 函数的文档注释 3. 函数的参数3.1 函数参数的使用3.2 函数参数的作用3.3 形参和实参 4. 函数的返回值5. 函数的嵌套使用6 使用模块中的函数6.1 第一个…