Spring5源码解析(扫描bean)
测试用例代码块
1 | typescript复制代码//AppConfig.java类 |
- 这里我是直接用AnnotationConfigApplicationContext类初始化spring的环境,这个类是基于注解配置应用上下文(即是用注解的方式初始化一个spring容器)
1 | java复制代码Spring中用来注解Bean定义的类有两个: |
下面进入spring容器初始化源码分析
- (1) AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
1 | scala复制代码public class AnnotationConfigApplicationContext extends GenericApplicationContext |
这里创建一个AnnotationConfigApplicationContext对象,主要是做了3个主要的操作。
1.创建一个new DefaultListableBeanFactory() 是一个Bean工厂容器
2.创建一个new AnnotatedBeanDefinitionReader(this),是Bean的读取器
3.创建一个new ClassPathBeanDefinitionScanner(this),是Bean的扫描器
为什么这里会创建一个DefaultListableBeanFactory()实例的beanFactory?
1.这个beanFactory主要是用来存放Spring管理的Bean对象,一个Bean存放的工厂。
2.怎么会调用了这步new DefaultListableBeanFactory()?因为AnnotationConfigApplicationContext继承了GenericApplicationContext,即在创建AnnotationConfigApplicationContext对象,会先执行父类GenericApplicationContext的构造方法。所以这里是在父类的构造方法中,执行了new DefaultListableBeanFactory()创建了一个beanFactory对象。
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
AnnotationConfigApplicationContext 继承了GenericApplicationContext
GenericApplicationContext 实现了 BeanDefinitionRegistry
- 即有:AnnotationConfigApplicationContext 也实现了BeanDefinitionRegistry,AnnotationConfigApplicationContext 也是一个registry类。
- 这个registry比较重要,registry有registerBeanDefinition(注册一个bean定义到bean工厂)、getBeanDefinition(从bean工厂获取一个Bean定义)等功能。所以AnnotationConfigApplicationContext 也是有可以往bean工厂中注册bean的能力。
1 | scss复制代码//创建一个bean读取器过程分析: |
这里创建一个AnnotatedBeanDefinitionReader对象,主要是做了2个主要的操作:
1.给在GenericApplicationContext()刚创建的beanFactory对象的某些属性赋值:beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);(主要能解析@Order注解和@Priority)
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());(提供处理延迟加载的功能)2.往bean工厂中注册6个spring内部对象,主要是**BeanPostProcessor类型的对象。(Spring的扩展点之一)
这里特别重要的类是ConfigurationClassPostProcessor,这个类完成bean的扫描。
- (2)ac.register(AppConfig.class);
1 | scss复制代码/** |
ac.register(AppConfig.class);的主要作用是将AppConfig类注册到bean工厂中。
即是到目前为止,bean工厂中已经有了7个beanDefinition。
- (3)ac.refresh(); 这里最重要的一步,实现bean的扫描和初始化阶段
1 | scss复制代码public void refresh() throws BeansException, IllegalStateException { |
- prepareRefresh
1 | kotlin复制代码protected void prepareRefresh() { |
- obtainFreshBeanFactory
1 | java复制代码protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { |
- prepareBeanFactory
1 | scss复制代码/** |
prepareBeanFactory方法的主要作用:
1.给beanFactory的某些属性赋值。
2.给beanFactory添加BeanPostProcessor:ApplicationContextAwareProcessor(可以插手bean的初始化,扩展点之一)
3.给beanFactory添加系统配置和系统环境信息等实例。
- invokeBeanFactoryPostProcessors
1 | scss复制代码protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { |
invokeBeanFactoryPostProcessors的主要作用:
1.执行spring内部的**BeanFactoryPostProcessor的方法。(ConfigurationClassPostProcessor)ConfigurationClassPostProcessor主要的作用就是实现bean的扫描,并实现将beanDefinition注册到bean工厂中
BeanFactoryPostProcessor
spring的扩展点之一:
1.实现该接口,可以在spring的bean创建之前修改bean的定义属性。
2.spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据,
3.并可以根据需要进行修改,例如可以把bean的scope从singleton改为prototype,也可以把property的值给修改掉。
4.可以同时配置多个BeanFactoryPostProcessor,并通过设置’order’属性来控制各个BeanFactoryPostProcessor的执行次序。
5.BeanFactoryPostProcessor是在spring容器加载了bean的定义文件之后,在bean实例化之前执行的。
BeanDefinitionRegistryPostProcessor实现了BeanFactoryPostProcessor 。是对BeanFactoryPostProcessor 的扩展,新增了postProcessBeanDefinitionRegistry方法,可以往Bean工厂中,注册一个BeanDefinition对象。
1 | 复制代码 |
本文转载自: 掘金