【Spring之底层核心架构概念解析】

文章目录

  • 一、BeanDefinition
  • 二、BeanDefinitionReader
    • 2.1、AnnotatedBeanDefinitionReader
    • 2.2、XmlBeanDefinitionReader
  • 五、ClassPathBeanDefinitionScanner
  • 六、BeanFactory
  • 七、ApplicationContext
    • 7.1、AnnotationConfigApplicationContext
    • 7.2、ClassPathXmlApplicationContext
  • 八、类型转换
    • 8.1、PropertyEditor
    • 8.2、ConversionService
    • 8.3、TypeConverter
  • 九、FactoryBean
  • 十、ExcludeFilter和IncludeFilter
  • 十一、MetadataReader、ClassMetadata、AnnotationMetadata

前置准备测试对象User:


public class User {

    public User(int flag, String uuid){
        System.out.println(flag+"----------"+uuid);
    }

    public User(){
        System.out.println("User 无参构造");
    }

}

一、BeanDefinition

BeanDefinition表示Bean的定义,其可记录Bean的特征,例如:

  1. Bean的类型:beanClass属性
  2. Bean的作用域:Scope属性
  3. Bean是否为懒加载:lazyinit属性

在Spring中,定义一个bean的方式主要有:XML文件中使用bean标签来定义其bean属性,除此外,可以使用@Bean注解以及@Component等注解来定义注解,当然,也可以使用编程式来定义Bean,如下代码:

//Spring核心概念测试类
public class TestSpringDemo {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);


        //定义一个BeanDefinition对象
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
        //向BeanDefinition对象中添加对象信息
        beanDefinition.setBeanClass(User.class);
        beanDefinition.setScope("prototype");
        //将BeanDefinition对象加入到Spring容器中
        context.registerBeanDefinition("user",beanDefinition);

        System.out.println("Spring BeanDefinition 创建的user对象为:"+context.getBean("user"));

        UserService userService = (UserService) context.getBean("userService");
        userService.test();
    }
}

在这里插入图片描述

二、BeanDefinitionReader

其表示BeanDefinition读取器,主要的读取方式有以下两种

2.1、AnnotatedBeanDefinitionReader

这个组件可以将某各类直接转换为BeanDefinition,并且会解析该类上的注解,测试代码如下:

//Spring核心概念测试类
public class TestSpringDemo {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        //声明一个BeanDefinition读取器,并在这个读取器中传入Spring容器
        AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(context);

        annotatedBeanDefinitionReader.register(User.class);
        System.out.println("BeanDefinition读取器AnnotatedBeanDefinitionReader创建bean为:"+context.getBean("user"));

        UserService userService = (UserService) context.getBean("userService");
        userService.test();
    }
}

在这里插入图片描述

2.2、XmlBeanDefinitionReader

该接口主要是通过解析XML文件中的Bean标签进行BeanDefinition转换,代码如下:

XML配置文件信息:
在这里插入图片描述

//Spring核心概念测试类
public class TestSpringDemo {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        //声明一个BeanDefinition读取器,并在这个读取器中传入Spring容器
        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(context);

        int i = xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");
        System.out.println("扫描到bean标签数量:"+i);
        System.out.println("BeanDefinition读取器XmlBeanDefinitionReader创建bean为:"+context.getBean("user"));

        UserService userService = (UserService) context.getBean("userService");
        userService.test();
    }
}

在这里插入图片描述

五、ClassPathBeanDefinitionScanner

其为BeanDefinition资源扫描器,作用和BeanDefinitionReader类似,只是读取的方式是以指定路径的方式扫描类资源,对扫描到的类进行解析,是否包含其相关注解信息,例:如果类中包含@Component注解,就会将该类作为BeanDefinition对象放入到Spring容器中,代码如下:

@Component
public class UserService {
    public void test(){
        System.out.println("test--->Spring创建对象");
    }
}
//Spring核心概念测试类
public class TestSpringDemo {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.refresh();
        //声明一个BeanDefinition读取器,并在这个读取器中传入Spring容器
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);

        int scan = scanner.scan("com.practice.service");
        System.out.println("指定路径下,扫描到的bean资源数量:"+scan);
        System.out.println("ClassPathBeanDefinitionScanner扫描器创建bean为:"+context.getBean("userService"));

    }
}

在这里插入图片描述

六、BeanFactory

BeanFactory会负责创建Bean,并且提供获取Bean的API

七、ApplicationContext

ApplicationContext是BeanFactory的一种,其在Spring的源码中的定义为:
在这里插入图片描述

图中的ListableBeanFactory和HierarchicalBeanFactory都继承至BeanFactory,所以ApplicationContext也是具备BeanFactory具备的特性和功能,但是,ApplicationContext还具备额外的功能,例如,支持国际化、支持获取环境信息、支持事件发布和相关资源加载,其有两个实现类,如下介绍

7.1、AnnotationConfigApplicationContext

其源代码如下:
在这里插入图片描述

AnnotationConfigApplicationContext继承了GenericApplicationContext,实现了AnnotationConfigRegistry接口,拥有了其父类以及父接口以及父接口继承甚至更向上的接口所有的功能

7.2、ClassPathXmlApplicationContext

在这里插入图片描述
其是继承了AbstractApplicationContext,但是相对于AnnotationConfigApplicationContext而言,功能没有AnnotationConfigApplicationContext强大,比如不能注册BeanDefinition

八、类型转换

在Spring中,有可能会存在一些类型转换的问题,其Spring中提供了一些技术来方便做类型转换操作,在Spring源码中,与存在许多类型转换的操作,类型转化主要有以下接口

8.1、PropertyEditor

这是JDK自带的类型转换工具类,具体使用如下:

public class StringToUserPropertyEditor extends PropertyEditorSupport implements PropertyEditor {
    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        User user = new User();
        user.setName(text);
        this.setValue(user);
    }
}
//Spring核心概念测试类
public class TestSpringDemo {
    public static void main(String[] args) {

        StringToUserPropertyEditor propertyEditor = new StringToUserPropertyEditor();
        propertyEditor.setAsText("1");
        User value = (User) propertyEditor.getValue();
        System.out.println(value);
    }
}

在这里插入图片描述

8.2、ConversionService

Spring中提供的类型转化服务,它比PropertyEditor更强大,其代码如下:

public class StringToUserConverter implements ConditionalGenericConverter {
    @Override
    public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
        return sourceType.getType().equals(String.class) &&
                targetType.getType().equals(User.class);
    }
    @Override
    public Set<ConvertiblePair> getConvertibleTypes() {
        return Collections.singleton(new ConvertiblePair(String.class, User.class));
    }
    @Override
    public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor
            targetType) {
        User user = new User();
        user.setName((String)source);
        return user;
    }
}
//Spring核心概念测试类
public class TestSpringDemo {
    public static void main(String[] args) {

        DefaultConversionService conversionService = new DefaultConversionService();
        conversionService.addConverter(new StringToUserConverter());
        User value = conversionService.convert("1", User.class);
        System.out.println(value);

    }
}

在这里插入图片描述

8.3、TypeConverter

整合了PropertyEditor和ConversionService的功能,是Spring内部用的,如下:

//Spring核心概念测试类
public class TestSpringDemo {
    public static void main(String[] args) {

        SimpleTypeConverter typeConverter = new SimpleTypeConverter();
        typeConverter.registerCustomEditor(User.class, new StringToUserPropertyEditor());
        User value = typeConverter.convertIfNecessary("1", User.class);
        System.out.println(value);

    }
}

在这里插入图片描述

九、FactoryBean

我们想一个Bean完完全全由我们来创造,可以通过FactoryBean来完成,如下:

public class factoryBeanTest implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
        UserService userService = new UserService();
        return userService;
    }
    @Override
    public Class<?> getObjectType() {
        return UserService.class;
    }

}

通过上面这段代码,我们自己创造了一个UserService对象,并且它将成为Bean。但是通过这种方式创造出来的UserService的Bean,只会经过初始化后,其他Spring的生命周期步骤是不会经过的,比如依赖注入

十、ExcludeFilter和IncludeFilter

这两个Filter是Spring扫描过程中用来过滤的。ExcludeFilter表示排除过滤器,IncludeFilter表示包含过滤器,如下:
在这里插入图片描述

在这里插入图片描述
FilterType分为:
1. ANNOTATION:表示是否包含某个注解
2. ASSIGNABLE_TYPE:表示是否是某个类
3. ASPECTJ:表示否是符合某个Aspectj表达式
4. REGEX:表示是否符合某个正则表达式
5. CUSTOM:自定义

十一、MetadataReader、ClassMetadata、AnnotationMetadata

在Spring中需要去解析类的信息,比如类名、类中的方法、类上的注解,这些都可以称之为类的元数据,所以Spring中对类的元数据做了抽象,并提供了一些工具类
MetadataReader表示类的元数据读取器,默认实现类为SimpleMetadataReader。代码如下示例:

package com.practice.service;

import org.springframework.stereotype.Component;

@Component
public class UserService {
    public void test(){
        System.out.println("test--->Spring创建对象");
    }
}

//Spring核心概念测试类
public class TestSpringDemo {
    public static void main(String[] args) throws IOException {

        SimpleMetadataReaderFactory simpleMetadataReaderFactory = new
                SimpleMetadataReaderFactory();
        // 构造一个MetadataReader
        MetadataReader metadataReader =
                simpleMetadataReaderFactory.getMetadataReader("com.practice.service.UserService");
        // 得到一个ClassMetadata,并获取了类名
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        System.out.println(classMetadata.getClassName());
        // 获取一个AnnotationMetadata,并获取类上的注解信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        for (String annotationType : annotationMetadata.getAnnotationTypes()) {
            System.out.println(annotationType);
        }
    }
}

在这里插入图片描述
注:SimpleMetadataReader去解析类时,使用的ASM技术。因为Spring启动的时候需要去扫描,如果指定的包路径比较宽泛,那么扫描的类是非常多的,那如果在Spring启动时就把这些类全部加载进JVM了,这样不太好,所以使用了ASM技术。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

E云管家个微协议框架--新版本的利器

在互联网时代&#xff0c;高效、可靠的互联网协议对于实现稳定、安全的数据传输至关重要。E云管家作为一项创新性的IPAD协议构建工具&#xff0c;基于IPAD8.0.37协议为开发者提供了强大而灵活的功能&#xff0c;使他们能够轻松构建高效的通信协议。本文将介绍E云管家的主要特点…

python3.8及以上版本绑定gdal库的一个注意事项

作者&#xff1a;朱金灿 来源&#xff1a;clever101的专栏 为什么大多数人学不会人工智能编程&#xff1f;>>> gdal和python绑定参考文章&#xff1a;windows环境下python和gdal绑定方法   值得注意的是绑定python3.8及以上版本后在python程序中初始化gdal库时会出…

“三门问题”解决方案:换不换?更换策略与贝叶斯策略?附 Java 验证代码

文章目录 前言一、什么是“三门问题”&#xff1f;二、“三门问题”解决策略详解2.1、错误策略&#xff1a;直觉策略与随机策略2.2、更换策略与事件分析计算2.3、贝叶斯策略及分析流程 三、Java 语言验证“三门问题”总结 前言 “三门问题”作为一道经典逻辑推理题&#xff0c;…

【Linux】Linux常用命令—用户管理

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

《QT从基础到进阶·二十》QThreadPool线程池的使用

什么情况下比较适合用线程池&#xff1f; 比如我有上百个任务要同时处理&#xff0c;难道开上百个线程&#xff1f;NO&#xff01;&#xff01;&#xff01; 有了线程池的加持&#xff0c;自动给任务分配线程处理&#xff0c; 多线程不再是真爱~ 线程池创建&#xff1a; 1、自…

【带头学C++】----- 四、动态内存空间申请 ---- 4.1 动态内存分配

1.动态内存分配概述 在C和C等语言中&#xff0c;可以使用malloc、calloc、realloc或使用new等函数来动态分配内存空间&#xff0c;同时使用free、delete函数释放动态分配的内存空间&#xff0c;这样可以根据程序的实际需要动态管理内存&#xff0c;避免静态内存分配的局限性。 …

微信超实用的小功能

微信真的有超多实用小功能 平时很少注意到&#xff0c;每次都用传统的方法解决&#xff0c;浪费人家研发人员的一片苦心~ 1重要事项提醒&#xff1a;健忘症的福音&#xff1b; 步骤&#xff1a;长按消息-提醒-设置。 2 图片翻译&#xff1a;不用跳转翻译软件&#xff0c;一键翻…

什么是自动化测试框架?我们该如何搭建自动化测试框架?

无论是在自动化测试实践&#xff0c;还是日常交流中&#xff0c;经常听到一个词&#xff1a;框架。之前学习自动化测试的过程中&#xff0c;一直对“框架”这个词知其然不知其所以然。 最近看了很多自动化相关的资料&#xff0c;加上自己的一些实践&#xff0c;算是对“框架”…

数据分析-numpy

numpy numpy numpy简介优点下载ndarray的属性输出数据类型routines 函数ndarray对象的读写操作ndarray的级联和切分级联切分 ndarray的基本运算广播机制&#xff08;Broadcast&#xff09;ndarry的聚合操作数组元素的操作numpy 数学函数numpy 查找和排序 写在最后面 简介 nump…

js 变量声明与赋值 笔试踩坑题

文章目录 概述函数声明函数形参与实参函数预编译用一个例子说明一下&#xff0c;这四个步骤分别要干些什么。重复四个步骤&#xff0c;反复练习一下 全局编译多重执行期上下文 概述 别小看变量声明与赋值&#xff0c;在所有的笔试中&#xff0c;基本都会考&#xff0c;这个要多…

LeetCode刷题总结(一)

文章目录 前言题型排序问题动态规划 前言 本文把刷题过程中的总结记下来&#xff0c;方便未来回顾的时候继续拓展。 题型 排序问题 排序问题的解决方法有很多。对于简单算法来说&#xff0c;最重要的是记住思路&#xff1b;对于高级算法来说&#xff0c;最重要的是记住细节…

asp.net core weapi 结合identity完成登录注册

1.安装所需要的nuget包 <PackageReference Include"Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version"6.0.24" /><PackageReference Include"Microsoft.EntityFrameworkCore" Version"6.0.24" /><PackageR…

工作利器!熟悉这几款数据流图工具,事半功倍!

数据流图工具在现代工作中起到了非常重要的作用。无论是在企业内部的流程优化&#xff0c;还是在软件开发、项目管理、系统设计等领域&#xff0c;数据流图工具都扮演着关键的角色。本文将为大家介绍8款高效的数据流图工具&#xff0c;帮助大家选择适合自己工作需求的工具。 1.…

创建Springboot工程

前期准备 查看是否安装Java;javac命令是否可用; java -version javac 都安装好之后可以进行创建。 步骤 此处我是使用IntelliJ IDEA 进行创建 打开新建项目–选择Spring Initializr 服务器URL&#xff1a;可以使用默认 &#xff0c; 如果感觉太慢可以选择 http://start.a…

原厂监视综合控制继电器 ZZS-7/1 AC220V 凸出端子固定安装

ZZS-7/11分闸、合闸、电源监视综合控制装置&#xff1b; ZZS-7/12分闸、合闸、电源监视综合控制装置&#xff1b; ZZS-7/13分闸、合闸、电源监视综合控制装置&#xff1b; ZZS-7/14分闸、合闸、电源监视综合控制装置&#xff1b; ZZS-7/102分闸、合闸、电源监视综合控制装置…

基于51单片机的万年历-脉搏计仿真及源程序

一、系统方案 1、本设计采用51单片机作为主控器。 2、DS1302采集年月日时分秒送到液晶1602显示。 3、按键年月日时分秒&#xff0c;心率报警上下限。 4、红外对接管传感器采集心率送到液晶1602显示。 5、心率低于下限或高于上限&#xff0c;蜂鸣器报警。 二、硬件设计 原理图如…

vue+nodejs商城实战项目【登录 + 购物车 + 支付】

从零开始一个前端项目并将其完成需要经历一系列步骤。以下是一个常见的开发流程&#xff0c;可以帮助规划和管理项目&#xff1a; 需求分析和规划&#xff1a; 确定项目的目标和范围。定义用户需求和功能要求。制定项目计划和时间表。 技术选型&#xff1a; 选择适当的前端技术…

4面百度软件测试工程师的面试经验总结

没有绝对的天才&#xff0c;只有持续不断的付出。对于我们每一个平凡人来说&#xff0c;改变命运只能依靠努力幸运&#xff0c;但如果你不够幸运&#xff0c;那就只能拉高努力的占比。 2023年7月&#xff0c;我有幸成为了百度的一名测试工程师&#xff0c;从外包辞职了历经100…

Java ClassNotFoundException异常解决指南

Java ClassNotFoundException异常解决指南 《Java ClassNotFoundException异常解决指南》摘要引言了解ClassNotFoundException异常的本质异常的起因表情小贴士 &#x1f61f; 异常的处理常见引发ClassNotFoundException的情况1. **类路径配置错误**2. **依赖关系错误**3. **动态…

评估 RAG 的神器来啦!TruLens + Milvus=?

大型语言模型&#xff08;LLM&#xff09;的日益普及引爆了向量数据库赛道&#xff0c;向量搜索技术也越发受到开发者关注。目前&#xff0c;主流的向量搜索技术提供者包括向量数据库 Milvus 和 Zilliz Cloud&#xff0c;向量搜索库 FAISS&#xff0c;以及与传统数据库集成的向…