天天看點

SpringIOC源碼解析一

準備

将spring5.1源碼導入到idea編寫幾個測試類

public class Main {

	public static void main(String[] args) {
		ApplicationContext app =	new ClassPathXmlApplicationContext("spring.xml");
	    Text02 text02=	(Text02)app.getBean("text02");
	    text02.text();
	}
}
           
public class Text02 {
	@Autowired
	private MZZ02 mzz02;

	public Text02(){
		System.out.println("構造器Text02");
	}
	public void text(){
		String text02 = mzz02.demo("Text02");
		System.out.println("text02:"+text02);
	}
           
@Component
public class MZZ02 {

	public MZZ02(){
		System.out.println("MZZ02");
	}
	public String demo(String text){
		System.out.println("MZZ02接收:"+text);
		return text+":MZZ02";
	}
}
           

spring.xml配置如下

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xmlns:p="http://www.springframework.org/schema/p"
	   xmlns:mvc="http://www.springframework.org/schema/mvc"
	   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-3.0.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context.xsd
      http://www.springframework.org/schema/mvc
      http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
	<bean id="text02" class="laixx.bean.Text02"></bean>
	//掃包
	<context:component-scan base-package="laixx.cont"/>
</beans>
           

進入ClassPathXmlApplicationContext類

public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {
		super(parent);
		//将配置檔案注入到AbstractRefreshableConfigApplicationContext類的成員屬性中
		setConfigLocations(configLocations);
		//refresh為true
		if (refresh) {
			refresh();
		}
	}
	//這個是上面的setConfigLocations方法,目的是把配置檔案設定到configLocations數組中
		public void setConfigLocations(@Nullable String... locations) {
		if (locations != null) {
			Assert.noNullElements(locations, "Config locations must not be null");
			this.configLocations = new String[locations.length];
			for (int i = 0; i < locations.length; i++) {
				this.configLocations[i] = resolvePath(locations[i]).trim();
			}
		}
		else {
			this.configLocations = null;
		}
	}
           

進入refresh();方法

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

			//為重新整理準備新的 context,設定其啟動日期和活動标志以及執行一些屬性的初始化。
			// 主要是一些準備工作,不是很重要的方法
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			//初始化beanfactroy
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			//準備bean工廠以便在此上下文中使用
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				//允許在上下文子類中對bean工廠進行後處理。
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				//調用在上下文中注冊為bean的工廠處理器
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				//注冊攔截bean建立的bean處理器
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				//為此上下文初始化消息源。
				initMessageSource();

				// Initialize event multicaster for this context.
				//為此上下文初始化事件多主機。
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				//為此上下文初始化事件多主機。初始化特定上下文子類中的其他特殊bean
				onRefresh();

				// Check for listener beans and register them.
				//檢查偵聽器bean并注冊它們。
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				//執行個體化所有剩餘的(非lazy init)單例。
				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...
				//重置Spring核心中常見的内省緩存,因為我們
                //可能不再需要用于單例bean的中繼資料了…
				resetCommonCaches();
			}
		}
	}

           

其中主要的方法有

  1. obtainFreshBeanFactory();//初始化beanfactory,并解析xml
  2. invokeBeanFactoryPostProcessors(beanFactory);//調用在上下文中注冊為bean的工廠處理器
  3. registerBeanPostProcessors(beanFactory);//注冊攔截bean建立的bean處理器
  4. finishBeanFactoryInitialization(beanFactory);//執行個體化所有剩餘的(非lazy init)單例。

繼續閱讀