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

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.lqws.cn/news/164413.html

相关文章:

  • Vue3实现拖拽改变元素大小
  • 1.2 fetch详解
  • React Hooks 指南:何时使用 useEffect ?
  • Grafana-ECharts应用讲解(玫瑰图示例)
  • Vue2数组数字字段求和技巧 数字求和方法
  • Compose Multiplatform 实现自定义的系统托盘,解决托盘乱码问题
  • Postman接口测试之postman设置接口关联,实现参数化
  • MATLAB仿真:偏振光在光纤通信中的应用研究_可复现,有问题请联系博主
  • 从内核到应用层:Linux缓冲机制与语言缓冲区的协同解析
  • Spring AI学习一
  • StoreView SQL,让数据分析不受地域限制
  • mysql复合查询mysql子查询
  • 如何通过外网访问内网?哪个方案比较好用?跨网远程连接网络知识早知道
  • Struts2漏洞由浅入深
  • Python语法进阶篇 --- 封装、继承、多态
  • React从基础入门到高级实战:React 实战项目 - 项目二:电商平台前端
  • 大中型水闸安全监测管理系统建设方案
  • 工厂模式 + 模板方法模式 + 策略模式的适用场景
  • 在 Spring Boot 中使用 JSP
  • 如何做好一份技术文档?(下篇)
  • Ansys Maxwell:线圈和磁体的静磁 3D 分析
  • 每日算法 -【Swift 算法】三数之和最接近目标值
  • 高敏感应用如何保护自身不被逆向?iOS 安全加固策略与工具组合实战(含 Ipa Guard 等)
  • wxpython快捷键示例
  • SpringBoot3整合MySQL8的注意事项
  • 云服务器自带的防御可靠吗
  • 使用 minicom 录制串口报文并回放
  • 数据融合是什么?进行数据融合的4大关键环节!
  • AI开启光伏新时代:精准计算每小时发电量​
  • 【JS进阶】ES5 实现继承的几种方式