Spring父子容器

news/2024/11/25 15:22:11/

一、痛点

当前开发工程以来的spring-boot-starter脚手架,配置了很多通用的bean,而部分无法满足自身需求,因此需要自定义bean,这时候就有可能出现自己定义bean和脚手架或者引入的第三方依赖中的某个bean冲突,导致出现bean重复的报错问题。

二、解决方案

方法1:自定义bean的名字

给自己定义的bean起个别名,避免和二、三方包里的bean重名

方法2:@ConditionalOnMissingBean

如果在 spring 上下⽂中找不到 GsonBuilder的 bean,这⾥才会配置。如果 上下⽂已经有相同的 bean 类型,那么这⾥就不会进⾏配置
给自己定义的bean起个别名,避免和二、三方包里的bean重名

方法3:父子容器

父子容器的主要用途之一便是是上下文隔离。spring总的上下文容器有父子之分。父容器和子容器。父容器对子容器可见,子容器对父容器不可见。

三、Spring⽗⼦容器上下⽂隔离实战(方法3)

将公共组件包(如 通⽤log、通⽤缓存)等⾥⾯的 Spring 配置信息通通由 ⽗容器进⾏加载。
将当前⼯程上下⽂中的所有 Spring 配置由 ⼦容器进⾏加载。
⽗容器和⼦容器可以存在相同类型的 bean,并且如果⼦容器存在,则会优先使⽤⼦容器的 bean,我们可以将上⾯代码进⾏如下改造:

在⼯程⽬录下创建⼀个 parent 包,并编写 parent ⽗容器的配置类:

@Slf4j
@Configuration
//将 starter 中的 enable 注解放在⽗容器的配置中
@EnableZookeeper
public class ParentSpringConfiguration {
}

⾃定义实现 SpringApplicationBuilder 类

public class ChildSpringApplicationBuilder extends SpringApplicationBuilder {public ChildSpringApplicationBuilder(Class<?>... sources) {super(sources);}public ChildSpringApplicationBuilder functions() {//初始化⽗容器,class类为刚写的⽗配置⽂件 ParentSpringConfigurationGenericApplicationContext parent = new AnnotationConfigApplicationContext(ParentSpringConfiguration.class);this.parent(parent);return this;}
}

主要作⽤是在启动 Springboot ⼦容器时,先根据⽗配置类 ParentSpringConfiguration 初始化⽗ 容器 GenericApplicationContext。
然后当前 SpringApplicationBuilder 上下⽂将 ⽗容器设置为初始化的⽗容器,这样就完成了⽗⼦容器配置。
starter 中的 GsonBuilder 会在⽗容器中进⾏初始化。

启动 Spring 容器:

@Slf4j
//@EnableZookeeper 此注解放到了 ParentConfiguration中。
@SpringBootApplication
public class ChildSpringServer {public static void main(String[] args) {ConfigurableApplicationContext applicationContext = new ChildSpringApplicationBuilder(ChildSpringServer.class).functions().run(args);log.info("applicationContext: {}", applicationContext);}
}

此时,可以正常启动 spring 容器,我们通过 applicationContext.getBean() 的形式获取 ZookeeperClinet。

public static void main(String[] args) {ConfigurableApplicationContext applicationContext = new ChildSpringApplicationBuilder(ChildSpringServer.class).functions().registerShutdownHook(false).run(args);log.info("applicationContext: {}", applicationContext);//当前上下⽂log.info("zk name: {}", applicationContext.getBean(ZookeeperClient.class));//当前上下⽂的⽗容器 getlog.info("parent zk name: {}", applicationContext.getParent().getBean(ZookeeperClient.class));}

⽇志打印:

zk name: ZookeeperClient(name=From Current Project) //来⾃当前⼯程,⼦容器
parent zk name: ZookeeperClient(name=From Starter.) //来⾃⽗容器

可以看到当前上下⽂拿到的 bean 是当前⼯程配置的 bean,然⽽我们还可以获取到 ⽗容器中配置的 bean,通过先 getParent() (注意NPE),
然后再获取bean,则会获取到 ⽗容器中的 bean。


http://www.ppmy.cn/news/139482.html

相关文章

小米联合金山云发布“1KM边缘计算” 携手布局“云+边缘”新赛道

金山云CEO王育林&#xff1a; “今天是一个特别特别特别的发布会&#xff0c;因为小米每次发布会都有硬件&#xff0c;而这次是和我们金山云联合发布“1KM边缘计算”解决方案&#xff0c;打造“云亿级终端”边缘计算模式。当然我们和小米的合作属于厚积薄发&#xff0c;是之前一…

盘点 | 2018年IoT蓄势待发

来源 | 地歌网 文 | 曹亦卿 编辑 | 夏广川 5G前夜&#xff0c;IoT厚积薄发&#xff0c;未来是否已来&#xff1f; 2018年&#xff0c;互联网圈儿大事不断。小米与美团点评高调上市&#xff0c;拼多多与趣头条弯道超车&#xff0c;马云“禅让”推合伙人制&#xff0c;腾讯变革…

MySQL数据库 第0章:每章SQL命令总结

MySQL数据库 第0章&#xff1a;每章SQL命令总结 MySQL数据库 第1章&#xff1a;数据库入门MySQL数据库 第2章&#xff1a;数据库基本操作MySQL数据库 第3章&#xff1a;数据类型与约束MySQL数据库 第4章&#xff1a;数据库设计MySQL数据库 第5章&#xff1a;单表操作MySQL数据库…

近场通信技术

目录标题 学习内容一、三种近场通信技术的特点1、NFCNFC技术的主要特点如下&#xff1a; 2、BlueToothBlueTooth技术的主要特点如下&#xff1a; 3、WIFIWIFI技术的主要特点如下&#xff1a; 4.三种技术比较 二、浅谈未来近场通信技术的应用场景1、NFC2、BlueTooth3、WIFI 学习…

Android近场通信

一&#xff0e;三种近场通信技术 1.类别 &#xff08;1&#xff09;WIFI &#xff08;2&#xff09;BlueTooth &#xff08;3&#xff09;NFC 2.三大技术的特点 &#xff08;1&#xff09;WIFI ​ WiFi(Wireless Fidelity&#xff0c;无线保真技术)即IEEE 802&#xff0e;11协…

典型三种近场通信的特点以及未来趋势

近场通信 三种近场通信技术的特点1、WIFI2、蓝牙3、NFC 未来近场通信技术的应用场景进行分析与预测1、WIFI2、蓝牙3、NFC 三种近场通信技术的特点 ​ 在通信和信息技术的不断发展&#xff0c;近距离的无线通信技术只要通信收发双方通过无线电波传输信息且传输距离限制在较短范…

关于数据中心的设计方案,数据中心网络规划设计

IDC网络解决方案有哪些 对于只有基本要求的数据中心&#xff0c;网络结构可采用三层系统结构。 第一层&#xff0c;Intenet连接层的设备具有以下的特点&#xff1a;高速的路由交换能力&#xff0c;该设备提供Gps一级的系统容量&#xff0c;实现访问请求和内容流量在IDC和多个…

几种短距离无线通信技术及未来展望

目录 一、三种近场通信技术的特点 1、WIFI ​简要介绍 主要技术特点 2、蓝牙 蓝牙技术介绍 主要技术特点 3、NFC ​简要介绍 技术特点 二、未来近场通信技术的应用场景进行分析与预测 1、WIFI 2、蓝牙 3、NFC 一、三种近场通信技术的特点 在通信和信息技术…