当前位置: 首页 > news >正文

Spring加载Bean的多种方式

文章目录

  • 1. XML方式定义
  • 2. 使用@Component + @ComponentScan
  • 3. 使用@Configuration + @Bean
  • 4. 使用FactoryBean的方式加载bean
  • 5. Import方式
  • 6. @Import + @ImportSelector
  • 7. @Import + ImportBeanDefinitionRegistrar
  • 8. 实现接口BeanDefinitionRegistryPostProcessor
  • 9. 实现接口BeanFactoryPostProcessor

Spring的IOC特性,使得其加载bean的方式有很多,这里记录一下加载bean的9种方式:

1. XML方式定义

这种方式在早起的项目中很常见,但是由于容易导致配置文件的爆炸式增长,致使其难以维护,现在的使用已经越来越少。

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="person" class="com.example.Person"/>
</beans>

在Java代码中可以获取名为person的bean。

class Person {
}public class Test {public static void main(String[] args) {ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring-config.xml");
System.out.println(applicationContext.getBean("person"));
}

这样我们可以轻松获取到bean。

2. 使用@Component + @ComponentScan

用@ComponentScan指定需要扫描的包,然后指定包下的标注了指定注解的类加载为bean。这里的注解包括但不限于:@Component,@Service, @Controller, @Repository。
这里要注意一点,springboot默认扫描启动类所在包以及其子包,所以很多时候我们看起来只是在类上加了注解就已经可以加载到Bean了。

3. 使用@Configuration + @Bean

有些Bean不是我们自己定义的,那么我们无法在这个类上添加注解,因此可以通过这个方法来加载Bean。

class Person {
}@Configuration
public class Config {@Beanpublic Person person() {return new Person();}
}

这样我们就可以从context中获取到名为person的Bean。当然,也可以在@Bean注解上指定Bean的name,即**@Bean(“customPerson”)**

4. 使用FactoryBean的方式加载bean

通过实现FactoryBean接口,来加载bean,这里其实是代理的方式在创建bean。

class Person {}@Component
public class PersonFactoryBean implements FactoryBean<Person> {@Overridepublic Person getObject() throws Exception {return new Person();}@Overridepublic Class<?> getObjectType() {return Person.class;}@Overridepublic boolean isSingleton() {return FactoryBean.super.isSingleton();}
}

实现了FactoryBean接口的类,它在spring容器中本身也是一个bean。这个bean的name与普通bean不同,将会以**&**开头,因此我们要获取这个类的时候,需要使用的bean名称是“&”+类名。这里就是“&PersonFactoryBean”。那么如何获取这个FactoryBean要产生的类呢?
我们已经获取了这个“FactoryBean”的bean,那么就可以通过其getObject()方法,获取这个person bean。
这样获取的话也是有些麻烦,所以我们可以直接获取名为“personFactoryBean”这个的这个bean,这个是由容器帮我们生成的,且这个bean就是Person类型的bean。

public static void main(String[] args) throws Exception {var context = new AnnotationConfigApplicationContext(SpringApplication.class);var bean = context.getBean("personFactoryBean");if (bean instanceof PersonFactoryBean) {System.out.println("personFactoryBean=====");} //这里的bean类型,是Person,并不是FactoryBeanvar bean1 = context.getBean("&personFactoryBean");//这个是FactoryBean本身的Beanif (bean1 instanceof PersonFactoryBean) {System.out.println(Objects.requireNonNull(((PersonFactoryBean) bean1).getObject()).getName());}Person person = (Person) context.getBean("personFactoryBean");System.out.println(person.getName());//直接获取这个person Bean}

5. Import方式

class Person {}@SpringBootApplicatioin
@Import({Person.class})
public class Application{public static void main(String[] args) {var context = new AnnotationConfigApplicationContext(Sj1123Application.class);Person person = (Person) context.getBean("com.example.sj1123.entity.Person");}}

这样就可以获取到Person类型的Bean。但是这里要注意的是,这个bean的名称,是类的全限定名,不是简单的person。

6. @Import + @ImportSelector

使用ImportSelector的好处:

  • 1、把某个功能的相关类放到一起,方面管理和维护。
  • 2、重写selectImports方法时,能够根据条件判断某些类是否需要被实例化,或者某个条件实例化这些bean,其他的条件实例化那些bean等,我们能够非常灵活的定制化bean的实例化。

这种方式我们需要实现ImportSelector接口,并重写selectImports()方法,然后将我们要导入的类的全限定名写在里面即可。

class Person {}class PersonImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {return new String[]{"com.example.sj1123.entity.Person"};}
}@SpringBootApplicatioin
@Import({PersonImportSelector.class})
public class Application{public static void main(String[] args) {var context = new AnnotationConfigApplicationContext(Sj1123Application.class);Person person = (Person) context.getBean("com.example.sj1123.entity.Person");}}

这里获取bean时,bean的名称仍然是全限定名。

7. @Import + ImportBeanDefinitionRegistrar

这种方式需要实现ImportBeanDefinitionRegistrar接口,并重写registerBeanDefinitions()方法,然后定义需要注册的Bean的定义信息,然后registry.registerBeanDefinition()方法注册即可。这种方式比ImportSelector更加灵活,可以自定义bean的名称、作用域等很多参数。

class Person {}class PersonBeanDefinitionRegister implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(@NonNull AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {ImportBeanDefinitionRegistrar.super.registerBeanDefinitions(importingClassMetadata, registry, importBeanNameGenerator);registry.registerBeanDefinition("person", new RootBeanDefinition(Person.class));}
}@SpringBootApplicatioin
@Import({PersonBeanDefinitionRegister.class})
public class Application{public static void main(String[] args) {var context = new AnnotationConfigApplicationContext(Sj1123Application.class);Person person = (Person) context.getBean("person");}}

8. 实现接口BeanDefinitionRegistryPostProcessor

在Spring容器启动方法refresh()方法的invokeBeanFactoryPostProcessors()方法中,会执行 BeanDefinitionRegistryPostProcessor 的 postProcessBeanDefinitionRegistry()方法,它允许对beanDefinition进行后置处理,我们可以在这个方法调整IOC容器中的beanDefinition定义信息,从而干扰到后面bean初始化的过程。

class Person {}@Component
public class PersonBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {registry.registerBeanDefinition("person", new RootBeanDefinition(Person.class));}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
}@SpringBootApplicatioin
public class Application{public static void main(String[] args) {var context = new AnnotationConfigApplicationContext(Sj1123Application.class);Person person = (Person) context.getBean("person");}}

9. 实现接口BeanFactoryPostProcessor

BeanDefinitionRegistryPostProcessor就是继承自BeanFactoryPostProcessor,所以使用BeanFactoryPostProcessor也可以实现注册Bean的功能。它们的区别如下:

  • 1、 BeanDefinitionRegistryPostProcessor:侧重于bean的注册;
  • 2、 BeanFactoryPostProcessor:侧重于对已经注册的bean的属性进行。
class Person {}@Component
public class PersonBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {((DefaultListableBeanFactory)beanFactory).registerBeanDefinition("person", new RootBeanDefinition(Person.class));}
}@SpringBootApplicatioin
public class Application{public static void main(String[] args) {var context = new AnnotationConfigApplicationContext(Sj1123Application.class);Person person = (Person) context.getBean("person");}}

相关文章:

Spring加载Bean的多种方式

文章目录 1. XML方式定义2. 使用Component ComponentScan3. 使用Configuration Bean4. 使用FactoryBean的方式加载bean5. Import方式6. Import ImportSelector7. Import ImportBeanDefinitionRegistrar8. 实现接口BeanDefinitionRegistryPostProcessor9. 实现接口BeanFacto…...

minio分布式存储系统

目录 拉取docker镜像 minio所需要的依赖 文件存放的位置 手动上传文件到minio中 工具类上传 yml配置 config类 service类 启动类 测试类 图片 视频 删除minio服务器的文件 下载minio服务器的文件 拉取docker镜像 拉取稳定版本:docker pull minio/minio:RELEASE.20…...

Kafka 如何保证消息消费的全局顺序性

哈喽大家好&#xff0c;我是咸鱼 今天我们继续来讲一讲 Kafka 当有消息被生产出来的时候&#xff0c;如果没有指定分区或者指定 key &#xff0c;那么消费会按照【轮询】的方式均匀地分配到所有可用分区中&#xff0c;但不一定按照分区顺序来分配 我们知道&#xff0c;在 Kaf…...

boa+cgi上传文件超过1M报错问题

写在前面 今天需要使用页面上传bin包&#xff0c;文件大概是3.9mb&#xff0c;结果一直报错 POST /cgi-bin/Upgrade.cgi undefined Host: 192.168.137.200:8888 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0 Accept: text/h…...

抖去推--短视频账号矩阵系统saas工具源码技术开发(源头)

一、短视频矩阵系统搭建常见问题&#xff1f; 1、抖去推的短视频AI矩阵营销软件需要一定的技术水平吗&#xff1f; 答&#xff1a;不需要。产品简单易用&#xff0c;不需要具备专业的技术水平&#xff0c;即使是初学者&#xff0c;也能够轻松上手操作。 3、抖去推的短视频AI矩…...

【服务器能干什么】搭建一个短网址平台,可以查看数据详情!

昨天在 YouTube 上看到又一个搭建自己短网址的视频教程&#xff0c;用的是开源的 polr&#xff0c;但是按照步骤一步步搭建下来&#xff0c;最后一步都会出现 顺哥轻创 PLAINTEXT Whoops, looks like something went wrong百度、谷歌查了一圈也没找到有效的解决方法。&#x…...

MySQL备份与恢复(重点)

MySQL备份与恢复&#xff08;重点&#xff09; 一、用户管理与权限管理 ☆ 用户管理 1、创建MySQL用户 注意&#xff1a;MySQL中不能单纯通过用户名来说明用户&#xff0c;必须要加上主机。如jack10.1.1.1 基本语法&#xff1a; mysql> create user 用户名被允许连接的主…...

机器学习中的特征选择:方法和 Python 示例

布拉加德什桑达拉拉詹 一、说明 特征选择是机器学习流程中至关重要且经常被低估的步骤。它涉及从数据集中的原始特征集中选择最相关的特征&#xff08;输入变量或属性&#xff09;的子集。特征选择的重要性怎么强调都不为过&#xff0c;因为它直接影响机器学习模型的质量、效率…...

有哪些不错的golang开源项目?

前言 下面是github上的golang项目&#xff0c;适合练手&#xff0c;可以自己选择一些项目去练习&#xff0c;整理不易&#xff0c;希望能多多点赞收藏一下&#xff01;废话少说&#xff0c;我们直接进入正题>>> 先推荐几个教程性质的项目&#xff08;用于新手学习、…...

解决ssh使用public key远程登录服务器拒绝问题

目录 使用场景windows安装ssh客户端使用powershell ssh登录服务器生成密钥文件ubuntu ssh服务器配置使用vscode远程登录使用Xshell远程登录使用MobaXtem远程登录Server refused our key问题解决方案 使用场景 使用vscode远程ssh登录使用public key不需要输入密码,比较方便. w…...

js数组中,相同id的item数据合并

原数据&#xff1a; const list [ {id:1, key: a}, {id:1, key: b}, {id:2, key: c}, {id:2, key: d}, ]期望数据格式 const newList [ {id:1, keyList: [a,b]}, {id:2, keyList: [c,d]}, ]// 相同id的数据合并let newList_(list ).flatten().groupBy(id).map(_.spread((..…...

LeetCode(33)最小覆盖子串【滑动窗口】【困难】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 76. 最小覆盖子串 1.题目 给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串&#xff0c;则返回空字符串 "" 。 注意&#xff1a; 对于 t 中重复字…...

设计模式 创建者模式

设计模式 创建者模式 前言原来代码使用设计模式总结Builder模式在源码中的应用&#xff1a;其他代码 前言 “对象创建”模式——绕开new 工厂模式 抽象工厂 原型模式 构建器 动机与背景 目前需要建造一个房子&#xff0c;建造房子需要一系列特定的步骤&#xff0c;但是房子的类…...

排序算法--插入排序

实现逻辑 ① 从第一个元素开始&#xff0c;该元素可以认为已经被排序 ② 取出下一个元素&#xff0c;在已经排序的元素序列中从后向前扫描 ③如果该元素&#xff08;已排序&#xff09;大于新元素&#xff0c;将该元素移到下一位置 ④ 重复步骤③&#xff0c;直到找到已排序的元…...

【操作宝典】SQL巨擘:掌握SQL Server Management的终极秘籍!

目录 ⛳️【SQL Server Management】 ⛳️1. 启动登录 ⛳️2. 忘记密码 ⛳️3. 操作数据库和表 3.1 新建数据库text 3.2 新建表 3.3 编辑表 3.4 编写脚本 ⛳️【SQL Server Management】 ⛳️1. 启动登录 需要开启服务 ⛳️2. 忘记密码 登录windows--> 安全性 -->…...

Airtest遇到模拟器无法输入中文的情况该如何处理?

1. 前言 最近有收到同学们的一些提问&#xff0c;使用Airtest的 text 接口&#xff0c;发现在部分模拟器上&#xff0c; text 无法输入中文&#xff0c;不知道该怎么处理。 今天我们就输入这个小问题&#xff0c;来详细聊一下。 2. Airtest的输入法简介 对于Android设备来说…...

从农夫山泉家族任命,看“食企二代”的接班与传承

本文转载自产业科技 农夫山泉再次引发舆论关注&#xff0c;起因是一则人事任命消息。 市场消息称&#xff0c;农夫山泉对区域及人员进行了调整&#xff0c;其总部所在地浙江省被划分为四个区域&#xff0c;在以往浙南、浙北基础上多了浙西大区以及杭州大区&#xff0c;其中农…...

JavaScript启动本地应用程序

JavaScript调起本地应用程序 以下内容&#xff0c;自定义部分我也还未经过实际验证&#xff0c;酌情查看。 文章目录 JavaScript调起本地应用程序确定协议调用协议传参自定义写入协议获取参数 在浏览器中通过 JavaScript调起本地应用程序的一个可行方法就是 通过协议调起。 …...

软件工程理论与实践 (吕云翔)第十四章 软件维护与软件工程管理课后习题与解析

第十四章 软件维护与软件工程管理 1.判断题 &#xff08;1&#xff09;代码行技术是比较简单的定量估算软件规模的方法。(√) &#xff08;2&#xff09;功能点技术依据对软件信息域特性和软件复杂性的评估结果&#xff0c;估算软件规模。&#xff08;√&#xff09; &#…...

Flutter 桌面应用开发之读写Windows注册表

文章目录 需求来源Windows查询Windows版本号方法1. 如何查看Windows版本号2. Windows开发如何通过代码查询Windows版本号(1) 使用C#代码&#xff1a;(2) 使用VB.NET代码 3.通过注册表查看Windows版本信息 Flutter查询Windows版本号方法依赖库支持平台实现步骤1. 在pubspec.yaml…...

告别C盘焦虑!手把手教你将WSL2+Ubuntu22.04完整迁移到D盘(附Anaconda权限配置)

彻底释放C盘空间&#xff1a;WSL2Ubuntu22.04迁移至D盘全流程与Anaconda深度配置指南 每次打开资源管理器看到C盘飘红的存储条&#xff0c;就像程序员看到满屏的error log一样令人窒息。特别是当你的WSL2和Ubuntu系统在C盘安家后&#xff0c;那种空间被蚕食的焦虑感与日俱增。本…...

BBDown_GUI终极指南:三步完成B站视频批量下载的完整教程

BBDown_GUI终极指南&#xff1a;三步完成B站视频批量下载的完整教程 【免费下载链接】BBDown_GUI BBDown的图形化版本 项目地址: https://gitcode.com/gh_mirrors/bb/BBDown_GUI BBDown_GUI是一款功能强大的B站视频下载工具&#xff0c;通过直观的图形化界面让用户无需记…...

Frida实战:SSL Pinning绕过技术全解析

1. 为什么需要绕过SSL Pinning 当你用手机银行转账时&#xff0c;有没有想过数据是怎么安全传输的&#xff1f;这就是SSL/TLS加密的功劳。但有些应用为了更安全&#xff0c;会额外启用SSL Pinning技术——就像给你的快递加了专属密码锁&#xff0c;只有特定快递员能打开。 我在…...

从‘抛硬币’到‘A/B测试’:贝叶斯推断如何帮你做出更靠谱的业务决策?

从抛硬币到A/B测试&#xff1a;贝叶斯推断如何重塑数据决策逻辑 在产品迭代的十字路口&#xff0c;产品经理小张盯着屏幕上两组截然不同的实验结果&#xff1a;传统频率学派统计显示新功能显著提升了转化率&#xff08;p0.04&#xff09;&#xff0c;但贝叶斯分析给出的成功概率…...

如何用Obsidian Projects实现知识管理的可视化革命?[特殊字符]

如何用Obsidian Projects实现知识管理的可视化革命&#xff1f;&#x1f680; 【免费下载链接】obsidian-projects Plain text project planning in Obsidian 项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-projects 你是否曾为散落在各处的笔记而烦恼&#xf…...

Qt Design Studio新手避坑指南:从BASIC到Controls,这11个组件属性别再乱用了

Qt Design Studio新手避坑指南&#xff1a;从BASIC到Controls&#xff0c;这11个组件属性别再乱用了 刚接触Qt Design Studio的开发者常会被其丰富的组件库和灵活的QML语法吸引&#xff0c;但随之而来的是属性配置的"选择困难症"。不同于传统Qt Widgets开发&#xff…...

基于Docker与宝塔面板的Nextcloud私有云盘高效部署指南

1. 为什么选择Docker宝塔部署Nextcloud&#xff1f; 最近几年私有云盘越来越火&#xff0c;我自己也试过不少方案。Nextcloud作为开源的私有云解决方案&#xff0c;功能强大但部署起来确实有点门槛。传统的手动部署需要配置Nginx、PHP、MySQL等一系列服务&#xff0c;对新手来说…...

【深度解析】pyodbc.InterfaceError: IM002 错误的根源与系统级排查指南

1. 理解IM002错误的本质 当你第一次在Windows上用Python连接Access数据库时&#xff0c;突然蹦出pyodbc.InterfaceError: IM002这个错误&#xff0c;是不是感觉像被泼了一盆冷水&#xff1f;这个错误的核心其实就一句话&#xff1a;系统找不到你指定的ODBC驱动程序。想象一下你…...

从产品经理视角看技术实现:拆解‘苍穹外卖’套餐管理的业务逻辑与接口设计

从产品经理视角看技术实现&#xff1a;拆解‘苍穹外卖’套餐管理的业务逻辑与接口设计 在数字化餐饮服务领域&#xff0c;套餐管理模块的设计直接影响运营效率和用户体验。作为连接商业策略与技术落地的关键环节&#xff0c;产品经理需要深入理解业务规则如何转化为系统约束&am…...

保姆级避坑指南:在Ubuntu 18.04上编译i.MX8M Plus Yocto镜像(含依赖包处理)

保姆级避坑指南&#xff1a;在Ubuntu 18.04上编译i.MX8M Plus Yocto镜像全流程实战 1. 环境准备与依赖处理 i.MX8M Plus作为NXP旗舰级处理器&#xff0c;其Yocto编译环境对系统版本有严格要求。Ubuntu 18.04 LTS是最稳定的基础平台&#xff0c;但需要特别注意以下几个关键配置&…...