Spring源碼分析之ClassPathXmlApplicationContext

第一步,首先寫一個Spring的demo。spring

public class App { public void say(){ System.out.println("cn.com.hxq.App.app()"); } } mybatis

`public class AppTest { public static void main(String[] args) { @SuppressWarnings("resource") ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicaction.xml"); App app = (App)applicationContext.getBean("app"); app.say(); }app

}`ide

`<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">post

<bean id="app" class="cn.com.hxq.App"></bean>

</beans>`測試

第二步,斷點進入ClassPathXmlApplicationContextthis

`public ClassPathXmlApplicationContext( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {.net

super(parent);
	setConfigLocations(configLocations);
	if (refresh) {
		refresh();
	}
}`

這裏的setConfigLocations(configLocations)主要是加載Spring配置文件的位置。 而後看refresh()方法: 首先進入到AbstractApplicationContext的refresh()方法:code

`@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh();xml

// 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) {
			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();
		}
	}
}`

obtainFreshBeanFactory方法以下:它先使用refreshBeanFactory銷燬Bean、BeanFactory,而後分別生成BeanFactory,Bean; 而後利用getBeanFactory獲得一個新生成的BeanFactory,而後返回這個BeanFactory:

loadBeanDefinitions進行Beans的讀取和載入,下面能夠看到找到了Spring的配置文件,而且遍歷對其(這裏只有一個配置文件)進行了分析:

同時能夠看到是,loadBeanDefinitions支持三種類型的參數,Properties說明Spring的配置支持properties文件,而Groovy可能與Groovy語言有關;

最後就是Bean的分析,能夠看到分別調用的下面的方法: loadBeanDefinitions -> doLoadBeanDefinitions(加載Bean) -> registerBeanDefinitions -> doRegisterBeanDefinitions(註冊Bean) -> parseBeanDefinitions(分析全部Beans) ->parseDefaultElement(分析每個Bean元素) 咱們測試時只有一個Bean,標籤爲<bean></bean>, 因此接着會調用下面的方法:

這樣就對Spring中的全部節點<bean><import>等進行了分析。

總的來講ClassPathXmlApplicationContext 這種形式的Spring配置文件的加載主要是下面的過程: A:加載配置文件名到系統配置 B:銷燬已有的Beans和BeanFactory C:建立新的BeanFactory D:加載Beans,分析Bean中的節點,而後加載到BeanFactory,BeanFactory生效。

相關文章
相關標籤/搜索