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

【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 {@Overridepublic 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 {@Overridepublic boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {return sourceType.getType().equals(String.class) &&targetType.getType().equals(User.class);}@Overridepublic Set<ConvertiblePair> getConvertibleTypes() {return Collections.singleton(new ConvertiblePair(String.class, User.class));}@Overridepublic Object convert(Object source, TypeDescriptor sourceType, TypeDescriptortargetType) {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 {@Overridepublic Object getObject() throws Exception {UserService userService = new UserService();return userService;}@Overridepublic 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 = newSimpleMetadataReaderFactory();// 构造一个MetadataReaderMetadataReader 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技术。

相关文章:

  • Docker快速安装kafka
  • EM@解三角形@正弦定理@余弦定理
  • 云效流水线docker部署 :node.js镜像部署VUE项目
  • 大数据毕业设计选题推荐-农作物观测站综合监控平台-Hadoop-Spark-Hive
  • Swift编写爬取商品详情页面的爬虫程序
  • MATLAB算法实战应用案例精讲-【目标检测】机器人抓取
  • MATLAB算法实战应用案例精讲-【目标检测】机器视觉-工业相机参数
  • .NET关于 跳过SSL中遇到的问题
  • LeetCode 137. 只出现一次的数字 II 中等
  • 【蓝桥杯选拔赛真题17】C++时间换算 第十二届蓝桥杯青少年创意编程大赛C++编程选拔赛真题解析
  • USB偏好设置-Android13
  • 使用Go语言抓取酒店价格数据的技术实现
  • 人工智能模型转ONNX 连接摄像头使用ONNX格式的模型进行推理
  • 前端自动检查更新,适用Vue任何版本项目,包服务端更后客户端更新
  • 工作学习记录
  • 【391天】每日项目总结系列128(2018.03.03)
  • CentOS学习笔记 - 12. Nginx搭建Centos7.5远程repo
  • GraphQL学习过程应该是这样的
  • JavaScript 基础知识 - 入门篇(一)
  • Linux各目录及每个目录的详细介绍
  • Lsb图片隐写
  • Puppeteer:浏览器控制器
  • python_bomb----数据类型总结
  • python学习笔记 - ThreadLocal
  • Sass 快速入门教程
  • ⭐ Unity 开发bug —— 打包后shader失效或者bug (我这里用Shader做两张图片的合并发现了问题)
  • Vue.js 移动端适配之 vw 解决方案
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • 案例分享〡三拾众筹持续交付开发流程支撑创新业务
  • 从伪并行的 Python 多线程说起
  • 罗辑思维在全链路压测方面的实践和工作笔记
  • 猫头鹰的深夜翻译:JDK9 NotNullOrElse方法
  • 如何解决微信端直接跳WAP端
  • 入门级的git使用指北
  • 通过git安装npm私有模块
  • 微服务入门【系列视频课程】
  • 微信小程序--------语音识别(前端自己也能玩)
  • 看到一个关于网页设计的文章分享过来!大家看看!
  • 仓管云——企业云erp功能有哪些?
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ​学习一下,什么是预包装食品?​
  • $.ajax()
  • (03)光刻——半导体电路的绘制
  • (2)STL算法之元素计数
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (env: Windows,mp,1.06.2308310; lib: 3.2.4) uniapp微信小程序
  • (LeetCode C++)盛最多水的容器
  • (zz)子曾经曰过:先有司,赦小过,举贤才
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • (一)python发送HTTP 请求的两种方式(get和post )
  • (原)Matlab的svmtrain和svmclassify
  • (转)C#调用WebService 基础
  • .NET core 自定义过滤器 Filter 实现webapi RestFul 统一接口数据返回格式
  • .NET 读取 JSON格式的数据
  • .NET 服务 ServiceController