「JavaEE」Spring IoC 1:Bean 的存储

news2024/9/17 8:58:40

🎇个人主页

🎇所属专栏:Spring

🎇欢迎点赞收藏加关注哦!
 


IoC 简介

IoC 全称 Inversion of Control,即控制反转

控制反转是指控制权反转:获得依赖对象的过程被反转了

传统开发模式中,需要某个对象时,我们要自己通过 new 来创建对象, 现在无需自行创建, 而是把创建对象的任务交给容器, 程序中只需依赖注入 (Dependency Injection, 简称 DI) 就可以了。这个容器称为 IoC 容器

Spring 是一个 IoC 容器, 所以 Spring 有时也被称为 Spring 容器。作为容器, 它具备两个最基础的功能:存和取

Spring 容器管理的对象我们称为 Bean 。我们把 Bean 交给 Spring 管理, 由它负责对象的创建和销毁。我们的程序只需告诉 Spring,哪些需要存, 以及如何从 Spring 中取出对象


Bean 的存储

有两类注解类型可以实现存储

  1. 类注解:@Controller@Service@Repository@Component@Configuration

  2. 方法注解:@Bean

@Controller (控制器存储)

@Controller // 将对象存储到 Spring 中
public class UserController { 
    public void Hello(){
        System.out.println("Hello UserController"); 
    }
}  

要确认对象是否已经存到 Spring 容器中,我们可以试试能否从 Spring 中取出 Bean,那就得先得到 Spring 的上下文,即 ApplicationContext

@SpringBootApplication
public class SpringIoCDemoApplication {
    public static void main(String[] args) {
        //获取 Spring 上下文对象
        ApplicationContext context = SpringApplication.run(SpringIoCDemoApplication.class, args);
        //从上下文中获取 Bean
        UserController userController = context.getBean(UserController.class);
        //使用 Bean
        userController.Hello();
    }
}

观察运行结果:

如果把 @Controller 去掉的话,运行时会抛异常:

这个异常意思是说没有找到你要的 Bean,说明去掉注解后就没有 UserController 类的实例,说明没存进 Spring

上面代码是根据类型查找对象

ApplicationContext 也提供了其他获取 bean 的方式, ApplicationContext 获取 bean 对象的功能, 是父类 BeanFactory 提供的功能: 

public interface BeanFactory {
    Object getBean(String name) throws BeansException;

    <T> T getBean(String name, Class<T> requiredType) throws BeansException;

    Object getBean(String name, Object... args) throws BeansException;

    <T> T getBean(Class<T> requiredType) throws BeansException;

    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
    
    //其他成员方法已省略
}

常用的是第 1、2、4 种,这三种方式获取到的bean是一样的。其中第一、二种根据名称获取对象。Spring 会给每个对象起一个名字, 根据 Bean 的名称(BeanId)就可以获取到对应的对象

命名规则

默认情况下是类名的小驼峰表示。如果类名的前两位均为大写,那么 Bean 的名称就是类名本身

举个例子

类名:UserController Bean 名称为:userController

类名: UController Bean的名称为: UController

@SpringBootApplication
public class SpringIoCDemoApplication {
    public static void main(String[] args) {
        //获取 Spring 上下文对象
        ApplicationContext context = SpringApplication.run(SpringIoCDemoApplication.class, args);
        UserController userController1 = context.getBean(UserController.class);
        UserController userController2 = (UserController) context.getBean("userController");
        UserController userController3 = context.getBean(UserController.class,"userController");
        System.out.println(userController1);
        System.out.println(userController2);
        System.out.println(userController3);
    }
}

运行后发现地址都是一样的,说明是同一个对象


@Service(服务存储)

直接把上述代码的 @Controller 改为 @Service

@Service
public class UserController {
    public void Hello() {
        System.out.println("Hello UserController");
    }
}

观察运行结果,发现成功从 Spring 中获取到 UserService 对象, 并执行 UserService 的 Hello 方法

同理,换成 @Repository(仓库存储)、@Component(组件存储)、@Configuration(配置存储)还是可以得到一样的结果。这样看来的话,这些注解的作用是差不多的,那还为什么要弄这么多类注解?


类注解的分类

这个也是和我们前面讲的应用分层相呼应。目的是让程序员看到类注解之后,就能直接了解当前类的用途,类注解的用途如下:

  • @Controller:控制层, 接收请求, 处理请求并响应

  • @Servie:业务逻辑层, 处理具体的业务逻辑

  • @Repository:数据访问层,也称为持久层,负责数据访问操作

  • @Configuration:配置层. 处理项目中的一些配置信息

程序应用分层的调用流程如下:

观察 @Controller / @Service / @Repository / @Configuration 等注解的源码可以发现这些注解里面都有 @Component

@Component 是一个元注解,可以注解其他类注解。如 @Controller@Service@Repository 等. 这些注解称为 @Component衍生注解

@Controller , @Service 和 @Repository 用于更具体的用例,这三个分别在控制层, 业务逻辑层, 持久化层


方法注解 @Bean

方法注解 @Bean 要配合类注解才能将对象存储到 Spring 容器中

@Componen
public class BeanConfig { 
     @Bean 
     public User user(){ 
         User user = new User(); 
         user.setName("zhangsan"); 
         user.setAge(18); 
         return user; 
     } 
}

@SpringBootApplication 
public class SpringIocDemoApplication { 
    public static void main(String[] args) { 
         //获取Spring上下⽂对象 
         ApplicationContext context = SpringApplication.run(SpringIocDemoApplicatio 
         //从Spring上下⽂中获取对象 
         User user = context.getBean(User.class); 
         //使⽤对象 
         System.out.println(user); 
    }
 } 

运行结果如下:

@Bean 注解的 Bean 名称就是它的方法名,如果同个类有多个对象,我们通过 Bean 的名称来获取它们

@Component 
public class BeanConfig { 
     @Bean 
     public User user1(){ 
         User user = new User(); 
         user.setName("zhangsan"); 
         user.setAge(18); 
         return user; 
     } 
     @Bean 
     public User user2(){ 
         User user = new User(); 
         user.setName("lisi"); 
         user.setAge(19); 
         return user; 
     } 
}

@SpringBootApplication 
public class SpringIocDemoApplication { 
     public static void main(String[] args) { 
         //获取Spring上下⽂对象 
         ApplicationContext context = SpringApplication.run(SpringIocDemoApplicatio 
         //根据bean名称, 从Spring上下⽂中获取对象 
         User user1 = (User) context.getBean("user1"); 
         User user2 = (User) context.getBean("user2"); 
         System.out.println(user1); 
         System.out.println(user2); 
     } 
} 

运行结果:


扫描路径

Bean 要想生效,还需要被 Spring 扫描

通过修改目录结构来测试 Bean 对象是否生效:

@SpringBootApplication
public class ApplicationControllerApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(ApplicationControllerApplication.class, args);
        Student s1 = (Student) context.getBean("student1");
        Student s2 = (Student) context.getBean("student2");
        System.out.println(s1);
        System.out.println(s2);
    }
}

运行时抛出异常:没有找到 Bean 对象

使用五大注解声明的 bean,要想生效, 还需要配置扫描路径, 让 Spring 扫描到这些注解,通过 @ComponentScan 进行配置

@SpringBootApplication
@ComponentScan({"com.example.demo"})
public class ApplicationControllerApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(ApplicationControllerApplication.class, args);
        Student s1 = (Student) context.getBean("student1");
        Student s2 = (Student) context.getBean("student2");
        System.out.println(s1);
        System.out.println(s2);
    }
}

配置之后再次运行,就可以正常跑起来了:

加了 @ComponentScan 注解的类,当它需要用到某个依赖时,它就会去 @ComponentScan 所指的路径中找

一开始没配置扫描路径也可以运行是因为:虽然没有显式配置 @ComponentScan,但它实际上已经包含在了启动类声明注解 @SpringBootApplication 中了,默认扫描的范围是 SpringBoot 启动类所在包及其子包

建议把启动类放在我们希望扫描的包的路径下, 这样我们定义的 bean 就都可以被扫描到

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

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

相关文章

38 Debian如何配置Keepalived+LVS+NFS实现高可用负载均衡

作者:网络傅老师 特别提示:未经作者允许,不得转载任何内容。违者必究! Debian如何配置Keepalived+LVS+NFS实现高可用负载均衡 《傅老师Debian知识库系列之38》——原创 ==前言== 傅老师Debian知识库特点: 1、拆解Debian实用技能; 2、所有操作在VMware虚拟机实测完成;…

C# Unity 面向对象补全计划 之 初识继承方法与多态

本文仅作学习笔记与交流&#xff0c;不作任何商业用途&#xff0c;作者能力有限&#xff0c;如有不足还请斧正 本系列旨在通过补全学习之后&#xff0c;给出任意类图都能实现并做到逻辑上严丝合缝 1.继承方法 C# & Unity 面向对象补全计划 之 继承&#xff08;字段与属性&…

什么是五力分析?5分钟带你了解它在企业财务经营中的应用与价值!

如今&#xff0c;随着全球化进程的不断加速&#xff0c;市场环境复杂多变&#xff0c;市场竞争日益激烈&#xff0c;财务经营已经成为了企业应对复杂市场环境、保持自身竞争力的关键。体系化的五力分析平台能够为企业提供一套全面的解决方案&#xff0c;帮助企业在盈利能力、偿…

重生奇迹MU 多准备几套装备才能玩得更好

一、时装必须是要准备一套的 我相信每个玩家都非常注重时装&#xff0c;无论是哪个职业&#xff0c;都希望在平常场合下穿上时髦惊艳的服装。在勇者大陆中&#xff0c;这种操作很常见&#xff0c;几乎所有玩家都需要准备一套。 在游戏中&#xff0c;需要具备一套适合的装备才…

Java实现数据库图片上传(包含从数据库拿图片传递前端渲染)-图文详解

目录 1、前言&#xff1a; 2、数据库搭建 &#xff1a; 建表语句&#xff1a; 3、后端实现&#xff0c;将图片存储进数据库&#xff1a; 思想&#xff1a; 找到图片位置&#xff08;如下图操作&#xff09; 图片转为Fileinputstream流的工具类&#xff08;可直接copy&#…

【C++】模板的特化

文章目录 概念函数模板特化类模板特化全特化偏特化 概念 通常情况下&#xff0c;使用模板可以实现一些与类型无关的代码&#xff0c;但是有一些类型需要特殊处理&#xff0c;否则可能会得到一些错误的结果。 比如&#xff0c;在比较两个数的大小时&#xff0c;如果传入两个变量…

RAG+AI工作流+Agent:LLM框架该如何选择,全面对比MaxKB、Dify、FastGPT、RagFlow、Anything-LLM,以及更多推荐

RAGAI工作流Agent&#xff1a;LLM框架该如何选择&#xff0c;全面对比MaxKB、Dify、FastGPT、RagFlow、Anything-LLM,以及更多推荐 1.MaxKB MaxKB Max Knowledge Base&#xff0c;是一款基于 LLM 大语言模型的开源知识库问答系统&#xff0c;旨在成为企业的最强大脑。它能够帮…

MySQL:存储引擎相关命令、性能比较

目录 存储引擎 概念 类型 示例 数据库文件 MylSAM .frm .MYD .MYI InnoDB .frm .ibd .opt 查看指定表的存储引擎类型 查看系统支持的存储引擎 修改存储引擎 通过配置文件指定存储引擎 使用alter修改 创建表的同时指定存储引擎 使用set命令临时指定存储引擎…

java入门-API学习

package API;//告诉编译器&#xff0c;编译之后应该放到哪个包里import API.try3.test3; import API.try3.test5; import itcast.test2;import java.util.Random; import java.util.Scanner;//导包 public class Introduce {public static void main(String[] args) {//别忘记写…

为何2024年这4款ai智能写作工具被赞为YYDS?

在数字化的大潮中&#xff0c;人工智能已经深入到我们生活的各个角落&#xff0c;当然也包括写作领域。随着ai智能写作工具的兴起&#xff0c;它们不仅显著提升了写作效率&#xff0c;还为创作打开了全新的可能性。今天&#xff0c;我们就来看看四款特别受欢迎的AI写作工具&…

QT log4qt 记录日志

一.环境 Qt 5.15.2 log4qt 二.源码 1.编译 log4qt 源码,生成dll文件,并将.h 拷贝至项目目录 2.main.cpp #include "mainwindow.h"#include <QApplication> #include <QDir> #include "Log4Qt/logmanager.h" #include "Log4Qt/pattern…

职场离职潮:年轻人的选择与挑战

近年来&#xff0c;随着社会的发展和个人价值观的变化&#xff0c;越来越多的人开始主动或被动地离开职场。这一现象在社交网络上引发了广泛的讨论&#xff0c;甚至出现了专门分享离职经历的“离职博主”。为了深入了解这一趋势背后的真实情况&#xff0c;近日相关机构展开了一…

【传输层协议】UDP和TCP协议

UDP协议 UDP协议全称为User Datagram Protocol&#xff0c;用户数据报协议。UDP协议报文格式如下&#xff1a; 16UDP长度。表示整个数据报的最大长度&#xff0c;即UDP首部UDP数据。这个字段帮助我们确保在网络字节流中获取完整的UDP报文信息。校验和&#xff1a;用于检测数…

法兰式满油阀SPF-125-12C、STF-125-12C

法兰式满油阀又名预充阀、充液阀&#xff0c;合金钢和球墨铸铁材质&#xff0c;体积小&#xff0c;易于拆卸&#xff0c;低压损&#xff0c;流量大&#xff0c;构造简单&#xff0c;耐久性佳&#xff0c;可直接装置于油缸盖侧&#xff0c;SPF-32-12C、STF-32-12C、SPF-50-12C、…

ZooKeeper中间件监控指标解读

监控易是一款功能全面的IT监控软件&#xff0c;能够实时监控各类IT资源和应用的状态&#xff0c;包括中间件、数据库、网络设备等。对于ZooKeeper这一重要的分布式协调服务中间件&#xff0c;监控易提供了详尽的监控指标&#xff0c;帮助用户全面了解ZooKeeper集群的运行状态。…

鸿蒙(API 12 Beta2版)NDK开发【使用Node-API接口进行异步任务开发】

使用Node-API接口进行异步任务开发 场景介绍 napi_create_async_work是Node-API接口之一&#xff0c;用于创建一个异步工作对象。可以在需要执行耗时操作的场景中使用&#xff0c;以避免阻塞主线程&#xff0c;确保应用程序的性能和响应性能。例如以下场景&#xff1a; 文件…

最新版Polyverse - Music Bundle Deal [06.2024],win和mac,支持intel和M1芯片

一。Polyverse插件套装 Polyverse - Music Bundle Deal 1.释放您的创作潜力 无论您是希望突破创作极限的音乐制作人&#xff0c;还是寻求新颖创新方式来增强混音的音频工程师&#xff0c;Polyverse 捆绑包交易都具有非凡的价值&#xff0c;可以帮助您将音乐提升到一个新的水平…

【数学建模】【优化算法】:【MATLAB】从【一维搜索】到】非线性方程】求解的综合解析

目录 第一章&#xff1a;一维搜索问题 黄金分割法 股票交易策略优化 总结&#xff1a; 第二章&#xff1a;线性规划 线性规划&#xff08;Simplex 算法&#xff09; 生产计划优化 总结&#xff1a; 第三章&#xff1a;无约束非线性优化问题 梯度下降法 神经网络训练…

Python中导入不同文件夹中的函数

1、代码举例&#xff1a;from Python_CodeFile.LDAP3.del_file.Get_Computer_Dn import get_computer_dn # 以上代码导入路径为&#xff1a;Python_CodeFile/LDAP3/del_file/Get_Computer_Dn.py 文件中的get_computer_dn函数。

传统放牧方式与北斗科技的碰撞:北三短报文头羊定位追踪器PD28守护放牧生活

在大草原的广袤天地中&#xff0c;放牧生活是蒙古族人民的传统之一。然而&#xff0c;除了美丽和自由&#xff0c;放牧生活也伴随着一些危险。以前由于科技落后&#xff0c;人工成本低&#xff0c;主要依靠人力去放牧&#xff0c;牧民放牧顶风踏雪走个几十公里都极为寻常。除了…