欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

庖丁解牛之spring源码系列一

程序员文章站 2022-06-16 16:42:44
...

       spring最重要的是ioc和aop了,深入spring学习,源码当然必不可少,本文尝试分下spring ioc源码,希望能够对大家深入spring有一定的帮助。

一、AnnotationConfigApplicationContext

        spring提供了很多容器,AnnotationConfigApplicationContext是spring提供的一个支持注解式注入的容器,本文从AnnotationConfigApplicationContext容器开始,进行对spring ioc源码探索之旅。

        先来分析它的继承关系图,图在下面,已从左至右,从上到下的顺序开始分析,ResourceLoader是一个支持容器从文件系统和类路径加载资源的接口,默认实现是DefaultResourceLoader,ResourcePatternResolver扩展了ResourceLoader接口,能够支持“路径模式”的方式加载资源,也就是路径带*号的,比如说支持/WEB-INF/*-context.xml形式的路径。

         MessageSource是支持国际化的接口,ApplicationEventPublisher是spring提供的事件模型,支持发布事件。

         BeanFactory是spring的核心接口,是用来访问spring bean的容器,这个接口的实现类会拥有一个bean definitions集合,beanDefinitions是描述spring bean的数据结构。另外spring规定了beanfactory的实现类必须要支持的生命周期接口,也就是spring给我们提供的扩展点,包括BeanNameAware、BeanClassLoaderAware,BeanFactoryAware,EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware,ApplicationEventPublisherAware,BeanPostProcessors等等,关于生命周期接口以后在详细阐述,另外它的扩展接口ListableBeanFactory表示从容器中一次性获取多个spring bean对象。EnviromentCapable是一个暴露容器环境的接口,通过getEnvironment方法,返回当前容器的Environment对象,值得一提的是在ConfigurableApplicationContext中,getEnvironment返回的是ConfigurableEnvironment,也意味着用户可以修改Environment对象。

          ApplicationContext是beanfactory的一个扩展容器,继承了ListableBeanFactory,ResourceLoader,ApplicationEventPublisher接口,因此ApplicationContext除了支持beanfactory的功能,还支持加载资源,发布事件,支持国际化等,当然ApplicationContext运行的过程中仅支持可读,不能够进行更改,不过注意的是实现类可以重新加载容器。                                ConfigurableApplicationContext继承了ApplicationContext,能够更加灵活的配置容器,比如重新配置环境,增加beanfactory后置处理,追加事件监听器,另外大名鼎鼎的refresh方法就是此接口定义的。

          AbstractApplicationContext是ConfigurableApplicationContext的抽象实现类,使用了模板方法设计模式,由子类具体实现,AbstractApplicationContext能够自动注册一些定义在容器内部的bean,包括BeanFactoryPostProcessors、BeanPostProcessors、ApplicationListener,这个等会在源码跟踪的时候在详细阐述。GenericApplicationContext继承了ConfigurableApplicationContext,它有个DefaultListableBeanFactory成员对象,DefaultListableBeanFactory是个很牛逼的beanfactory实现类,可以拿着DefaultListableBeanFactory对象对beanfactory进行很多操作,另外它实现了BeanDefinitionRegistry接口,表示能够将BeanDefinition注册到容器中,下面给出GenericApplicationContext容器的使用代码案例。

 GenericApplicationContext ctx = new GenericApplicationContext();
  XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
  xmlReader.loadBeanDefinitions(new ClassPathResource("applicationContext.xml"));
  PropertiesBeanDefinitionReader propReader = new PropertiesBeanDefinitionReader(ctx);
  propReader.loadBeanDefinitions(new ClassPathResource("otherBeans.properties"));
  ctx.refresh();
AnnotationConfigApplicationContext继承了GenericApplicationContext,支持注解式注入,可以使用Configuration,
Component,Bean注解啥的。 

庖丁解牛之spring源码系列一

二、知识准备

          首先要明确一点,在普通的java程序中,是由一个一个对象构成,生命周期是new出来之后,然后由jvm进行销毁,而在spring中,是由bean构成,spring容器管理的是bean,其中最重要的就是一个叫BeanDefinition的数据结构,它是对bean的描述,在BeanDefinition中定义各种bean的属性,比如这个bean是否是单例,是否懒加载,它的类对象是啥等等,所以spring在容器启动过程中,会先将一个一个类转化成BeanDefinition,并存放到一个beanDefinitionMap的map集合,key为beanDefinition的名字,value为beanDefinition,然后根据这个map集合的BeanDefinition所描述的信息,生成实例对象。然后梳理下我们需要知道的AnnotationConfigApplicationContext的数据结构,AnnotationConfigApplicationContext下有个beanfactory的成员变量,它会在调用AnnotationConfigApplicationContext的构造方法中被创建,类型为defaultListableBeanFactory,beanfactory下有个beanDefinitionMap的成员变量,beanDefinitionMap是一个map集合,key为beanDefinition的名字,value为beanDefinition。

三、启动过程分析

           看下最基本的启动 AnnotationConfigApplicationContext 容器的例子:

@Configuration
@ComponentScan("com.ls")
public class App 
{
    public static void main( String[] args )
    {
        AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(App.class);
        context.getBean("student");
    }
}

@Component
public class Student {
    private  String name;
}

接下来点进去,发现调用了三个方法,this()、register(componentClasses)、refresh()。

	public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
        /**
             1.生成了一个DefaultListableBeanFactory的beanfactory
             2.生成一个reader和scanner对象,用于beandifinition的注册
             3.将一些beanfactoryProcessor注册到beanfactory中,其中有个            
            ConfigurationClassPostProcessor的beanfactoryProcessor这个很关键,后面它用来解析                
         component注解,componentscan注解,import注解等等。
            
        */
		this();
        /**
            将启动的类注册到容器中
        */
		register(componentClasses);
        /**
            调用刷新方法,这个方法很关键,spring最核心的方法,接下来着重分析这个方法
        */
		refresh();
	}

点击refresh方法,进入方法体,发现里面代码其实也不多,但里面很复杂,我先大概讲解下每个方法的作用,大家可以先留个印象。我这里说的把类注册到容器的意思是指这个类的beandifinition put到beandifinitionMap中。

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 容器刷新工作进行的准备
            //设置定时器,容器的状态设置为**
			prepareRefresh();

			// 获取那个beanFactory对象,其实就是上步那个this()方法中创建的                
            //DefaultListableBeanFactory对象,这个代码很简单,下面就不点进去看了。
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 配置beanfactory,比如说classloader,post-processors
			prepareBeanFactory(beanFactory);

			try {
				// 这个是扩展方法,由子类进行重写,对beanfactory进行操作。
				postProcessBeanFactory(beanFactory);

				// 调用那些已经注册在beanfactory中的beanfactoryPostProcessors,前面提到过
                //this方法中,已经注册过一些beanfactoryPostProcessors,就会在这里调用,
                //ConfigurationClassPostProcessor这个调用完成后是会把component注解,    
                //componentscan注解的规则的类注册到beanfactory,也就是说会将student这个
                //类注册到beanfactory中,也就是beandifinitionMap中了。
				invokeBeanFactoryPostProcessors(beanFactory);

				//BeanPostProcessors注册到beanfactory中。
				registerBeanPostProcessors(beanFactory);

				// 这个是用于国际化的,暂时先忽略。
				initMessageSource();

				//初始化事件多播器,用于发布事件
				initApplicationEventMulticaster();

				// 由子类重写,在springboot中就重写这个方法,用于启动嵌入式web容器
				onRefresh();

				// 注册事件监听器。
				registerListeners();

				// 初始化所有单例的实例
				finishBeanFactoryInitialization(beanFactory);
                //结果刷新,发布有关事件,前面注册的监听器可以进行监听,这个方法很复杂,后面的博客在进行讲解。
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

prepareRefresh方法是容器刷新前的准备工作,比如定时器,**标识以及初始化一些源文件的环境属性。

	protected void prepareRefresh() {
		// 开始计时
		this.startupDate = System.currentTimeMillis();
        //设置状态
		this.closed.set(false);
		this.active.set(true);
        //打印debug日志
		if (logger.isDebugEnabled()) {
			if (logger.isTraceEnabled()) {
				logger.trace("Refreshing " + this);
			}
			else {
				logger.debug("Refreshing " + getDisplayName());
			}
		}

		// 初始化配置的环境属性,由子类重写
		initPropertySources();

		// 验证属性
		getEnvironment().validateRequiredProperties();

	}

invokeBeanFactoryPostProcessors方法主要是调用beanfactoryPostProcessors方法,也是一个重点方法,

	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
	}

继续点进PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());会发现这个方法超长,先不慌,其实逻辑很简单。

public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

		
		Set<String> processedBeans = new HashSet<>();
        //可以看上面继承图,这个条件是满足的
		if (beanFactory instanceof BeanDefinitionRegistry) {
            /**
                BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口,
                BeanDefinitionRegistryPostProcessor主要是向beanfactory注册beandifinition 
              的。这里regularPostProcessors存储BeanFactoryPostProcessor的实现类,registryProcessors存储BeanDefinitionRegistryPostProcessor的实现类。
            */
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
				else {
					regularPostProcessors.add(postProcessor);
				}
			}
            //调用步骤为分别顺序调用实现了 PriorityOrdered, Ordered, 其他接口的    
            //BeanDefinitionRegistryPostProcessors
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			//第一步先调用实现了PriorityOrdered的BeanDefinitionRegistryPostProcessors
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();

			// 然后调用实现了Ordered的BeanDefinitionRegistryPostProcessors
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();

			// 最后调用剩余的BeanDefinitionRegistryPostProcessors
			boolean reiterate = true;
			while (reiterate) {
				reiterate = false;
				postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
				for (String ppName : postProcessorNames) {
					if (!processedBeans.contains(ppName)) {
						currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
						processedBeans.add(ppName);
						reiterate = true;
					}
				}
				sortPostProcessors(currentRegistryProcessors, beanFactory);
				registryProcessors.addAll(currentRegistryProcessors);
				invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
				currentRegistryProcessors.clear();
			}

			//然后调用 postProcessBeanFactory中的方法
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

		else {
			
			invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
		}

		
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

		// 隔离开来实现了 PriorityOrdered, 或者Ordered,或者其他的beanFactoryPostProcessor
		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (processedBeans.contains(ppName)) {
				
			}
			else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		//第一步调用实现PriorityOrdered的beanFactoryPostProcessor
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		// 然后调用实现Ordered的beanFactoryPostProcessor
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// 最后调用其他的
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
		beanFactory.clearMetadataCache();
	}

上面有个重要的BeanDefinitionRegistryPostProcessor值得说下,就是前面一直强调的ConfigurationClassPostProcessor,看看它的postProcessBeanDefinitionRegistry方法,里面有个parser.parse(candidates)方法,这个方法解析了@configuration,@componentscan,@import等等注解,继续点进那个parser.parse(candidates)方法,看到有个parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName())的方法,再继续进入processConfigurationClass方法,在继续进入doProcessConfigurationClass方法,终于找到解析注解的地方了。

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
			throws IOException {

		if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
			// Recursively process any member (nested) classes first
			processMemberClasses(configClass, sourceClass);
		}

		//处理 @PropertySource 注解
		for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), PropertySources.class,
				org.springframework.context.annotation.PropertySource.class)) {
			if (this.environment instanceof ConfigurableEnvironment) {
				processPropertySource(propertySource);
			}
			else {
				logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
						"]. Reason: Environment must implement ConfigurableEnvironment");
			}
		}

		//处理 @ComponentScan 注解
		Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
		if (!componentScans.isEmpty() &&
				!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
			for (AnnotationAttributes componentScan : componentScans) {
				// The config class is annotated with @ComponentScan -> perform the scan immediately
				Set<BeanDefinitionHolder> scannedBeanDefinitions =
						this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
				// Check the set of scanned definitions for any further config classes and parse recursively if needed
				for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
					BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
					if (bdCand == null) {
						bdCand = holder.getBeanDefinition();
					}
					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
						parse(bdCand.getBeanClassName(), holder.getBeanName());
					}
				}
			}
		}

		// 解析 @Import 注解
		processImports(configClass, sourceClass, getImports(sourceClass), true);

		// 解析 @ImportResource 注解
		AnnotationAttributes importResource =
				AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
		if (importResource != null) {
			String[] resources = importResource.getStringArray("locations");
			Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
			for (String resource : resources) {
				String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
				configClass.addImportedResource(resolvedResource, readerClass);
			}
		}

		// 解析 @Bean 注解
		Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
		for (MethodMetadata methodMetadata : beanMethods) {
			configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
		}

		
		processInterfaces(configClass, sourceClass);

		// 解析父类
		if (sourceClass.getMetadata().hasSuperClass()) {
			String superclass = sourceClass.getMetadata().getSuperClassName();
			if (superclass != null && !superclass.startsWith("java") &&
					!this.knownSuperclasses.containsKey(superclass)) {
				this.knownSuperclasses.put(superclass, configClass);
				// Superclass found, return its annotation metadata and recurse
				return sourceClass.getSuperClass();
			}
		}

		// 整个解析过程完成
		return null;
	}

四、结语

          这篇先暂时将spring源码介绍到这,下篇将详细介绍finishBeanFactoryInitialization实例化所有单例对象方法,从源码角度分析spring bean的生命周期和spring是如何解决循环依赖等等。