【框架源码】Spring源码底层IOC容器加入对象的方式

news2024/10/7 20:29:26

1.Spring容器加入对象方式简介

  • 使用XML配置文件
    • 在XML配置文件中使用< bean >标签来定义Bean,通过ClassPathXmlApplicationContext等容器来加载并初始化Bean。
  • 使用注解
    • 使用Spring提供的注解,例如@Component、@Service、@Controller、@Repository等注解来标识Bean
    • 然后通过@ComponentScan等注解扫描器来加载并初始化Bean。
  • 使用Java配置
    • 可以使用Java代码来配置Bean,例如使用@Configuration和@Bean注解来定义Bean
    • 然后通过AnnotationConfigApplicationContext等容器来加载并初始化Bean。
  • 使用Import注解
    • 使用@Import注解来引入其他配置类,然后通过容器加载并初始化Bean
    • @Import注解提供了三种用法
      • 直接Import导入
      • ImportSelector接口批量
      • ImportBeanDefinitionRegistrar条件注册

2.import注解导入Bean实操

(1)import注解简介

  • import注解是Spring框架中的一个注解,用于在一个配置类中引入其他配置类或者普通的Java类
  • 通过@Import注解,可以将其他配置类或者Java类中定义的Bean引入到当前配置类中
  • 默认的bean名称是【类全限定名,即包名+类名】

(2)import注解源码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
  Class<?>[] value();
}

(3)import案例实战

  • 创建汽车相关的接口以及类实体Bean
//汽车接口
public interface Car {
}

//奔驰类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BenChiCar implements Car{
    private String name = "奔驰汽车";
}

//宝马类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BaoMaCar implements Car{
    private String name = "宝马汽车";
}

//奥迪类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AoDiCar implements Car{
    private String name = "奥迪汽车";
}
  • 创建配置类Manager
@Configuration
@Import(value = {BaoMaCar.class, AoDiCar.class, BenChiCar.class})
public class CarBeanManager {
}
  • 主类测试
public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        //扫描指定的包,包括子包
        context.scan("com.lixiang");
        //里面完成初始化操作,核心方法
        context.refresh();
        Map<String, Car> beansOfType = context.getBeansOfType(Car.class);
        beansOfType.forEach((k,v)-> System.out.println(k+"="+v));
    }
}

在这里插入图片描述

3.ImportSelector批量导入Bean实操

(1)importSelector批量导入简介

  • ImportSelector 接口用于实现动态注册Bean的功能,【批量】导入对象到容器里,根据条件动态地选择需要注册的Bean,并加入Spring容器

  • 实现ImportSelector接口,这个接口的selectImports方法会返回一个String数组,数组中的值就是要添加的组件的全类名

(2)importSelector源码

public interface ImportSelector {
  //该方法的返回值是一个String数组,用于指定需要注册的Bean的类名。
  String[] selectImports(AnnotationMetadata importingClassMetadata);

  @Nullable
  default Predicate<String> getExclusionFilter() {
    return null;
  }
}

(3)案例实战

  • 我们还是用Car这几个实体Bean,批量导入到Spring容器,自定义选择器实现ImportSelector接口。
public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[] {"com.lixiang.domain.AoDiCar","com.lixiang.domain.BaoMaCar","com.lixiang.domain.BenChiCar"};
    }
}
  • 在我们的Manager中修改import值
@Configuration
//只需要引入MyImportSelector即可
@Import(value = {MyImportSelector.class})
public class CarBeanManager {
}
  • 主类测试
public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        //扫描指定的包,包括子包
        context.scan("com.lixiang");
        //里面完成初始化操作,核心方法
        context.refresh();
        Map<String, Car> beansOfType = context.getBeansOfType(Car.class);
        beansOfType.forEach((k,v)-> System.out.println(k+"="+v));
    }
}

在这里插入图片描述

4.BeanDefinitionRegistrar动态注册Bean实操

(1)ImportBeanDefinitionRegistrar接口简介

  • ImportBeanDefinitionRegistrar是Spring框架中的一个接口,用于实现动态注册Bean的功能
  • ImportBeanDefinitionRegistrar可以在运行时动态地向Spring容器中注册BeanDefinition
  • 与ImportSelector不同的是,ImportSelector只能返回需要注册的Bean的类名
  • 在使用@Import注解时,将实现ImportBeanDefinitionRegistrar接口的类引入到当前配置类中,实现动态注册Bean的功能

(2)ImportBeanDefinitionRegistrar源码

public interface ImportBeanDefinitionRegistrar {

  /**
    * @param importBeanNameGenerator 
    * @param annotationMetadata 当前类的注解相关信息
    * @param registry IOC容器里面bean的注册信息
    */
  default void registerBeanDefinitions(
    AnnotationMetadata importingClassMetadata, 
    BeanDefinitionRegistry registry,
    BeanNameGenerator importBeanNameGenerator) {

    registerBeanDefinitions(importingClassMetadata, registry);
  }

  /**
    * @param annotationMetadata 当前类的注解相关信息
    * @param registry IOC容器里面bean的注册信息
    */
  default void registerBeanDefinitions(
    AnnotationMetadata importingClassMetadata, 
    BeanDefinitionRegistry registry) {
  }

}

(3)案例实战

  • 现在我们有一个场景,当宝马汽车、奥迪汽车、奔驰汽车都存在时,新创建一个新能源汽车
  • 创建新能源汽车主类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class NewEnergyCar implements Car{
    private String name = "新能源汽车";
}
  • 创建自定义的ImportBeanDefinitionRegistrar
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        /**
         * 可以通过该方法进行手动注册
         */
        boolean adCar = beanDefinitionRegistry.containsBeanDefinition("com.lixiang.domain.AoDiCar");
        boolean bmCar = beanDefinitionRegistry.containsBeanDefinition("com.lixiang.domain.BaoMaCar");
        boolean bcCar = beanDefinitionRegistry.containsBeanDefinition("com.lixiang.domain.BenChiCar");

        if (adCar && bmCar && bcCar){
            //IOC容器加个混合对象
            BeanDefinition beanDefinition = new RootBeanDefinition(NewEnergyCar.class);
            beanDefinitionRegistry.registerBeanDefinition("newEnergyCar",beanDefinition);
        }
    }
}
  • 配置Manager中import的值
@Configuration
@Import(value = {MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
public class CarBeanManager {
}
  • 主类测试
public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        //扫描指定的包,包括子包
        context.scan("com.lixiang");
        //里面完成初始化操作,核心方法
        context.refresh();
        Map<String, Car> beansOfType = context.getBeansOfType(Car.class);
        beansOfType.forEach((k,v)-> System.out.println(k+"="+v));
    }
}

在这里插入图片描述在这里插入图片描述在这里插入图片描述

在这里插入图片描述

(4)BeanDefinition 介绍

  • Spring容器中最重要的概念之一,它是容器创建和管理Bean实例的基础,对Bean的定义信息的抽象和封装
  • 描述一个Bean的定义信息,包括Bean的名称、类型、作用域、属性等信息
  • 可以对Bean的创建和管理进行详细的配置和控制,例如可以指定Bean的作用域、是否懒加载、是否自动注入等属性
    在这里插入图片描述

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

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

相关文章

一篇带你看懂什么是DesignOps(设计运营管理)

“好设计就是好生意”(Good design is good business) ----IBM创始人Thomas J. Watson早在20世纪50年代&#xff0c;IBM就开始关注好设计。IBM创始人Thomas J. Watson认为好的设计能很大程度提高产品的质量、功能和美观度&#xff0c;吸引更多的消费者和客户&#xff0c;增加销…

工程监测无线中继采集仪的寄存器(参数)汇总详解

工程监测无线中继采集仪的寄存器&#xff08;参数&#xff09;汇总详解 一、 寄存器&#xff08;参数&#xff09;汇总 无线中继采集发送仪有很多参数&#xff08;寄存器&#xff09;&#xff0c;对于一些简单的应用&#xff0c;用户无需关心这些参数&#xff0c;使用默认参数值…

【GPT-4理论篇-1】GPT-4核心技术探秘 | 京东云技术团队

前言 GPT-4已经发布有一段时间了&#xff0c;但是出于安全性等各种原因&#xff0c;OpenAI并没有公布GPT-4的技术细节和代码&#xff0c;而是仅仅给出了一个长达100页的技术报告[1]。 这个技术报告着重介绍了GPT-4的强大之处&#xff0c;仅仅给出了几个技术方向的概括&#x…

《汇编语言》- 读书笔记 - 实验

《汇编语言》- 读书笔记 - 实验 实验 1 查看 CPU 和内存&#xff0c;用机器指令和汇编指令编程1. 预备知识: Debug 的使用r 修改或显示寄存器的值d 查看内存数据e 编辑内存中指定地址的内容u 显示代码t 单步执行一条指令a 写入汇编指令g 执行到指定位置n 指定文件名L 加载文件W…

可视化大屏就是“面子工程”?那是你压根不了解大屏的真正功能

我经常收到这样的私信“企业投入可视化大屏有必要吗&#xff1f;有什么好处呢&#xff1f;”我想说在当前数据时代&#xff0c;企业提高自身竞争力多在这方面下功夫是有必要的。说“没用”的人&#xff0c;都是大屏做的失败的人群&#xff0c;其实“面子”作用确实有&#xff0…

HTTP的协议格式与Fiddler的应用

HTTP的协议格式与Fiddler的应用 &#x1f50e;HTTP协议是什么&#x1f50e;HTTP协议的工作过程&#x1f50e;HTTP的协议格式Fiddler 的应用抓包工具原理协议格式总结 &#x1f50e;结尾 &#x1f50e;HTTP协议是什么 HTTP(超文本传输协议)是一种应用非常广泛的应用层协议 对于…

栈和队列OJ题:LeetCode--20.有效的括号

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;今天给大家带来的是LeetCode--20.有效的括号 数 据 结 构 专 栏&#xff1a;数据结构 个 人 主 页 &#xff1a;stackY、 LeetCode 专 栏 &#xff1a;LeetCode刷题训练营 LeetCode--20.有效的括号&#xff1a;htt…

TypeError Object of type int64 is not JSON serializable

TypeError: Object of type int64 is not JSON serializable debug解析&#xff0c;在正常处理数据过程中&#xff0c;把模型预测结果&#xff0c;其他结构化数据转为str保存时&#xff0c;常常用到 json.dumps()&#xff0c;报错内容如标题所示。 原因&#xff1a;json.dump…

Vue图片处理解决方案,一篇就够了

文章目录 一、阅读须知二、解决的问题三、知识储备四、解决方案五、核心代码六、参考资料七、FileReader()对象八、Exif库使用九、Canvas画布十、动态创建标签并添加绑定事件十一、utils方法十二、vue中图片预览十三、工具网站 一、阅读须知 小帅爆肝整理的这篇文章&#xff0c…

华为OD机试真题 Java 实现【异常的打卡记录】【2023Q1 100分】

一、题目描述 考勤记录是分析和考核职工工作时间利用情况的原始依据&#xff0c;也是计算职工工资的原始依据。 为了正确地计算职工工资和监督工资基金使用情况&#xff0c;公司决定对员工的收集打卡记录进行异常排查。 如果出现以下两种情况&#xff0c;则认为打卡异常&…

持续引领 | 通付盾入选数说安全《2023年中国网络安全市场全景图》!

5月16日&#xff0c;数说安全正式发布《2023年中国网络安全市场全景图》&#xff08;以下简称全景图&#xff09;&#xff0c;这是自2018年开始&#xff0c;数说安全发布的第六版全景图。 其中&#xff0c;通付盾入选自动化攻击防护&#xff08;Anti-Bot&#xff09;、移动应用…

【软件工程】面向对象开发全面总结

文章目录 前言一、引言二、面向对象开发的含义三、面向对象开发的原则1. 封装原则2. 继承原则3. 多态原则4. 抽象原则5. 接口隔离原则6. 依赖倒置原则 四、面向对象开发的基本原则1. 单一职责原则2. 开放封闭原则3. 里氏替换原则 五、面向对象开发的方法1. 面向对象分析&#x…

阿里云服务器安装MySQL的具体步骤

1.首先打开阿里云&#xff0c;找到自己对于的公网ip 2.这里我使用MobaXterm的远程连接工具&#xff0c;这个工具还是很不错的耶&#xff0c;就是复制上图的公网ip地址 3.填写完成之后&#xff0c;会让你输入你阿里云服务端登入的密码&#xff0c;也就是你阿里云重置实例的密码&…

深度学习的十条调参经验

目录 法则一:调参、模型和数据 1、调参是锦上添花的事 2、模型 3、数据

富文本编辑器 kindeditor 使用整理

kindeditor富文本编辑器忘记什么时候添加到项目中了&#xff0c;最近做一个功能需要在原有编辑器上自定义添加一些固定内容&#xff0c;于是对着编辑器文档研究了一番&#xff0c;在这里做一个使用方式整理。 1.下载kindeditor 下载地址如下&#xff1a; https://github.com/…

视频平台。。。。 。

1.py 读取图片视频流 from flask import Flask from flask import render_template import os images_path_list[‘D:\imgs\’filename for filename in os.listdir(‘D:\imgs\’) if filename.endswith(‘.jpg’)] print(images_path_list) def return_img_stream(img_local_p…

城市内涝监测预警系统解决方案

一、方案背景 城市化进程的逐渐加快&#xff0c;城市内人口大量增多&#xff0c;交通运输压力增大&#xff0c;城市建设越来越密集&#xff0c;道路铺建面积越来越多&#xff0c;城市化的发展改变了城市区域的地表环境&#xff0c;致使城市雨水不能像农村或是古代雨水那样&…

JVM调优神器,运用 Arthas 释放 Java应用性能的全部潜力

Arthas、jstack、jstat 和 jmap 都是 Java 调优工具&#xff0c;但它们之间有以下区别&#xff1a; Arthas 是一款全新的 Java 诊断与调试工具&#xff0c;不仅可以执行传统的 JVM 监控命令&#xff0c;还提供了许多其他高级特性&#xff0c;如实时监控、动态修改代码、反编译…

什么是容器

什么是容器 一&#xff1a;概念二&#xff1a;容器API类图2.1 Collection2.2 Set2.3 List2.4 Map 三&#xff1a;详细解释3.1 Collection接口3.1.1 Collection用法 3.2 Iterator接口3.3 List接口3.4 Comparable接口 四&#xff1a;如何选择数据结构4.1 衡量标准&#xff1a;读的…

CRM系统本地部署和云部署的优缺点

众所周知&#xff0c;CRM系统部署方式有两种&#xff0c;分别是本地部署和云部署。两者各有优缺点&#xff0c;企业可以按照自身的需求来进行选择。下面说说CRM不同部署方式的优缺点。 CRM本地部署 本地部署是指将CRM系统安装在企业自己的服务器上&#xff0c;并由企业自行维…