Spring容器建立源码解析

img

前言

  这篇博客是对Spring(5.0.7)的ioc容器建立过程的解析,也是博主不断debug几天的成果。内容可能有点多,讲的也可能比较枯燥。不过我相信个人分析对你们理解spring容器的整个工做原理仍是有一些帮助的。php

无参构造器:

  先是调用它的无参构造函数,初始化一些信息。
  无参构造函数中newAnnotatedBeanDefinitionReaderClassPathBeanDefiitionScanner赋值给readercontext的scanner属性。java

newAnnotatedBeanDefinitionReader对象:

    将该容器对象做为BeanDefinitionRegistry赋值给registry属性,而且new了一个ConditionEvaluator赋值给conditionEvaluator属性。以后调用registerAnnotationConfigProcessors方法将全部的annotation处理器注册进容器。web

new ConditionEvaluator:

    这是spring对该类的描述Internal class used to evaluate {@link Conditional} annotations.。能够看出这个类是@Conditional注解的一个解析器。在建立该类的时候利用deduceBeanFactory给该对象初始化了一个DefaultListableBeanFactory,而且该类是从容器中获取的。spring

img

AnnotationConfigUtils.registerAnnotationConfigProcessors:

    该方法先是给容器的beanFactory初始化了private Comparator<Object> dependencyComparator;private AutowireCandidateResolver autowireCandidateResolver两个属性;他们分别是用于bean的排序和解析自动注入@Autowired的;以后便开始注册一些spring内部的bean对象: 缓存

//spring检查容器中是否注入了这些bean 没有就建立简单的含有基本信息的BeanDefiintion对象注册
    // The bean name of the internally managed Configuration annotation processor.
	public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
			"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
	// The bean name of the internally managed Autowired annotation processor.
	public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
			"org.springframework.context.annotation.internalAutowiredAnnotationProcessor";
	// The bean name of the internally managed Required annotation processor.
	public static final String REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
			"org.springframework.context.annotation.internalRequiredAnnotationProcessor";
	// The bean name of the internally managed JSR-250 annotation processor.
	public static final String COMMON_ANNOTATION_PROCESSOR_BEAN_NAME =
			"org.springframework.context.annotation.internalCommonAnnotationProcessor";
	// The bean name of the internally managed JPA annotation processor.
	public static final String PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME =
			"org.springframework.context.annotation.internalPersistenceAnnotationProcessor";
	private static final String PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME =
			"org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor";
	// The bean name of the internally managed @EventListener annotation processor.
	public static final String EVENT_LISTENER_PROCESSOR_BEAN_NAME =
			"org.springframework.context.event.internalEventListenerProcessor";
	// The bean name of the internally managed EventListenerFactory.
	public static final String EVENT_LISTENER_FACTORY_BEAN_NAME =
			"org.springframework.context.event.internalEventListenerFactory";
			
    //注册过程以下 详见DefaultListableBeanFactory的registerBeanDefinition
    	if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				//do some thing .... 
			}
		}
		BeanDefinition oldBeanDefinition;
		 // get beanDefinintion from cache
		oldBeanDefinition = this.beanDefinitionMap.get(beanName);
		if (oldBeanDefinition != null) { 
		    // if cache alredy has this beanName beanDefinition break
		    // some warn message or throw exception
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
		// determine if create bean has started
		//(判断方法很简单benaFactory中的Set<String>alreadyCreated是否已经被填充过)
			if (hasBeanCreationStarted()) { 
            //lock beanDefinitionMap and put this beanDefinition to map
            //这里有个小细节他在添加元素进beanDefinitionNames时是直接建立了一个原先cache size+1的list
            //而后再将this beanDefinition name 放入list,最终改变beanDefinitionNames的为新建立list
            //if this beanDefinition is in manualSingletonNames,remove from list. why?
			}
			else {
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				this.manualSingletonNames.remove(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}
		if (oldBeanDefinition != null || containsSingleton(beanName)) {
		// 若是这个bean已经存在了单实例的对象则将其销毁
			resetBeanDefinition(beanName);
		}
复制代码

    至此AnnotatedBeanDefinitionReaderd对象建立完成markdown

newClassPathBeanDefinitionScanner对象:

    先是调用这个构造方法:app

img

    这里能够看出有3步操做 registerDefaultFilters, setEnvironment, setResourceLoader

registerDefaultFilters方法:

    从名字咱们不难看出这是建立默认过滤器的方法;
    其实是往该对象中添加了一个匹配@Component注解的AnnotationTypeFilter。spring对该类的解释以下:
    A simple filter which matches classes with a given annotation,checking inherited annotations as well.框架

//代码以下:
		this.includeFilters.add(new AnnotationTypeFilter(Component.class));
		ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
		try {
			this.includeFilters.add(new AnnotationTypeFilter(
					((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
		}
		try {
			this.includeFilters.add(new AnnotationTypeFilter(
					((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
		}
复制代码
setEnvironment方法:

    同样看名字咱们就能知道这是设置环境信息的。就是将以前建立AnnotatedBeanDefinitionReader对象时获取的StandardEnvironment设置给该对象的environment属性。异步

setResourceLoader方法:

    该方法分别给该对象的resourcePatternResolver,metadataReaderFactory,componentsIndex属性初始化。resourcePatternResolver对象其实就是容器对象.... metadataReaderFactory是一个从容器resourceCaches属性拷贝过来的ConcurrentHashMapresourcePatternResolver多是在加载META-INF/spring.components这个配置文件吧。具体我也不太清楚。
    至此spring容器的无参构造函数终于时调用完成了(😓)这只是简单的一步并且不少地方即便是知道了它在干什么仍是不清楚他为何这么作若是有更了解的大佬还望指教编辑器

register:

  将Config类注册进来,其实就是调用以前建立的AnnotatedBeanDefinitionReader对象的register方法将咱们所传入的配置类注册到容器当中。咱们能够直接看AnnotatedBeanDefinitionReader对象的doRegisterBean方法:
  该方法先是建立了Config对象的定义信息AnnotatedGenericBeanDefinition。以后调用如下方法shouldSkip,resolveScopeMetadata,generateBeanName,processCommonDefinitionAnnotations,applyScopedProxyMode,registerBeanDefinition

img

shouldSkip方法:

    该方法先经过isAnnotated判断有没有@Conditional注解若是有则判断该类是否符合注入要求。
     咱们先来看下他是如何判断有没有该注解的:
    首先是searchWithGetSemantics方法来查出该类全部注解。searchWithGetSemanticsInAnnotations来作判断。若是该注解不是java包中的注解。则判断它是不是@Conditional注解或者任什么时候候都忽略的process。以后递归调用searchWithGetSemantics来看元注解有没有包含@Conditional的。如下为判断源码:

Class<? extends Annotation> currentAnnotationType = annotation.annotationType();
if (!AnnotationUtils.isInJavaLangAnnotationPackage(currentAnnotationType)) {
	if (currentAnnotationType == annotationType ||
			currentAnnotationType.getName().equals(annotationName) ||
			processor.alwaysProcesses()) {
		T result = processor.process(element, annotation, metaDepth);
		if (result != null) {
			if (processor.aggregates() && metaDepth == 0) {
				processor.getAggregatedResults().add(result);
			}
			else {
				return result;
			}
		}
	}
	// Repeatable annotations in container?
	else if (currentAnnotationType == containerType) {
		for (Annotation contained : getRawAnnotationsFromContainer(element, annotation)) {
			T result = processor.process(element, contained, metaDepth);
			if (result != null) {
				// No need to post-process since repeatable annotations within a
				// container cannot be composed annotations.
				processor.getAggregatedResults().add(result);
			}
		}
	}
}
复制代码

resolveScopeMetadata方法:

    获取该bean的scope(这里就不细讲spring bean的做用域了不懂的自行百度),ScopeMetadata对象的值默认为singleton,因此若是该类没有@Scope注解默认为单例的。

generateBeanName方法:

    获取该bean的@Component注解标注的beanName,若是没有默认为类sortName。 获取类上的@Component注解步骤与第一步时获取@Conditional注解相似(递归获取注解-排除java注解)这里就不细讲了。

processCommonDefinitionAnnotations方法:

    对@Lazy,@Primary,@DependsOn,@Role,@Description的解析(这里提一下若是@Lazy没有的话默认是false,以前看到有人说默认懒加载显然时不正确的~)。丰富beanDefinition。比较简单不详细分析了,贴下源码:

 AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
 if (lazy != null) {
 abd.setLazyInit(lazy.getBoolean("value"));
 }
 else if (abd.getMetadata() != metadata) {
 lazy = attributesFor(abd.getMetadata(), Lazy.class);
 if (lazy != null) {
 abd.setLazyInit(lazy.getBoolean("value"));
 }
 }
 if (metadata.isAnnotated(Primary.class.getName())) {
 abd.setPrimary(true);
 }
 AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
 if (dependsOn != null) {
 abd.setDependsOn(dependsOn.getStringArray("value"));
 }
 if (abd instanceof AbstractBeanDefinition) {
 AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
 AnnotationAttributes role = attributesFor(metadata, Role.class);
 if (role != null) {
 absBd.setRole(role.getNumber("value").intValue());
 }
 AnnotationAttributes description = attributesFor(metadata, Description.class);
 if (description != null) {
 absBd.setDescription(description.getString("value"));
 }
 }
复制代码

applyScopedProxyMode方法:

    判断是否须要建立代理对象。若是须要调用ScopedProxyCreator.createScopedProxy方法建立。(待补全代理对象的建立过程...)

registerBeanDefinition方法:

    从方法名能够看出这部是真正的注册beanDefinition。真正调用的是容器中的BeanFactory(这里是DefaultListableBeanFactory)的registerBeanDefinition方法。首先验证beanDefinition的信息(具体我也没看懂在干什么)。以后判断该beanDefinition是否被注册过(若注册过符合条件覆盖以前的beanDefinition)。以后就是第一次注册该bean的操做(和调用无参构造函数注册过程一致详情。)     

register方法分析到这里就结束了,其实作的事情就是将配置类注册到容器当中。

refresh:

  refresh是最重要的一步,进行了容器刷新以及bean建立。执行步骤比较多。

 prepareRefresh();
 // Tell the subclass to refresh the internal bean factory.
 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
 // Prepare the bean factory for use in this context.
 prepareBeanFactory(beanFactory);
 try {
 // Allows post-processing of the bean factory in context subclasses.
 postProcessBeanFactory(beanFactory);
 // Invoke factory processors registered as beans in the context.
 invokeBeanFactoryPostProcessors(beanFactory);
 // Register bean processors that intercept bean creation.
 registerBeanPostProcessors(beanFactory);
 // Initialize message source for this context.
 initMessageSource();
 // Initialize event multicaster for this context.
 initApplicationEventMulticaster();
 // Initialize other special beans in specific context subclasses.
 onRefresh();
 // Check for listener beans and register them.
 registerListeners();
 // Instantiate all remaining (non-lazy-init) singletons.
 finishBeanFactoryInitialization(beanFactory);
 // Last step: publish corresponding event.
 finishRefresh();
 }
 catch (BeansException ex) {
 // Destroy already created singletons to avoid dangling resources.
 destroyBeans();
 // Reset 'active' flag.
 cancelRefresh(ex);
 }
 finally {
 // Reset common introspection caches in Spring's core, since we
 // might not ever need metadata for singleton beans anymore...
 resetCommonCaches();
 }
复制代码

prepareRefresh():

     进行容器的预刷新工做。这步仍是比较简单的。先是将容器置为启动状态。以后调用initPropertySources(该方法为空方法,提供给子类的覆盖) 最后调用validateRequiredProperties来验证是否包含一些必要参数(这里必要参数依旧为空)。

obtainFreshBeanFactory():

     对beanFactory进行刷新工做。先是调用refreshBeanFactory,使用CAS判断工厂是否已经刷新(已刷新抛异常),以后给工厂bean一个序列化id, 并将工厂对象放入缓存(由序列化id映射)。最后返回工厂bean(调用容器无参构造函数建立的DefaultListableBeanFactory对象);

prepareBeanFactory(beanFactory):

进行beanFactory的准备工做:

  1. beanFactory添加类加载器,表达式解析器,属性编辑器注册器, ApplicationContextAwareProcessor
  2. 忽略某些类的自动注入(这些接口大多为Spring为实现类注入bean的功能接口,例如:ApplicationContextAware)。
  3. 指定BeanFactory,ResourceLoader,ApplicationEventPublisher,ApplicationContext这些类型自动注入时的类(除beanFactory为当前beanFactory其他都为当前容器)
  4. 为工厂注入一些环境配置信息(beanName分别为environment、systemProperties、systemEnvironment)

postProcessBeanFactory:

    该方法时BeanFactory初始化以后再进行后续的一些BeanFactory操做。对于AnnotationConfigApplicationContext这是父类的一个空方法。在SpringBoot建立的另外两个web容器的时候(AnnotationConfigServletWebServerApplicationContextAnnotationConfigReactiveWebServerApplicationContext)会重写该方法。之后可能会出个SpringBoot原理分析系列详细会讲到这两个容器的建立及准备。

invokeBeanFactoryPostProcessors:

invokeBeanFactoryPostProcessors方法比较关键。该方法作了如下步骤:

  1. 执行ConfigurationClassPostProcessor,这个处理器主要来解析配置类(分为完整配置类和精简配置类,这里只详解带@Configuration注解的完整配置类),主要用于注册bean。
  2. 执行其余BeanFactoryPostProcessor。(分为BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor两种接口)
执行ConfigurationClassPostProcessor:

该方法主要执行了步骤:

  1. ConfigurationClassParser的parse方法:
    1. 获取@PropertySource注解信息(以后全部的获取注解信息都是分析shouldSkip提到的searchWithGetSemantics方法完成的),使用processPropertySource解析添加配置文件信息。处理过程大体是先建立PropertySource(建立的时候调用loadProperties读取配置文件信息)。以后将该配置文件信息添加到beanFactory的environmentbean对象中去。
    2. 获取@ComponentScans注解信息(若未获取到则为配置类的目录)。使用ComponentScanAnnocationParser来解析须要注册的bean,以后调用ClassPathBeanDefinitionScanner的doScan来将beanDefinition注册进容器。doScan作的事情就是扫包获取指定包的全部class文件并筛选有@Component而且@Conditional匹配的class。BeanDefinition注册过程就是以前提到的registerBeanDefinition方法。以后遍历获取到的BeanDefinitions执行parse。 操做将注册进来的Bean里的@PropertySource,@ComponentScans等注解的信息注册进来(递归注册)。
    3. @Import注解解析。processImports方法来执行该操做。将全部该注解引入的类注册到容器当中。使用collectImports方法递归查找该类下全部的注解中包含的@Import引入的对象。以后即是遍历处理操做:
      1. 若是引入对象是ImportSelector实现类,实例化该类。若是该类实现了Aware接口先给该类初始化这些属性(包含BeanClassLoaderAware,BeanFactoryAware,EnvironmentAware,ResourceLoaderAware)。以后判断若是该类实现类DeferredImportSelector接口就将其放入deferredImportSelectors后续处理。不然调用selectImports获取import对象并执行processImports递归。
      2. 若是引入对象是ImportBeanDefinitionRegistrar实现类,和以前同样先实例化再根据Aware初始化。最后将实例化后的类添加到带有@Import类的ConfigurationClassimportBeanDefinitionRegistrars属性中以便后续操做。
      3. 其余状况将其放入ConfigurationClassParserimportStackimports缓存(用于判断该类是否须要解析)。生成该类的ConfigurationClass(带有importedBy属性)。
    4. @ImportResource和第一步相似这个引入的是spring的配置类。往带有该注解的ConfigurationClassimportedResources属性添加该
    5. retrieveBeanMethodMetadata,解析该类全部带有@Bean的方法将其添加到该类的ConfigurationClass。
    6. processInterfaces,解析注入类中的全部接口中的default方法是否包含@Bean的,若是有就建立一个BeanMethod添加到该类的ConfigurationClass以便下一步来注册该对象。这两个方法查找了全部的@BeanMethod。
    7. 添加父类class到配置类中进行注册操做,和以前的parse操做相同。
    8. 将当前解析类的ConfigurationClass放入ConfigurationClassParser的configurationClasses属性中,为以后解析作准备。
    9. processDeferredImportSelectors处理3中放入deferredImportSelectors缓存中的DeferredImportSelector。调用全部的selectors的selectImports方法来获取全部导入类并封装成SourceClass列表再去调用processImports来递归。(这么多操做实际目的就是将全部的@Import生成ConfigurationClass或者放入importBeanDefinitionRegistrars为以后loadBeanDefinitions作准备)
  2. ConfigurationClassBeanDefinitionReader的loadBeanDefinitions:
    1. 遍历ConfigurationClass执行loadBeanDefinitionsForConfigurationClass。
    2. 判断该ConfigurationClass是不是导入的(带有importedBy属性),若是是将给类注册到beanFactory
    3. 解析该ConfigurationClass带有@Bean的方法生成beanDefinition(该定义信息除了有Lazy等属性外还有factoryBeanName和factoryMethodName)并注册到容器当中。
    4. 从importedResources属性中注册beanDefinition。读取配置文件信息获取beanDefinition并注册。
    5. 从1.3.2中放入importBeanDefinitionRegistrars属性中调用ImportBeanDefinitionRegistrar的registerBeanDefinitions直接注册到容器中。
执行BeanFactoryPostProcessor:

BeanFactoryPostProcessor排序执行:

  1. 获取BeanDefinitionRegistryPostProcessor执行处理(postProcessBeanDefinitionRegistry)。以后执行回调(postProcessBeanFactory)
  2. 获取BeanFactoryPostProcessor执行执行前置处理(postProcessBeanFactory)。以后执行后置处理(postProcessBeanFactory)
  3. 清除beanFactory缓存,清除mergedBeanDefinitions的未建立对象的定义信息。

registerBeanPostProcessors:

添加BeanPostProcessors:

  1. 添加BeanPostProcessorChecker处理器。
  2. 获取全部的BeanPostProcessors排序并添加。 registerBeanPostProcessors过程很简单就是将该处理器对象放入beanFactory,这个过程会经过getBean建立处理器对象。
  3. 添加ApplicationListenerDetector处理器。

执行顺序:

  1. 实现PriorityOrdered接口。
  2. 实现Ordered接口。
  3. 没有实现PriorityOrdered和Ordered接口的。
  4. 实现MergedBeanDefinitionPostProcessor接口的处理器。

initMessageSource:

国际化配置的信息。

initApplicationEventMulticaster:

初始化容器的事件广播器。若是容器中没有applicationEventMulticasterbean对象,建立一个SimpleApplicationEventMulticaster时间广播器并注册进beanFactory。

onRefresh:

能够重写的模板方法,以添加特定于上下文的刷新工做。对于AnnotationConfigApplicationContext这是个空方法。

registerListeners:

检查监听器bean并注册它们:

  1. 注册静态指定的侦听器。(添加到applicationListeners集合中)
  2. 从beanFactory获取ApplicationListener类型的beanNames并注册他们。
  3. 执行早期容器事件。

finishBeanFactoryInitialization:

将实例化的beanDefinition进行实例化:

  1. 若是容器中没有字符串解析器,new字符串解析器(使用容器Environment中的解析器来解析,默认是PropertySourcesPropertyResolver)。
  2. 开启容许缓存全部的beanDefinition而且将全部的beanDefinitions放入冻结配置状况的缓存中。
  3. 使用beanFactory的preInstantiateSingletons来实例化全部的beanDefinition。
    1. 遍历全部beanDefinition,获取该bean组合的beanDefinition。若是该bean须要工厂建立的对象,先使用getBean获取工厂对象再getBean获取工产对象。不是工厂对象直接调用getBean。(getBean起到建立对象做用。建立对象时会调用BeanPostProcessor。详细看这篇博客这篇博客)
    2. 遍历全部的beanDefinition,getSingleton从缓存中获取以前建立的Bean。若是该bean实现了SmartInitializingSingleton接口,执行接口方法afterSingletonsInstantiated。

finishRefresh:

  1. 清除上下文级资源缓存(这里是资源reader对象)。
  2. 为此上下文初始化生命周期处理器。(beanName:lifecycleProcessor),若是没有获取到默认注册DefaultLifecycleProcessor。
  3. 调用生命周期处理器的onRefresh:
    1. 获取beanFactory中全部实现Lifecycle接口的beanName,遍历,筛选出实现Lifecycle接口的必须在以前被实例化了或者实现SmartLifecycle接口。(过滤lifecycleProcessor)
    2. 遍历1获取的全部Lifecycle中实现SmartLifecycle接口而且该类的isAutoStartup方法为true的对象。
    3. 遍历2中获取的Lifecycle执行start方法。
  4. 添加ContextRefreshedEvent的
  5. 向LiveBeansView中注册该容器。(JMX的相关操做)

总结:

以上就是AnnotationConfigApplicationContext的建立过程。这里解析的都是基于注解的解析方式,由兴趣的小伙伴还能够看下基于xml的解析(应该只有Resource读取有所差别),以后我会本身实现一个能够扩展的简单容器(项目名字已经起好了叫seed😁),应该还会整合这个容器和netty(还在学习中...)实现一个异步的Controller层的框架,但愿个人文章能帮到你们。

相关文章
相关标签/搜索