SpringIOC源码走读

SpringIOC源码走读

  • 简介
  • 准备工作
  • 阅读源码
    • super(parent);
    • setConfigLocations(configLocations);
    • refresh();
      • prepareRefresh()
      • obtainFreshBeanFactory()
      • prepareBeanFactory(beanFactory)
      • postProcessBeanFactory(beanFactory)
      • invokeBeanFactoryPostProcessors(beanFactory)
      • registerBeanPostProcessors(beanFactory)
      • initMessageSource()
      • initApplicationEventMulticaster()
      • onRefresh()
      • registerListeners()
      • finishBeanFactoryInitialization(beanFactory)
      • finishRefresh()
      • 总结

简介

Spring的两大核心就是IOC和AOP,了解其机制可以有效的提高我们对于spring的理解和运用。本篇文章我们先来了解一下Spring IOC的大致实现过程。

准备工作

Spring的常用方式包括XML配置和java配置两种方法,本篇文章我们使用xml配置的方式来了解Spring IOC的机制。

  1. 引入spring依赖 ,这个就不写了;
  2. 编写一个java类用于等下注入到spring;
public class Animal {
   private String name;
   private int sex;
   //...省去get/set和toString
}
  1. 在resource目录下添加一个applicationContext.xml并注入Animal;
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd">
   <bean name="animal" class="com.liyanan.springmvc.Animal">
       <property name="name" value="tiger"/>
       <property name="sex" value="0"/>
   </bean>
</beans>
  1. 编写测试类获取animal,并打印出animal的信息;
public class AnimalTest {
   @Test
   public void testIoc() {
       ClassPathXmlApplicationContext applicationContext =
               new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
       Animal animal = applicationContext.getBean(Animal.class);
       System.out.println(animal);
   }
}

阅读源码

准备工作做完了,现在可以开始跟着debug阅读源码了。
从上面可以知道入口在new ClassPathXmlApplicationContext(“classpath:applicationContext.xml”)中,点进去最终调用如下:

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
			throws BeansException {
		super(parent);
		setConfigLocations(configLocations);
		if (refresh) {
			refresh();
		}
	}

super(parent);

没什么太大的作用,设置一下父级ApplicationContext,这里是null。

setConfigLocations(configLocations);

将配置文件路径保存到configLocations中。

refresh();

这个就是整个Spring Bean加载的核心了,它是ClassPathXmlApplicationContext的父类AbstractApplicationContext的一个方法,顾名思义,用于刷新整个Spring上下文信息,定义了整个Spring上下文加载的流程。

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			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();
			}

prepareRefresh()

initPropertySources();初始化placeholder资源占位符里面的资源。
验证所有必须的properties是否可解析。
初始化earlyApplicationEvents。

obtainFreshBeanFactory()

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (logger.isDebugEnabled()) {
			logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
		}
		return beanFactory;
	}
@Override
	protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			customizeBeanFactory(beanFactory);
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

destroyBeans()和closeBeanFactory()的作用是销毁之前的数据,并重新创建DefaultListableBeanFactory工厂,配置是否支持bean定义重写allowBeanDefinitionOverriding和循环引用allowCircularReferences,默认都是true。

loadBeanDefinitions(beanFactory)加载beanDefinitions,在DefaultBeanDefinitionDocumentReader的doRegisterBeanDefinitions中读取xml中beans节点下的内容。

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);
		}
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}

最终调用DefaultListableBeanFactory.registerBeanDefinition()方法,把bean的名字和定义以键值对的形式保存到DefaultListableBeanFactory的beanDefinitionMap中

XML解析:
AbstractXmlApplicationContext#loadBeanDefinitions方法
1.创建XmlBeanDefinitionReader,构造把DefaultListableBeanFactory作为register传入
2.调用loadBeanDefinitions(beanDefinitionReader)
调用AbstractBeanDefinitionReader的loadBeanDefinitions()方法
调用XmlBeanDefinitionReader的loadBeanDefinitions(EncodedResource encodedResource)方法
调用doLoadBeanDefinitions()方法根据资源文件创建Document对象
调用registerBeanDefinitions(Document doc, Resource resource)注册bean定义
创建DefaultBeanDefinitionDocumentReader对象
调用DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element root)方法,参数为上面的Document对象获取的Element
preProcessXml(root),预处理Xml,在ClassPathXmlApplicationContext的步骤中这里是个空实现
parseBeanDefinitions(root, this.delegate)
在parseDefaultElement()中解析beans,bean,import,alias四个标签,在解析bean的时候获取获取bean里面的attr等属性用于反射装载对象
在BeanDefinitionParserDelegate.java的parseBeanDefinitionElement()中解析bean元素具体属性
bean里面的属性的解析主要在BeanDefinitionParserDelegate.java的parseBeanDefinitionAttributes()里面
从属性值的获取里面可以知道一个bean可以添加哪些属性,比如init-method,destroy-method等等。
bean的构造等等也是在BeanDefinitionParserDelegate.java的parseConstructorArgElements()中等等。。

prepareBeanFactory(beanFactory)

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		beanFactory.setBeanClassLoader(getClassLoader());
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
	    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
		if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
	}

1: 设置classloader
2: 设置Spel表达式解析器
3: 添加特定后置处理器
4: 存储不自动装配的接口Class对象集合,在DefaultListableBeanFactory的父类里面
5: 将一些bean以键值对的形式保存到DefaultListableBeanFactory的resolvableDependencies中注册依赖当注册了依赖解析后,例如当注册了对BeanFactory.class的解析后,当bean的属性注入的时候,一旦检测到属性为BeanFactory类型便会将beanFactory的实例注入进去。
6: 注册特定后置处理器
7: 注册系统相关属性bean

postProcessBeanFactory(beanFactory)

在ClassPathXmlApplicationContext的继承关系里,这里是个空实现。

invokeBeanFactoryPostProcessors(beanFactory)

实例化并且调用所有的BeanFactoryPostProcessor bean工厂后置处理器,如果有指定优先级,会按照优先级进行实例化(就是继承类似PriorityOrdered和Order的接口的BeanFactoryPostProcessor)并调用他们的postProcessBeanDefinitionRegistry。
这个具体是实现在org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()里面,因为代码太长就不贴了。

registerBeanPostProcessors(beanFactory)

把BeanPostProcessor bean后置处理器保存到DefaultListableBeanFactory的父类AbstractBeanFactory的beanPostProcessors中,并调用processor的方法具体是在PostProcessorRegistrationDelegate.registerBeanPostProcessors()方法中registerBeanPostProcessors()BeanProcessor的添加按照是否实现了PriorityOrdered,Ordered和普通的顺序。
所以),我们只需要在配置文件中添加我们自定义的BeanPostProcessor,在前面的obtainFreshBeanFactory()会将我们的后置处理器添加到DefaultListableBeanFactory中。
然后在这里将beanfactory中读取出来的后置处理器添加到DefaultListableBeanFactory的beanPostProcessors集合中

initMessageSource()

这个是加载跟i18n相关的配置。

initApplicationEventMulticaster()

注册ApplicationEventMulticaster。

onRefresh()

在当前过程中也是一个空实现。

registerListeners()

protected void registerListeners() {
		for (ApplicationListener<?> listener : getApplicationListeners()) {			getApplicationEventMulticaster().addApplicationListener(listener);
		}
		String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
		for (String listenerBeanName : listenerBeanNames) {			getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
		}
		Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
		this.earlyApplicationEvents = null;
		if (earlyEventsToProcess != null) {
			for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
				getApplicationEventMulticaster().multicastEvent(earlyEvent);
			}
		}
	}

注册所有的ApplicationListener。
(所以) :我们可以在xml中配置我们自定义的ApplicationListener用于监听我们想要监听的事件根据ApplicationListener的泛型描述 the specific ApplicationEvent subclass to listen to我们可以知道想要监听具体的ApplicationEvent,只需要指定相应的泛型即可。

finishBeanFactoryInitialization(beanFactory)

实例化所有的非懒加载单例bean,并在执行init-method前后调用BeanPostProcessor后置处理器的两个方法具体在AbstractAutowireCapableBeanFactory.initializeBean()中。

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged(new PrivilegedAction() {
				@Override
				public Object run() {
					invokeAwareMethods(beanName, bean);
					return null;
				}
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}

finishRefresh()

容器加载完成,并且通知所有的ApplicationListener该完成事件。

总结

基于Xml配置的SpringIOC的主要流程在于AbstractApplicationContext和DefaultListableBeanFactory
AbstractApplicationContext主要处理Spring容器刷新的过程,包括创建beanfactory,解析bean,配置后置处理器,配置PlaceHolder资源解析器等等。
DefaultListableBeanFactory主要是保存几乎所有的bean和他的beandefinition以及后置处理器等等,算是真正的容器所在。而且我们可以在配置文件中自定义BeanPostProcessor,ApplicationListener等等。

你可能感兴趣的:(javaweb)