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

发布于:2025-06-06 ⋅ 阅读:(20) ⋅ 点赞:(0)

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();

网站公告

今日签到

点亮在社区的每一天
去签到