Spring 框架之IOC容器加载重要组件

1.读取配置
如果配置了这样的Bean:在这里插入图片描述
或者在这里插入图片描述
或者在这里插入图片描述
这些是不同定义bean的方式, 他们最终都会生成bean。 那Spring为了生成bean代码复用,使用统一的创建流程,所以通过多态方式读取不同的配置会有不同的读取器,读取完后后续创建bean的流程是通用的。
不同的spring容器会使用不同的读取器:

  1. AnnotationConfigApplicationContext-AnnotatedBeanDefinitionReader
  2. ClassPathXmlApplicationContext-XmlBeanDefinitionReader
    1.读取器:BeanDefinitionReader
    接下来,我们来介绍几种在Spring源码中所提供的BeanDefinition读取器(BeanDefinitionReader),这些BeanDefinitionReader在我们使用Spring时用得少,但在Spring源码中用得多,相当于Spring源码的基础设施。
    AnnotatedBeanDefinitionReader
    可以直接把某个类转换为BeanDefinition,并且会解析该类上的注解,比如在这里插入图片描述
    注意:它能解析的注解是:@Conditional,@Scope、@Lazy、@Primary、@DependsOn、@Role、@Description
    XmlBeanDefinitionReader
    可以解析标签
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);12XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(context); 3int i = xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml"); 45System.out.println(context.getBean("user")); 

2. 扫描器ClassPathBeanDefinitionScanner
ClassPathBeanDefinitionScanner是扫描器,但是它的作用和BeanDefinitionReader类似,它可以进行扫描,扫描某个包路径,对扫描到的类进行解析,比如,扫描到的类上如果存在@Component注解,
那么就会把这个类解析为一个BeanDefinition,比如:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.refresh();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.scan(“com.xs”);
System.out.println(context.getBean(“userService”));
3.注册BeanDefinition
Spring为了使用通用的创建bean流程, 不同的配置最终会成为通用的对象:BeanDefinition
BeanDefinition表示Bean定义,BeanDefinition中存在很多属性用来描述一个Bean的特点。比如:
class,表示Bean类型
scope,表示Bean作用域,单例或原型等
lazyInit:表示Bean是否是懒加载
initMethodName:表示Bean初始化时要执行的方法
destroyMethodName:表示Bean销毁时要执行的方法
还有很多…
在Spring中,我们经常会通过以下几种方式来定义Bean:

@Bean
@Component(@Service,@Controller)
这些,我们可以称之申明式定义Bean。
我们还可以编程式定义Bean,那就是直接通过BeanDefinition,比如:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
/ 生成一个BeanDefinition对象,并设置beanClass为User.class,并注册到ApplicationContext中
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(User.class);
context.registerBeanDefinition(“user”, beanDefinition);
System.out.println(context.getBean(“user”));
我们还可以通过BeanDefinition设置一个Bean的其他属性;
在这里插入图片描述
和申明式事务、编程式事务类似,通过,@Bean,@Component等申明式方式所定义的Bean,最终都会被Spring解析为对应的BeanDefinition对象,并放入Spring容器中。
MetadataReader、ClassMetadata、AnnotationMetadata
在Spring中需要去解析类的信息,比如类名、类中的方法、类上的注解,这些都可以称之为类的元数据,所以Spring中对类的元数据做了抽象,并提供了一些工具类。
MetadataReader表示类的元数据读取器,默认实现类为SimpleMetadataReader。比如:


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

需要注意的是,SimpleMetadataReader去解析类时,使用的ASM技术。
为什么要使用ASM技术,Spring启动的时候需要去扫描,如果指定的包路径比较宽泛,那么扫描的类是非常多的,那如果在Spring启动时就把这些类全部加载进JVM了,这样不太好,所以使用了ASM技术。
4. BeanFactory
BeanFactory表示Bean工厂,所以很明显,BeanFactory会负责创建Bean,并且提供获取Bean的API。
而ApplicationContext是BeanFactory的一种,在Spring源码中,是这么定义的:
在这里插入图片描述
首先,在Java中,接口是可以多继承的,我们发现ApplicationContext继承了ListableBeanFactory和HierarchicalBeanFactory,而ListableBeanFactory和HierarchicalBeanFactory都继承至BeanFactory,
所以我们可以认为ApplicationContext继承了BeanFactory,相当于苹果继承水果,宝马继承汽车一样,ApplicationContext也是BeanFactory的一种,拥有BeanFactory支持的所有功能,不过ApplicationContext比BeanFactory更加强大,ApplicationContext还基础了其他接口,也就表示
ApplicationContext还拥有其他功能,比如MessageSource表示国际化,ApplicationEventPublisher表示事件发布,EnvironmentCapable表示获取环境变量,等等,关于ApplicationContext后面再详细讨论。
在Spring的源码实现中,当我们new一个ApplicationContext时,其底层会new一个BeanFactory出来,当使用ApplicationContext的某些方法时,比如getBean(),底层调用的是BeanFactory的getBean()方法。
在Spring源码中,BeanFactory接口存在一个非常重要的实现类是:DefaultListableBeanFactory,也是非常核心的。
所以,我们可以直接来使用DefaultListableBeanFactory,而不用使用ApplicationContext的某个实现类,比如:在这里插入图片描述
DefaultListableBeanFactory是非常强大的,支持很多功能,可以通过查看DefaultListableBeanFactory的类继承实现结构来看
在这里插入图片描述
这部分现在看不懂没关系,源码熟悉一点后回来再来看都可以。
它实现了很多接口,表示,它拥有很多功能:
1.AliasRegistry:支持别名功能,一个名字可以对应多个别名
2.BeanDefinitionRegistry:可以注册、保存、移除、获取某个BeanDefinition
3BeanFactory:Bean工厂,可以根据某个bean的名字、或类型、或别名获取某个Bean对象
4SingletonBeanRegistry:可以直接注册、获取某个单例Bean
5SimpleAliasRegistry:它是一个类,实现了AliasRegistry接口中所定义的功能,支持别名功能
6ListableBeanFactory:在BeanFactory的基础上,增加了其他功能,可以获取所有BeanDefinition的beanNames,可以根据某个类型获取对应的beanNames,可以根据某个类型获取{类型:对应的Bean}的映射关系
7HierarchicalBeanFactory:在BeanFactory的基础上,添加了获取父BeanFactory的功能
8DefaultSingletonBeanRegistry:它是一个类,实现了9SingletonBeanRegistry接口,拥有了直接注册、获取某个
单例Bean的功能
10ConfigurableBeanFactory:在HierarchicalBeanFactory和SingletonBeanRegistry的基础上,添加了设置父BeanFactory、类加载器(表示可以指定某个类加载器进行类的加载)、设置Spring EL表达式解析器(表示该BeanFactory可以解析EL表达式)、设置类型转化服务(表示该BeanFactory可以进行类型转化)、可以添加BeanPostProcessor(表示该BeanFactory支持Bean的后置处理器),可以合并BeanDefinition,可以销毁某个Bean等等功能
11FactoryBeanRegistrySupport:支持了FactoryBean的功能
AutowireCapableBeanFactory:是直接继承了BeanFactory,在BeanFactory的基础上,支持在创建Bean的过程中能对Bean进行自动装配
AbstractBeanFactory:实现了ConfigurableBeanFactory接口,继承了FactoryBeanRegistrySupport,这个BeanFactory的功能已经很全面了,但是不能自动装配和获取beanNamesConfigurableListableBeanFactory:继承了ListableBeanFactory、AutowireCapableBeanFactory、
ConfigurableBeanFactoryAbstractAutowireCapableBeanFactory:继承了AbstractBeanFactory,实现了AutowireCapableBeanFactory,拥有了自动装配的功能DefaultListableBeanFactory:继承了AbstractAutowireCapableBeanFactory,实现了
ConfigurableListableBeanFactory接口和BeanDefinitionRegistry接口,所以DefaultListableBeanFactory的功能很强大

ApplicationContext
HierarchicalBeanFactory:拥有获取父BeanFactory的功能
ListableBeanFactory:拥有获取beanNames的功能
ResourcePatternResolver:资源加载器,可以一次性获取多个资源(文件资源等等)
EnvironmentCapable:可以获取运行时环境(没有设置运行时环境功能)
ApplicationEventPublisher:拥有广播事件的功能(没有添加事件监听器的功能)
MessageSource:拥有国际化功能
我们先来看ApplicationContext两个比较重要的实现类:
AnnotationConfigApplicationContext
ClassPathXmlApplicationContext
AnnotationConfigApplicationContext
在这里插入图片描述
ConfigurableApplicationContext:继承了ApplicationContext接口,增加了,添加事件监听器、添加BeanFactoryPostProcessor、设置Environment,获取ConfigurableListableBeanFactory等功能

AbstractApplicationContext:实现了ConfigurableApplicationContext接口

GenericApplicationContext:继承了AbstractApplicationContext,实现了BeanDefinitionRegistry接口,拥有了所有ApplicationContext的功能,并且可以注册BeanDefinition,注意这个类中有一个属性
(DefaultListableBeanFactory beanFactory)

AnnotationConfigRegistry:可以单独注册某个为类为BeanDefinition(可以处理该类上的**@Configuration注解**,已经可以处理**@Bean注解**),同时可以扫描AnnotationConfigApplicationContext:继承了GenericApplicationContext,实现了AnnotationConfigRegistry接
口,拥有了以上所有的功能

ClassPathXmlApplicationContext
在这里插入图片描述
ApplicationContext=BeanFactory的全自动版+ 服务周到版


DefaultListableBeanFactory defaultListableBeanFactory = new
DefaultListableBeanFactory();
AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new
AnnotatedBeanDefinitionReader(defaultListableBeanFactory);
annotatedBeanDefinitionReader.register(MainStart.class); 
// 解析配置
AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition)
defaultListableBeanFactory.getBeanDefinition("mainStart");
if(beanDefinition.getMetadata().hasAnnotation(ComponentScan.class.getName())){// 读取为BeanDefintion ClassPathBeanDefinitionScanner classPathBeanDefinitionScanner = new
ClassPathBeanDefinitionScanner(defaultListableBeanFactory);classPathBeanDefinitionScanner.scan("com.xushu.all"); 
} 
// 一个个创建bean 
defaultListableBeanFactory.preInstantiateSingletons();

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

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

相关文章

数字证书_CA_详解

目录 一、数字证书简介 二、 CA(证书颁发机构) (一) 证书链(信任链) 1. 根证书 2. 中间证书 3. 网站证书 (二) 抓包软件的证书链与信任机制 1. 抓包通信流程 2. 证书链伪造与信任验证流程 (三) 关于移动设备的CA 一、数…

Qt Creator 11.0创建ROS2 Humble工程

Qt Creator 11.0创建ROS2 Humble项目工程 安装ROSProjectManager插件创建ROS2项目在src下添加packagegit clone ROS2功能包编译运行安装ROSProjectManager插件 安装ROSProjectManager的主要流程参考官方的流程,地址(ros_qtc_plugin)。 此处采用二进制安装: sudo apt inst…

卡西欧模拟器:Windows端功能强大的计算器

引言 大家还记得初中高中时期用的计算器吗?今天给大家分享的就是一款windows端的卡西欧计算器。 软件介绍 大家好,我是逍遥小欢。 CASIO fx-9860G是一款功能强大的图形计算器,适用于数学、科学和工程计算。以下是其主要功能和特点的详细介…

软件工程专业的本科生应该具备哪些技能

软件工程专业的本科生需要具备扎实的技术基础、良好的开发流程认知和一定的软技能,以适应软件开发行业的需求。以下从技术技能、开发流程与工具、软技能、实践能力等维度整理核心技能清单,供参考: 一、核心技术技能 1. 编程语言 - 必学基础语…

微信小程序实现运动能耗计算

微信小程序实现运动能耗计算 近我做了一个挺有意思的微信小程序,能够实现运动能耗的计算。只需要输入性别、年龄、体重、运动时长和运动类型这些信息,就能算出对应的消耗热量。 具体来说,在小程序里,性别不同,身体基…

点评中是如何实现短信登录的

点评中是如何实现短信登录的 首先在这个项目中 我们主要还是通过session来实现的验证码登录 根据这个图片我们很清楚的知道 首先要制造一个随机的验证码以确保并且保存到redis中(等下我会说为什么不存在session中)接下来前端传来验证码 后端校验后 判断…

Kafka入门-集群基础环境搭建(JDK/Hadoop 部署 + 虚拟机配置 + SSH 免密+Kafka安装启动)

Kafka 简介 传统定义:Kafka是一个分布式的基于发布/订阅模式的消息队列,应用于大数据实时处理领域。 Kafka最新定义:Apache Kafka是一个开源分布式事件流平台,被数千家公司用于高性能数据管道、流分析、数据集成和关键任务应用…

从OSI到TCP/IP:网络协议的演变与作用

个人主页:chian-ocean 文章专栏-NET 从OSI到TCP/IP:网络协议的演变与作用 个人主页:chian-ocean文章专栏-NET 前言网络发展LANWAN 协议举个例子: 协议的产生背景 协议的标准化OSI模型参考OSI各个分层的作用各层次的功能简介 TCP/…

Java观察者模式深度解析:构建松耦合事件驱动系统的艺术

目录 观察者模式基础解析核心结构与实现原理Java内置观察者实现Spring框架中的高级应用典型应用场景与实战案例观察者模式变体与优化常见问题与最佳实践总结与未来展望1. 观察者模式基础解析 1.1 模式定义与核心思想 观察者模式(Observer Pattern)是一种行为型设计模式,它…

前端(vue)学习笔记(CLASS 7):vuex

vuex概述 vuex是一个vue的状态管理工具,状态就是数据 大白话:vuex是一个插件,可以帮我们管理vue通用的数据(多组件共享的数据) 场景 1、某个状态在很多个组件来使用(个人信息) 2、多个组件…

论文中pdf图片文件太大怎么办

文章目录 1.使用pdf文件的打印功能将文件导出2.操作3.前后文件大小对比 1.使用pdf文件的打印功能将文件导出 该方法在保证清晰度的同时,内存空间也能实现减少(如果使用线上的压缩pdf工具,清晰度会直线下降) 2.操作 点击文件—&…

Java并发编程:读写锁与普通互斥锁的深度对比

在Java并发编程中,锁是实现线程安全的重要工具。其中,普通互斥锁(如synchronized和ReentrantLock)和读写锁(ReentrantReadWriteLock)是两种常用的同步机制。本文将从多个维度深入分析它们的区别、适用场景及…