Spring原理篇(10)--Spring系列IOC小总结;Spring的启动原理;不得了;当初我某个同学把这一块东西搞得明明白白的; 不管是工作上遇到的问题;还是面试中遇到的问题都不在话下;

@TOC# Spring系列
记录在程序走的每一步___auth:huf


临近放假;预祝同学们国庆节日快乐,祝祖国繁荣昌盛; 因为近期的工作,以及上生产版本比较频繁;所以文章有稍微更新不及时; 国庆期间会给大家把文章补齐; 其实我们一直看源码 看得都是Spring的启动原理; Spring的启动原理 涵盖了我之前所有文章源码的集合;这里没有AOP 如果精准一点说 是有一丢丢AOP的知识点体系; AOP的源码国庆后会更新出来给大伙;在Spring中 即使没有代理对象 我们依然可以很快乐的使用Spring; 但是AOP又是Spring的高亮之一; 也是面试的重点 也是知识体系掌握的重点; 所以就独立开来 后面单独的去讲这一块;

Spring 的启动原理;

该篇章为源码篇章 所有解释在源码里边;


/**
 * auth:huf
 */
@SpringBootApplication(exclude= {
    
    DataSourceAutoConfiguration.class})
public class testMain {
    
    
    public static void main(String[] args) {
    
    
    	创建启动上下文; 那么我们就从这个方法开始进行深入的解析整个过程;
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(testMain.class);
        TeacharServiceImpl teacharServiceImpl = (TeacharServiceImpl) context.getBean("teacharServiceImpl");
        System.out.println(teacharServiceImpl);
    }
}
public AnnotationConfigApplicationContext() {
    
    
		在其方法的内部 我们可以看到; 在Spring中 所有的东西的开始 就是类; 包括一开始使用的BeanFactory
		或者是说BeanPostProcessor  在一开始 肯定是需要一个承载的东西去承载 所有一切的开始;
		StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
		
		该承载器就是DefaultListableBeanFactory 一开始通过this this是什么 
		就是AnnotationConfigApplicationContext本身 
		然后传入到AnnotatedBeanDefinitionReader方法内部
		内部通过unwrapDefaultListableBeanFactory方法 给你强转成为 
		DefaultListableBeanFactory 这个就是梦的开始; 下面有该方法详细解说;
		this.reader = new AnnotatedBeanDefinitionReader(this);
		createAnnotatedBeanDefReader.end();
		之后就加入Component 的Filters 便于解析Component类需要用到的; 该方法不详说
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

AnnotatedBeanDefinitionReader

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, @Nullable Object source) {
    
    
		根据上述所说 我们通过强转得到了一个DefaultListableBeanFactory 
		我这里是这样理解这个东西的. 一切都需要一个开端. 一切都需要开始的一个步骤;
		DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
		if (beanFactory != null) {
    
    
			if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
    
    
				一开始创建了一个比较器;该比较器里面(排序等) 类型比较; 然后放进去BeanFactory
				beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
			}
			if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
    
    
				然后创建一个AutowrireCandiate的自动解析器; 主要用于BeanFactory 自动解析; 
				主要解析是否可以依赖注入; 这里源码感兴趣的同学可以自行点进去看其作用;
				beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
			}
		}
		创建一个List 放置前置 BeanDefinition 它 就是BeanDefintionHolder 
		Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
		if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
    
    
			这ConfigurationClassPostProcessor 
			其实它是BeanFactoryPostProcessor 它的作用是用于配置文件的扫描 等等作用
			RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
		}
		if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
    
    
			这个就很简单了 这个一看这个.Class 就能明白.它是自定义注解的PostProcessor
			RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
		}
		if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
    
    
			这个是@Resource 那个注解的 BeanPostProcessor
			RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
		}
		这里是JPA的 的一些注解PostProcessor
		if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
    
    
			RootBeanDefinition def = new RootBeanDefinition();
			try {
    
    
				def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
						AnnotationConfigUtils.class.getClassLoader()));
			}
			catch (ClassNotFoundException ex) {
    
    
				throw new IllegalStateException(
						"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
			}
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
		}
		这里是Spring事件监听的PostProcessor
		if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
    
    
			RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
		}
		这里是Spring事件相关的PostProcessor
		if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
    
    
			RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
		}
		return beanDefs;
	}

这个方法就是这么简单; 也就是说 一开始启动的时候 就会创建一个空的BeanFactory 并且向里面设置一些内容;这些内容是之后我们要用到的内容 请注意 这些内容并没有实例化; 注意!! 这些内容并没有实例化; 仅仅是生成相对应的RootBeanDefinition 并且放到registry 里边 也就是BeanFactory里边!!!

	public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    
    
		这个This 就是刚刚上面说的那些内容
		this();
		这里是将传入的那个testMain.class 进行解析;生成BeanDefinition 放进去BeanFactorgy里面
		这两行代码其实并不难;  同学们可以自己点进去看一下; 别看到代码多就慌; 
		register(componentClasses);
		重点看这行代码 重点!!重点!!重点!!!
		refresh();
	}

refresh

refresh():加载或刷新持久化的 配置,可能是XML文件、属性文件或关系数据库中存储的。由于这是一个启动方法,如果失败,它应 该销毁已经创建的单例,以避免暂用资源。换句话说,在调用该方法之后,应该实例化所有的单例, 或者根本不实例化单例 。

ApplicationContext关闭之后不代表JVM也关闭了,ApplicationContext是 属于JVM的,说白了ApplicationContext也是JVM中的一个对象。
在Spring的设计中,也提供可以刷新的ApplicationContext和不可以刷新的ApplicationContext

可刷新的
AbstractRefreshableApplicationContext extends AbstractApplicationContext
不可刷新的
GenericApplicationContext extends AbstractApplicationContext

AnnotationConfigApplicationContext继承的是GenericApplicationContext,所以它是不能刷新 的。 AnnotationConfigWebApplicationContext继承的是 AbstractRefreshableWebApplicationContext,所以它是可以刷的。 上面说的不能刷新是指不能重复刷新,只能调用一次refresh方法,第二次时会报错。

一下就是关键重点代码; 我前几篇文章 全部都有写; 但是可能写得不够详细;这里我们再从新写一次;
里面的代码我就不再继续累赘; 因为里面代码 我们基本上都看过一次;

public void refresh() throws BeansException, IllegalStateException {
    
    
		synchronized (this.startupShutdownMonitor) {
    
    
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
			---------------------------------
			这里是往BeanFactory 继续set 其他属性 并且里面有一个方法是:
			--initPropertySources() 该方法就是初始化property 里面的属性;
			 有一些属性是可以设置成必须注入的属性 我们以前再整合SpringMVC的时候 再web.xml里面就有配置;
			 直白一点就是一些Key Value键值对;
			 以下就是详细:
			 1记录启动时间 
			 2可以允许子容器设置一些内容到Environment中 
			 3验证Environment中是否包括了必须要有的属性
			prepareRefresh(); --源码
			---------------------------------
			进行BeanFactory的refresh,在这里会去调用子类的 refreshBeanFactory方法,
			具体子类是怎么刷新的得看子类,然后再调用子类的 getBeanFactory方法,
			重新得到一个BeanFactory
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); --源码
			---------------------------------
			prepareBeanFactory(beanFactory);--源码
			1:设置beanFactory的类加载器
			2:设置表达式解析器:StandardBeanExpressionResolver,用来解析Spring中的表达式
			3:添加PropertyEditorRegistrar:ResourceEditorRegistrar,PropertyEditor类型转化器注 册器,用来注册一些默认的PropertyEditor
			4:添加一个Bean的后置处理器:ApplicationContextAwareProcessor,是一个 BeanPostProcessor,用来执行EnvironmentAware、ApplicationEventPublisherAware 等回调方法
			5:添加ignoredDependencyInterface:可以向这个属性中添加一些接口,
				如果某个类实现 了这个接口,并且这个类中的某些set方法在接口中也存在,
				那么这个set方法在自动注入的 时候是不会执行的,比如EnvironmentAware这个接口,
				如果某个类实现了这个接口,那么 就必须实现它的setEnvironment方法,
				而这是一个set方法,和Spring中的autowire是冲突 的,
				那么Spring在自动注入时是不会调用setEnvironment方法的,
				而是等到回调Aware接 口时再来调用(注意,这个功能仅限于xml的autowire,@Autowired注解是忽略这个属性 的){
    
    
				a. EnvironmentAware
				b. EmbeddedValueResolverAware
				c. ResourceLoaderAware 
				d. ApplicationEventPublisherAware 
				e. MessageSourceAware 
				f. ApplicationContextAware 
				g 另外其实在构造BeanFactory的时候就已经提前添加了另外三个: 
				h. BeanNameAware 
				i. BeanClassLoaderAware 
				j. BeanFactoryAware
					}
			 6:添加resolvableDependencies:在byType进行依赖注入时,会先从这个属性中根据类型 找bean{
    
    
				a. BeanFactory.class:当前BeanFactory对象 
				b. ResourceLoader.class:当前ApplicationContext对象 
				c. ApplicationEventPublisher.class:当前ApplicationContext对象 
				d. ApplicationContext.class:当前ApplicationContext对象
					}
			 7:添加一个Bean的后置处理器:ApplicationListenerDetector,
				 是一个 BeanPostProcessor,用来判断某个Bean是不是ApplicationListener,
				 如果是则把这个 Bean添加到ApplicationContext中去,
				 注意一个ApplicationListener只能是单例的
			 8: 添加一个Bean的后置处理器:LoadTimeWeaverAwareProcessor,
			 	是一个 BeanPostProcessor,用来判断某个Bean是不是实现了LoadTimeWeaverAware接口,
			 	如果实现了则把ApplicationContext中的loadTimeWeaver回调setLoadTimeWeaver方法
			 	设置给该Bean。
			 9:添加一些单例bean到单例池{
    
    
			 	a. "environment":Environment对象 
			 	b. "systemProperties":System.getProperties()返回的Map对象 
			 	c. "systemEnvironment":System.getenv()返回的Map对象
			 	}
			---------------------------------
			try {
    
    
				提供给AbstractApplicationContext的子类进行扩 展,具体的子类,可以继续向BeanFactory中再添加一些东西
				postProcessBeanFactory(beanFactory); --源码
				---------------------------------
				记录beanPostProcess 创建时间
				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process"); --源码
				---------------------------------
				invokeBeanFactoryPostProcessors(beanFactory);--源码
				执行BeanFactoryPostProcessor{
    
    
				1:此时在BeanFactory中会存在一个BeanFactoryPostProcessor: ConfigurationClassPostProcessor,它也是一个 BeanDefinitionRegistryPostProcessor
				2:从BeanFactory中找到类型为BeanDefinitionRegistryPostProcessor的beanName,也就 是ConfigurationClassPostProcessor, 然后调用BeanFactory的getBean方法得到实例 对象
				3:执行**ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry()**方法:[
					a. 解析AppConfig类 
					b. 扫描得到BeanDefinition并注册
					c. 解析@Import@Bean等注解得到BeanDefinition并注册 
					d. ConfigurationClassPostProcessor是如何工作的 放到下个篇章 这里留个坑
					e. 在这里,我们只需要知道在这一步会去得到BeanDefinition,而这些BeanDefinition中 可能存在BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor,所以 执行完ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry()方 法后,还需要继续执行其他BeanDefinitionRegistryPostProcessor的 postProcessBeanDefinitionRegistry()方法
					]
				4:执行其他BeanDefinitionRegistryPostProcessor的 **postProcessBeanDefinitionRegistry()**方法
				5:执行所有BeanDefinitionRegistryPostProcessor的**postProcessBeanFactory()**方法
				6:从BeanFactory中找到类型为BeanFactoryPostProcessor的beanName,而这些 BeanFactoryPostProcessor包括了上面的BeanDefinitionRegistryPostProcessor
				7:执行还没有执行过的BeanFactoryPostProcessor的**postProcessBeanFactory()**方法
				}
				---------------------------------
				因为上面的步骤完成了扫描,这个过程中程序员 可能自己定义了一些BeanPostProcessor,
				在这一步就会把BeanFactory中所有的 BeanPostProcessor找出来并实例化得到一个对象,
				并添加到BeanFactory中去(属性 beanPostProcessors),
				最后再重新添加一个ApplicationListenerDetector对象(之前其实就添加了过,
				这里是为了把ApplicationListenerDetector移动到最后)
				registerBeanPostProcessors(beanFactory);--源码
				---------------------------------
				到此,所有的BeanFactoryPostProcessor的逻辑都执行完了,主要做的事情就是得到 BeanDefinition并注册到BeanFactory中
				beanPostProcess.end();--源码
				---------------------------------
				如果BeanFactory中存在一个叫做"messageSource"的 BeanDefinition,那么就会把这个Bean对象创建出来并赋值给ApplicationContext的 messageSource属性,让ApplicationContext拥有国际化的功能
				initMessageSource();--源码
				---------------------------------
				如果BeanFactory中存在一个叫 做"applicationEventMulticaster"的BeanDefinition,
				那么就会把这个Bean对象创建出来并 赋值给ApplicationContext的applicationEventMulticaster属性,
				让ApplicationContext拥有 事件发布的功能			 
				initApplicationEventMulticaster();--源码
				---------------------------------

				提供给AbstractApplicationContext的子类进行扩展,没用
				onRefresh();--源码
				---------------------------------

				从BeanFactory中获取ApplicationListener类型的beanName,
				然后添加 到ApplicationContext中的事件广播器applicationEventMulticaster中去,
				到这一步因为 FactoryBean还没有调用getObject()方法生成Bean对象,
				所以这里要在根据类型找一下 ApplicationListener,记录一下对应的beanName
				registerListeners();--源码
				---------------------------------

				完成BeanFactory的初始化,主要就是实例化 非懒加载的单例Bean
				finishBeanFactoryInitialization(beanFactory);--源码
				---------------------------------
				
				finishRefresh();--源码
				BeanFactory的初始化完后,就到了Spring启动的最后一步了
				设置ApplicationContext的lifecycleProcessor,默认情况下设置的是 DefaultLifecycleProcessor
				调用lifecycleProcessor的onRefresh()方法,如果是DefaultLifecycleProcessor,那么会获取所 有类型为Lifecycle的Bean对象,然后调用它的start()方法,这就是ApplicationContext的生命 周期扩展机制
				发布ContextRefreshedEvent事件
			}
			catch (BeansException ex) {
    
    
				if (logger.isWarnEnabled()) {
    
    
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}
				destroyBeans();
				cancelRefresh(ex);
				throw ex;
			}
			finally {
    
    
				resetCommonCaches();
				contextRefresh.end();
			}
		}
	}

执行BeanFactoryPostProcessor

  1. 执行通过ApplicationContext添加进来的BeanDefinitionRegistryPostProcessor的 postProcessBeanDefinitionRegistry()方法
  2. 执行BeanFactory中实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor的 postProcessBeanDefinitionRegistry()方法
  3. 执行BeanFactory中实现了Ordered接口的BeanDefinitionRegistryPostProcessor的 postProcessBeanDefinitionRegistry()方法
  4. 执行BeanFactory中其他的BeanDefinitionRegistryPostProcessor的 postProcessBeanDefinitionRegistry()方法
  5. 执行上面所有的BeanDefinitionRegistryPostProcessor的postProcessBeanFactory()方法
  6. 执行通过ApplicationContext添加进来的BeanFactoryPostProcessor的 postProcessBeanFactory()方法
  7. 执行BeanFactory中实现了PriorityOrdered接口的BeanFactoryPostProcessor的 postProcessBeanFactory()方法
  8. 执行BeanFactory中实现了Ordered接口的BeanFactoryPostProcessor的 postProcessBeanFactory()方法
  9. 执行BeanFactory中其他的BeanFactoryPostProcessor的postProcessBeanFactory()方法

至此 Spring启动就算彻底完成;

seeyou

Guess you like

Origin blog.csdn.net/wenaicoo/article/details/120517063