将bean注入Spring容器的五种方式
前言
我们在项目开发中都用到Spring,知道对象是交由Spring去管理。那么将一个对象加入到Spring容器中,有几种方法呢,我们来总结一下。
@ComponentScan + @Component
@ComponentScan可以放在启动类上,指定要扫描的包路径;该包路径下被@Component修饰的类,都会被注入到Spring容器中。
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;@ComponentScan(basePackages = "com.gs.beanRegister")
public class BootStrap {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BootStrap.class);A bean = context.getBean(A.class);bean.say();}}
com.gs.beanRegister包下:
import org.springframework.stereotype.Component;@Component
public class A {public void say() {System.out.println("这是a");}}
注:在SpringBoot中,由于其自动装配的特性,所以@ComponentScan可以不加,只要@Component修饰的类和启动类在同一包下或者在启动类所在包的子包下。
@Configuration + @Bean
@Configuration用来声明一个配置类,如果它的方法被@Bean修饰,那么该方法返回的对象也会被注入到Spring容器中。
代码方面,BootStrap 类不动,A类的@Component去掉,com.gs.beanRegister包下建个配置类:
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;@Configuration
public class MyConfiguration {@Beanpublic A a() {return new A();}}
通过@Import注解
这个注解可能平时大家接触得不多,它有好几种使用方式。
1.直接导入类的class
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;@Import(A.class)
public class BootStrap {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BootStrap.class);A bean = context.getBean(A.class);//B bean = context.getBean(B.class);bean.say();}}
A类不用添加任何注解:
public class A {public void say() {System.out.println("这是a");}}
2.导入配置类
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Import;@Import(MyConfiguration.class)
public class BootStrap {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BootStrap.class);A bean = context.getBean(A.class);bean.say();}}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;// 使用@Import导入配置类时,@Configuration可以不加
//@Configuration
public class MyConfiguration {@Beanpublic A a() {return new A();}}
3.导入ImportSelector的实现类
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Import;@Import(MyImportSelector.class)
public class BootStrap {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BootStrap.class);A bean = context.getBean(A.class);bean.say();}}
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;public class MyImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata metadata) {// 返回要注入的bean的全路径,A类不用任何注解修饰// SpringBoot的自动装配,就用到了这种方式return new String[] { A.class.getName() };}}
4.导入ImportBeanDefinitionRegistrar的实现类
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Import;@Import(MyImportBeanDefinitionRegistrar.class)
public class BootStrap {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BootStrap.class);A bean = context.getBean(A.class);bean.say();}}
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {// 构建bean的元数据,A类不用任何注解修饰// spring-mybatis扫描mapper接口,生成代理类,就是用的这种方式BeanDefinition definition = new RootBeanDefinition(A.class);registry.registerBeanDefinition("a", definition);}}
借助FactoryBean接口
实现FactoryBean接口的类,除了本身会被注入外,getObject方法返回的对象也会被注入到Spring容器中。
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Import;@Import(MyFactoryBean.class)
public class BootStrap {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BootStrap.class);A bean = context.getBean(A.class);bean.say();}}
import org.springframework.beans.factory.FactoryBean;public class MyFactoryBean implements FactoryBean {@Overridepublic Object getObject() throws Exception {return new A();}@Overridepublic Class<?> getObjectType() {return A.class;}}
借助BeanDefinitionRegistryPostProcessor接口
在Spring容器启动时,会调用该接口的postProcessBeanDefinitionRegistry方法,大概意思是等BeanDefinition(上面提到的bean的元数据)加载完成后,再对它进行后置处理。所以可以在此调整BeanDefinition,从而把对应的bean注入。
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class BootStrap {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();BeanDefinitionRegistryPostProcessor postProcessor = new MyBeanDefinitionRegistryPostProcessor();context.addBeanFactoryPostProcessor(postProcessor);context.refresh();A a = context.getBean(A.class);a.say();}}
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {BeanDefinition definition = new RootBeanDefinition(A.class);registry.registerBeanDefinition("a", definition);}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
}
相关文章:
将bean注入Spring容器的五种方式
前言 我们在项目开发中都用到Spring,知道对象是交由Spring去管理。那么将一个对象加入到Spring容器中,有几种方法呢,我们来总结一下。 ComponentScan Component ComponentScan可以放在启动类上,指定要扫描的包路径;…...
C生万物 | 常量指针和指针常量的感性理解
文章目录📚引言✒常量指针🔍介绍与分析📰小结与记忆口诀✒指针常量🔍介绍与分析📰小结与记忆口诀👉一份凉皮所引发的故事👈总结与提炼📚引言 本文我们来说说大家很困惑的两个东西&am…...
python 打包工具 pyinstaller和Nuitka区别
1.1 使用需求 这次也是由于项目需要,要将python的代码转成exe的程序,在找了许久后,发现了2个都能对python项目打包的工具——pyintaller和nuitka。 这2个工具同时都能满足项目的需要: 隐藏源码。这里的pyinstaller是通过设置key来…...
Python解题 - CSDN周赛第28期
上一期周赛问哥因为在路上,无法参加,但还是抽空登上来看了一下题目。4道题都挺简单的,有点遗憾未能参加。不过即使参加了,手速也未必能挤进前十。 本期也是一样,感觉新增的题目都偏数学类,基本用不到所谓的…...
DNS记录类型有哪些,分别代表什么含义?
DNS解析将域名指向IP地址,是互联网中的一项重要服务。而由于业务场景不同,在设置DNS解析时,需要选择不同的记录类型。网站管理人员需要准确了解每一种DNS记录类型所代表的含义和用途,才能满足不同场景的解析需求。本文中科三方简单…...
ICLR 2022—你不应该错过的 10 篇论文(上)
CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 ICLR 2023已经放榜,但是今天我们先来回顾一下去年的ICLR 2022! ICLR 2022将于2022年 4 月 25 日星期一至 4 月 29 日星期五在线举行(连续第三年!…...
HydroD 实用教程(三)环境数据
目 录一、前言二、Location三、Wind Profile四、Directions五、Water5.1 Wave Spectrums5.2 Current Profile5.3 Frequency Set5.4 Phase Set5.5 Wave Height5.6 Regular Wave Set六、参考文献一、前言 SESAM (Super Element Structure Analysis Module)…...
第四章 统计机器学习
机器学习:从数据中学习知识; 原始数据中提取特征;学习映射函数f;通过映射函数f将原始数据映射到语义空间,即寻找数据和任务目标之间的关系; 机器学习: 监督学习:数据有标签&#x…...
Redis第一讲
目录 一、Redis01 1.1 NoSql 1.1.1 NoSql介绍 1.1.2 NoSql起源 1.1.3 NoSql的使用 1.2 常见NoSql数据库介绍 1.3 Redis简介 1.3.1 Redis介绍 1.3.2 Redis数据结构的多样性 1.3.3 Redis应用场景 1.4 Redis安装、配置以及使用 1.4.1 Redis安装的两种方式 1.4.2 Redi…...
Java面试题-消息队列
消息队列 1. 消息队列的使用场景 六字箴言:削峰、异步、解耦 削峰:接口请求在某个时间段内会出现峰值,服务器在达到峰值的情况下会奔溃;通过消息队列将请求进行分流、限流,确保服务器在正常环境下处理请求。异步&am…...
基于离散时间频率增益传感器的P级至M级PMU模型的实现(Matlab代码实现)
👨🎓个人主页:研学社的博客💥💥💞💞欢迎来到本博客❤️❤️💥💥🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密…...
9个相见恨晚的提升办公效率的网站!
推荐9个完全免费的神器网站,每一个都是功能强大,完全免费,良心好用,让你相见恨晚。 1:知犀思维导图 https://www.zhixi.com/ 知犀思维导图是一个完全免费的宝藏在线思维导图工具。它完全免费,界面简洁唯美…...
java的双亲委派模型-附源码分析
1、类加载器 1.1 类加载的概念 要了解双亲委派模型,首先我们需要知道java的类加载器。所谓类加载器就是通过一个类的全限定名来获取描述此类的二进制字节流,然后把这个字节流加载到虚拟机中,获取响应的java.lang.Class类的一个实例。我们把实…...
Docker 笔记
Docker docker pull redis:5.0 docker images [image:57DAAA3E-CC88-454B-B8AC-587E27C9CD3A-85324-0001A93C6707F2A4/93F703D2-5F44-49AB-83C7-05E2E22FB226.png] Docker有点类似于虚拟机 区别大概: docker:启动 Docker 相当于启动宿主操…...
用户认证-cookie和session
无状态&短链接 短链接的概念是指:将原本冗长的URL做一次“包装”,变成一个简洁可读的URL。 什么是短链接-> https://www.cnblogs.com/54chensongxia/p/11673522.html HTTP是一种无状态的协议 短链接:一次请求和一次响应之后&#…...
UUID的弊端以及雪花算法
目录 一、问题 为什么需要分布式全局唯一ID以及分布式ID的业务需求 ID生成规则部分硬性要求 ID号生成系统的可用性要求 二、一般通用方案 (一)UUID (二)数据库自增主键 (三)Redis生成全局id策略 三…...
使用netty+springboot打造的tcp长连接通讯方案
文章目录项目背景正文一、项目架构二、项目模块三、业务流程四、代码详解1.消息队列2.执行类3.客户端五、测试六、源码后记项目背景 最近公司某物联网项目需要使用socket长连接进行消息通讯,捣鼓了一版代码上线,结果BUG不断,本猿寝食难安&am…...
【正点原子FPGA连载】第十章PS SYSMON测量温度电压实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南
1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id692450874670 3)全套实验源码手册视频下载地址: http://www.openedv.com/thread-340252-1-1.html 第十章PS SYSMON…...
AcWing《蓝桥杯集训·每日一题》—— 1460 我在哪?
AcWing《蓝桥杯集训每日一题》—— 1460. 我在哪? 文章目录AcWing《蓝桥杯集训每日一题》—— 1460. 我在哪?一、题目二、解题思路三、代码实现本次博客我是通过Notion软件写的,转md文件可能不太美观,大家可以去我的博客中查看&am…...
AcWing《蓝桥杯集训·每日一题》—— 3729 改变数组元素
AcWing《蓝桥杯集训每日一题》—— 3729. 改变数组元素 文章目录AcWing《蓝桥杯集训每日一题》—— 3729. 改变数组元素一、题目二、解题思路三、代码实现本次博客我是通过Notion软件写的,转md文件可能不太美观,大家可以去我的博客中查看:北天…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...
Bean 作用域有哪些?如何答出技术深度?
导语: Spring 面试绕不开 Bean 的作用域问题,这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开,结合典型面试题及实战场景,帮你厘清重点,打破模板式回答,…...
Python实现简单音频数据压缩与解压算法
Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中,压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言,提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...
