庖丁解牛之spring源码系列一

       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注解啥的。 

annotationConfigContext继承关系图

二、知识准备

          首先要明确一点,在普通的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是如何解决循环依赖等等。

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读