1、Spring--整体启动流程

启动入口

创建AnnotationConfigApplicationContext

创建AnnotationConfigApplicationContext对象,所有的加载创建操作都在这里进行

//创建AnnotationConfigApplicationContext对象
AnnotationConfigApplicationContext annotationConfigApplicationContext = 
          new AnnotationConfigApplicationContext(AppClassCofig.class);
//通过AnnotationConfigApplicationContext拿到bean
User user = annotationConfigApplicationContext.getBean("user", User.class);

AnnotationConfigApplicationContext会做什么

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
	//1、调用父类的构造方法
	this();
	//2、componentClasses就是我们的配置类,比如被修饰了注解@Configuration的类
	register(componentClasses);
	//3、刷新,添加扩展器,bean的实例化,等等都在这里处理
	refresh();
}

一、this()

执行父类的构造方法

public AnnotationConfigApplicationContext() {
	//创建一个BeanDefinition读取器
	this.reader = new AnnotatedBeanDefinitionReader(this);
	//创建一个BeanDefinition扫描器
	this.scanner = new ClassPathBeanDefinitionScanner(this);
}
//注册一个读取器,这个读取器很厉害,会创建下面7大后置处理器
this.reader = new AnnotatedBeanDefinitionReader(this);

功能:往BeanDefinitionRegistry注册器里面添加各种“后置处理器”

1、AnnotationAwareOrderComparator(比较器)
2、ContextAnnotationAutowireCandidateResolver(自动装配解析)
3、ConfigurationClassPostProcessor (配置类后置处理器,这个很厉害)
4、AutowiredAnnotationBeanPostProcessor(自动装配后置处理器)
5、CommonAnnotationBeanPostProcessor (普通注解后置处理器)
6、EventListenerMethodProcessor(事件监听器处理器)
7、DefaultEventListenerFactory(事件监听器工厂)

像ConfigurationClassPostProcessor这个后置处理器,会解析带有@Configuration的类

//创建一个扫描器
this.scanner = new ClassPathBeanDefinitionScanner(this);

二、register(componentClasses);

参数componentClasses其实就是我们启动的时候穿的参数AppClassCofig.class
向容器里面注册一个类componentClasses,且转成Bean,并把这个bean添加到容器beanDefinitionMap里面去。为什么需要把这个转成Bean,因为后面我们需要通过特殊的类,来解析这个bean,读取这个bean中像@ComponentScan这种注解,来解析需要扫描的路径下的带有@Servcie @Bean…

三、refresh()刷新

public void refresh(){
	1prepareBeanFactory(beanFactory);//预准备工作,beanFactory设置添加各种东西
	2invokeBeanFactoryPostProcessors(beanFactory);
	3registerBeanPostProcessors(beanFactory);
	4onRefresh();
	5finishBeanFactoryInitialization(beanFactory);
	6finishRefresh();
}

3.1 prepareBeanFactory(beanFactory);

描述:BeanFactory准备工作。这里面和开始看到那个七个类的作用有很大关系。
总结:

1.设置beanFactory 的类加载器;
2.设置EL表达式解析器(Bean创建完成填充属性时使用)和属性注册解析器
3.利用BeanPostProcessor的特性给各种Aware接口的实现类注入ApplicationContext中对应的属性
4.设置各种Aware接口的实现类为忽略自动装配
5.设置自动装配的类(BeanFactory,ResourceLoader,ApplicationEventPublisher,ApplicationContext)
6.如果BeanFactory中存在loadTimeWeaver的bean,那么需要添加动态织入功能
7.注册各种可用组件(environment,systemProperties,systemEnvironment)

细节

1、向BeanFactory中添加BeanPostProcessor:ApplicationContextAwareProcessor

ApplicationContextAwareProcessor的作用请看:跳转

2、向BeanFactory中添加BeanPostProcessor:ApplicationListenerDetector

ApplicationListenerDetector的作用请看:将早期用于检测内部bean的后处理器注册为applicationlistener。兼容以前的后置处理器 跳转

3、向BeanFactory中添加BeanPostProcessor:LoadTimeWeaverAwareProcessor

如果当前BeanFactory包含loadTimeWeaver Bean,说明存在类加载期织入AspectJ,则把当前BeanFactory交给类加载器BeanPostProcessor实现类LoadTimeWeaverAwareProcessor来处理,从而实现类加载期织入AspectJ的目的。
BeanPostProcessor:LoadTimeWeaverAwareProcessor详细介绍 跳转

4、设置忽略自动装配的接口

设置忽略自动装配的接口,如果注入EnvironmentAware这个bd会注不进来

关注prepareBeanFactory详细介绍可以看:跳转

3.2 invokeBeanFactoryPostProcessors

描述:拿到spring定义和用户定义的BeanFactoryPostProcessorsBeanDefinitionRegistryPostProcessor分别去调用他们的回调方法

1、获取spring自带部分BeanFactoryPostProcessors

这些都是Spring一开启动添加进去的

  1. ConfigurationWarningsPostProcessor
  2. CachingMetadataReaderFactoryPostProcessor
  3. PropertySourceOrderingPostProcessor

2、获取spring自带所有BeanDefinitionRegistryPostProcessor

就包括拿到上面7个后置处理器中的ConfigurationClassPostProcessor,然后执行回调方法,注意ConfigurationClassPostProcessor和internalConfigurationAnnotationProcessor是一个东西

ConfigurationClassPostProcessor会做下面几件事

  1. 通过getBeanDefinitionNames得到所有beanName
  2. 找出带有@Configuration的bean,比如SpringBoot项目中加了@SpringBootApplication的类(SpringBootApplication的顶层就包含了@Configuration注解),或者我们平时常用的AppConfigClass这种。
  3. 创建ConfigurationClassParser对象,并且把配置类作为参数传给ConfigurationClassParser对象,这里会做很多事,解析需要扫描的路径,把这些路劲下的Bean拿到,如果这些Bean又是一个@Config配置类,就递归去扫描解析,像加了@PropertySource、@ComponentScan、@Import、@ImportResource、@Bean都会被处理解析

ConfigurationClassParser和ConfigurationClassPostProcessor是2个东西别搞混了

3、获取所有BeanDefinitionRegistryPostProcessor
上面获取的都是spring自带的BeanDefinitionRegistryPostProcessor,当第二步扫描完全部路径,把需要创建的Bean都是添加进来之后,这些bean里面可能回包含用户自定义的BeanDefinitionRegistryPostProcessor。

4、获取所有BeanFactoryPostProcessor
获取所有BeanFactoryPostProcessor,包含spring定义的和用户定义的,下面5个是spring自带的。

0 = "internalConfigurationAnnotationProcessor"
1 = "servletComponentRegisteringPostProcessor"
2 = "propertySourcesPlaceholderConfigurer"
3 = "ConfigurationPropertiesBindingPostProcessor.store"
4 = "preserveErrorControllerTargetClassPostProcessor"	

还会判断这些类型是不是已经执行过了,就是确保只执行了一次,如果没有执行就调用自己实现的回调方法。

3.3 、registerBeanPostProcessors(beanFactory);

拿到所有的BeanPostProcessor,包含spring定义的和用户定义的。把他添加到BeanFactory中里面去,所以也可以说是注册BeanPostProcessor

0 = "internalAutowiredAnnotationProcessor"
1 = "internalRequiredAnnotationProcessor"
2 = "internalCommonAnnotationProcessor"
3 = "internalScheduledAnnotationProcessor"
4 = "ConfigurationPropertiesBindingPostProcessor"
5 = "embeddedServletContainerCustomizerBeanPostProcessor"
6 = "errorPageRegistrarBeanPostProcessor"
7 = "methodValidationPostProcessor"
8 = "dataSourceInitializerPostProcessor"
9 = "persistenceExceptionTranslationPostProcessor"
0= "org.springframework.aop.config.internalAutoProxyCreator"

1、把上面的beanPostProcessor添加到BeanFactory里面去:

beanFactory.addBeanPostProcessor(*)

2、手动添加:BeanPostProcessorChecker,并且把他加入到BeanFactory里面去
3、手动添加: ApplicationListenerDetector

3.4、onRefresh();

这里会实例化一部分Bean,这些bean是spring的,在额外包括用户自定义的Filter,也就是MVC的相关的bean都会在这里处理

spring自定义的Bean:

1=EmbeddedServletContainerAutoConfiguration$EmbeddedTomcat
2=tomcatEmbeddedServletContainerFactory
3=application
4=WebSocketAutoConfiguration$TomcatWebSocketConfiguration
5=websocketContainerCustomizer
6=HttpEncodingProperties

实例化bean的时候,还会触发BeanPostProcess的回调方法。只要实例化一个bean就会拿到所有的BeanPostProcess然后循环调用,只要有一个bean实例化,循环执行整个BeanPostProcess,所以每个BeanPostProcess可能会执行多次,而BeanFactoryPostProcess是只会执行一次。

3.5、finishBeanFactoryInitialization(beanFactory);

实例化剩下没有实例化的Bean,因为onRefresh()方法已经实例化了一部分。
大致看下怎么实例化的:

1、首先拿到所有需要创建Bean的Name

List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);

2、然后循环遍历里面的name把他转成RootBeanDefinition

RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

然后通过getBean方法来得到Bean,如果没有实例化,就会同时去创建实例的。
如果是存在循环依赖,就是找出依赖的Bean,然后再去创建这个Bean对象,如果这个Bean又有依赖的Bean,就一层一层递归下去。实例化完了之后就会再去调用BeanPostProcess的回调方法。

你可能感兴趣的:(spring,面试,spring,java,后端)