天天看點

Spring IOC源碼解析

前言

說到Spring,似乎IOC、DI成為了我們的共鳴。工作中,Spring無處不在,如影随形,Spring給我們開發者帶來了一個春天。這麼優秀而美麗的架構,我想,源碼是值得我們去深入學習的。

入口準備

我使用的是spring-framework5.0.x版本,建立一個子產品,作為自己的代碼編寫使用,需要在項目中已有的build.gradle檔案引入一些配置和依賴,如下

plugins {
    id 'java'
}
group 'org.springframework'
version '5.0.16.BUILD-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
    mavenCentral()
}
dependencies {
    //引入本次所需依賴子產品 context子產品包括了beans、aop、core、expression等
    compile(project(":spring-context"))
}
//如果建立的子產品沒有java及resources使用如下進行建立
task 'create-dirs' {
    doLast {
        sourceSets*.java.srcDirs*.each {
            it.mkdirs()
        }
        sourceSets*.resources.srcDirs*.each {
            it.mkdirs()
        }
    }
}
           

appliationContent.xml

<bean id="messageService" name="m1,m2,m3" class="com.whp.service.impl.MessageServiceImpl">
        <!--引入下面id為message的bean-->
		<property name="message" ref="message"/>
	</bean>
	<bean id="message" class="com.whp.bean.Message"/>
           

Message.java

/**
 * @author wanghp
 * @version 1.0
 * @date 2020/7/8 23:19
 */

public class Message {
	public Message() {
		//待會MessageServiceImpl注入Message會列印
		System.out.println("instance Message Bean");
	}
}
           

MessageServiceImpl.java

/**
 * @author wanghp
 * @version 1.0
 * @date 2020/7/8 23:41
 */
public class MessageServiceImpl implements MessageService, BeanNameAware {

	private Message message;

	public MessageServiceImpl() {
		//執行個體化MessageServiceImpl Bean會列印
		System.out.println(" instance MessageServiceImpl Bean");
	}

	public void setMessage(Message message) {
		this.message = message;
	}
	
	@Override
	public String speak() {
		System.out.println(message);
		return "this is my test -->spring ioc ";
	}
    //BeanNameAware回調方法,其實還有BeanClassLoaderAware、BeanFactoryAware
	@Override
	public void setBeanName(String name) {
		System.out.println("BeanNameAware:" + name);
	}
}
           

Junit Test 也就是我們學習源碼的入口,對于學習Spring找到一個入口是非常重要的。

@Test
	public void XMLTest() {
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("appliationContent.xml");
		MessageService messageService = (MessageService) applicationContext.getBean("messageService");
		System.out.println(messageService.speak());
	}
           

這是我建立測試的gradle子產品清單結構

Spring IOC源碼解析

在進入ClassPathXmlApplicationContext構造方法之前,一般我們學習源碼常用的2種方式,如下

Spring IOC源碼解析

1.ClassPathXmlApplicationContext:見名知意,基于類路徑下的xml作為Spring容器初始化

2.AnnotationConfigApplicationContext:類似于SpringBoot啟動加載,将主類傳入構造方法。

這兩種裡面其實都是圍繞refresh()裡的13個方法展開的,本次我們使用第一種,基于xml的方式。

啟動過程分析

public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {
        super(parent);
		setConfigLocations(configLocations);
		if (refresh) {
			//因為 ApplicationContext 建立起來以後,其實我們是可以通過調用 refresh() 這個方法重建的,
			// refresh() 會将原來的 ApplicationContext 銷毀,然後再重新執行一次初始化操作。
			refresh();
		}
	}
           

進入refresh()方法,先對裡面的13個方法有個大概的印象。

@Override
	public void refresh() throws BeansException, IllegalStateException {
		//來個鎖,不然你refresh()方法還沒結束,你又來個啟動或銷毀的操作,豈不是亂套了?????
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			// 準備工作,記錄下容器的啟動時間、标記“已啟動”狀态、處理配置檔案中的占位符
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			// 這步比較關鍵,這步完成後,配置檔案就會解析成一個個 Bean 定義,注冊到 BeanFactory 中,
			// 當然,這裡說的 Bean 還沒有初始化,隻是配置資訊都提取出來了,
			// 注冊也隻是将這些資訊都儲存到了注冊中心(說到底核心是一個 beanName-> beanDefinition 的 map)
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			// 設定 BeanFactory 的類加載器,添加幾個 BeanPostProcessor,手動注冊幾個特殊的 bean
			// 這塊待會會展開說
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				// 【這裡需要知道 BeanFactoryPostProcessor 這個知識點,Bean 如果實作了此接口,
				// 那麼在容器初始化以後,Spring 會負責調用裡面的 postProcessBeanFactory 方法。】

				// 這裡是提供給子類的擴充點,到這裡的時候,所有的 Bean 都加載、注冊完成了,但是都還沒有初始化
				// 具體的子類可以在這步的時候添加一些特殊的 BeanFactoryPostProcessor 的實作類或做點什麼事
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				// 調用 BeanFactoryPostProcessor 各個實作類的 postProcessBeanFactory(factory) 方法
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				// 注冊 BeanPostProcessor 的實作類,注意看和 BeanFactoryPostProcessor 的差別
				// 此接口兩個方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
				// 兩個方法分别在 Bean 初始化之前和初始化之後得到執行。注意,到這裡 Bean 還沒初始化
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				// 初始化目前 ApplicationContext 的 MessageSource,國際化這裡就不展開說了,不然沒完沒了了
				initMessageSource();

				// Initialize event multicaster for this context.
				// 初始化目前 ApplicationContext 的事件廣播器,這裡也不展開了
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				// 從方法名就可以知道,典型的模闆方法(鈎子方法),
				// 具體的子類可以在這裡初始化一些特殊的 Bean(在初始化 singleton beans 之前)
				onRefresh();

				// Check for listener beans and register them.
				// 注冊事件監聽器,監聽器需要實作 ApplicationListener 接口。這也不是我們的重點,過
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				// 初始化所有的 singleton beans
				//(lazy-init 的除外)
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				// 最後,廣播事件,ApplicationContext 初始化完成
				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.
				// 銷毀已經初始化的 singleton 的 Beans,以免有些 bean 會一直占用資源
				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();
			}
		}
	}
           

初始化準備工作

主要還是校驗xml,設定一些初始化值…

protected void prepareRefresh() {
		// 記錄啟動時間,
		// 将 active 屬性設定為 true,closed 屬性設定為 false,它們都是 AtomicBoolean 類型
		this.startupDate = System.currentTimeMillis();
		this.closed.set(false);
		this.active.set(true);

		if (logger.isInfoEnabled()) {
			logger.info("Refreshing " + this);
		}

		// Initialize any placeholder property sources in the context environment.
		initPropertySources();

		// Validate that all properties marked as required are resolvable:
		// see ConfigurablePropertyResolver#setRequiredProperties
		// 校驗 xml 配置檔案
		getEnvironment().validateRequiredProperties();

		// Store pre-refresh ApplicationListeners...
		if (this.earlyApplicationListeners == null) {
			this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
		} else {
			// Reset local application listeners to pre-refresh state.
			this.applicationListeners.clear();
			this.applicationListeners.addAll(this.earlyApplicationListeners);
		}
		
		// Allow for the collection of early ApplicationEvents,
		// to be published once the multicaster is available...
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}
           

解析xml,注冊bean,初始化BeanFactory

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		// 關閉舊的 BeanFactory (如果有),建立新的 BeanFactory,加載 Bean 定義、注冊 Bean 等等
		refreshBeanFactory();
		// 傳回剛剛建立的 BeanFactory
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (logger.isDebugEnabled()) {
			logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
		}
		return beanFactory;
	}
		@Override
	protected final void refreshBeanFactory() throws BeansException {
		// 如果 ApplicationContext 中已經加載過 BeanFactory 了,銷毀所有 Bean,關閉 BeanFactory
		// 注意,應用中 BeanFactory 本來就是可以多個的,這裡可不是說應用全局是否有 BeanFactory,而是目前
		// ApplicationContext 是否有 BeanFactory
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			// 初始化一個 DefaultListableBeanFactory,為什麼用這個,我們馬上說。
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			// 用于 BeanFactory 的序列化,我想不部分人應該都用不到
			beanFactory.setSerializationId(getId());

			// 下面這兩個方法很重要,别跟丢了,具體細節之後說
			// 1.設定 BeanFactory 的兩個配置屬性:是否允許 Bean 覆寫、是否允許循環引用
			customizeBeanFactory(beanFactory);

			//2.加載 Bean 到 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);
		}
	}
           

到了loadBeanDefinitions方法,他傳入了個beanFactory,通過方法名,我們可以大概猜測到這個是加載BeanDefinition的,還是多個BeanDefinition,然後可能是放到beanFactory裡。

對于BeanFactory也就是Bean工廠和這裡的實作類DefaultListableBeanFactory肯定是有聯系的,我們先來看一下這兩者的UML圖:

Spring IOC源碼解析

DefaultListableBeanFactory:由圖我們可以發現,它幾乎擁有了上面所有的能力,它的頂層幾乎要麼是接口,要麼是抽象類,而對于DefaultListableBeanFactory而言,它就是一個實作類,擁有了頂層所有的能力,這也就是為什麼DefaultListableBeanFactory是整個spring ioc的始祖,研究透它的前生今世對我們了解spring ioc的概念有着重要的作用。

BeanFactory:沒什麼好講的,大緻了解為Bean工廠吧,裡面的一些方法無非就是通過各種傳參類型擷取Bean。

BeanDefinitionRegistry:如果一個類是BeanFactory的實作類,那麼它就需要實作BeanDefinitionRegistry接口,原因很簡單,Bean工廠需要個人幫他把外部的比如xml配置的,或者基于注解掃面的bean注冊到Bean工廠,每個角色都有自己的職責,而不是BeanFactory什麼都去做,展現了接口與的單一職責設計原則。

Q:到這裡,那麼會有一個面試題,BeanFactory和FactoryBean的差別?

A:先看個FactoryBean的幾個實作類,相信你差不多知道答案了,

Spring IOC源碼解析

FactoryBean其實可以了解為Spring的一種靈活的應用,先看個簡單案例:

xml:
<bean id="person" class="com.whp.service.impl.PersonFactoryBean">
				<property name="personInfo" value="wanghp,100"/>
</bean>

PersonFactoryBean.java  
public class PersonFactoryBean implements FactoryBean<Person> {
	protected final Log logger = LogFactory.getLog(getClass());

	private String personInfo;

	public String getPersonInfo() {
		return personInfo;
	}

	public void setPersonInfo(String personInfo) {
		this.personInfo = personInfo;
	}

	@Override
	public Person getObject() throws Exception {
		if (logger.isDebugEnabled()) {
			logger.debug("進入getObject");
		}
		logger.info("進入getObject");
		Person person = new Person();
		String[] split = personInfo.split(",");
		person.setName(split[0]);
		person.setAge(Integer.parseInt(split[1]));
		return person;
	}

	@Override
	public Class<?> getObjectType() {
		logger.info("進入getObjectType");
		return Person.class;
	}
}
測試:
	@org.junit.Test
	public void FactoryBeanTest() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("appliationContent.xml");
		Object person = applicationContext.getBean("&person");
		System.out.println(person);//結果輸出:[email protected]
		Object personBean = applicationContext.getBean("person");//結果輸出:[email protected]
		System.out.println(personBean);
		((Person) personBean).message();
		//在Person類輸出屬性資訊為:wanghp今年100歲啦
	}
           

如果你在PersonFactoryBean的getObject方法,比如我把設定年齡改成person.setAge(3);

sout為:wanghp今年3歲啦 當然我也不可能3歲哈哈,題外話

是以一個FactoryBean和你想要的普通Bean就是一念之間("&"),如果想具體了解這兩者差別,小夥伴們可以自行查閱相關資料,我們回歸正軌…

下面開始進入驗證階段。

AbstractXmlApplicationContext.java

@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// Configure the bean definition reader with this context's
		// resource loading environment.
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		// Allow a subclass to provide custom initialization of the reader,
		// then proceed with actually loading the bean definitions.
		initBeanDefinitionReader(beanDefinitionReader);
		//重點在這裡
		loadBeanDefinitions(beanDefinitionReader);
	}
           

上面無非就是設定beanDefinitionReader的環境,加載資源,實體分解器EntityResolver,有個概念為SAX,你就把它當作是一個将xml解析到javaBean的東西,進入loadBeanDefinitions方法

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			//這裡不會進來,因為getConfigResources()就是傳回Null
			reader.loadBeanDefinitions(configResources);
		}
		//這個就是拿到我們前面ClassPathXmlApplicationContext構造傳進來的xml檔案名
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			//走這裡
			reader.loadBeanDefinitions(configLocations);
		}
	}
           

進入loadBeanDefinitions方法

@Override
	public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
		Assert.notNull(locations, "Location array must not be null");
		int counter = 0;
		// 注意這裡是個 for 循環,也就是每個檔案是一個 resource
		for (String location : locations) {
			counter += loadBeanDefinitions(location);
		}
		// 最後傳回 counter,表示總共加載了多少的 BeanDefinition
		return counter;
	}
           

再進入loadBeanDefinitions方法,下面這段代碼是不是頭皮發麻了,看我标記todo 那2行,前面通過

location也就是字元串"appliationContent.xml",把xml加載進來程式設計一個Resource,因為配置檔案能傳多個,是以是個數組,然後将其傳到loadBeanDefinitions進行解析

@Override
	public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
		return loadBeanDefinitions(location, null);
	}
		public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
		ResourceLoader resourceLoader = getResourceLoader();
		if (resourceLoader == null) {
			throw new BeanDefinitionStoreException(
					"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
		}

		if (resourceLoader instanceof ResourcePatternResolver) {
			// Resource pattern matching available.
			try {
			  //todo 核心部分在這裡
				Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
				int loadCount = loadBeanDefinitions(resources);
				if (actualResources != null) {
					for (Resource resource : resources) {
						actualResources.add(resource);
					}
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
				}
				return loadCount;
			}
			catch (IOException ex) {
				throw new BeanDefinitionStoreException(
						"Could not resolve bean definition resource pattern [" + location + "]", ex);
			}
		}
		else {
			// Can only load single resources by absolute URL.
			Resource resource = resourceLoader.getResource(location);
			int loadCount = loadBeanDefinitions(resource);
			if (actualResources != null) {
				actualResources.add(resource);
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
			}
			return loadCount;
		}
	}
           

進入loadBeanDefinitions方法

@Override
	public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
		Assert.notNull(resources, "Resource array must not be null");
		int counter = 0;
		for (Resource resource : resources) {
			//看這裡
			counter += loadBeanDefinitions(resource);
		}
		return counter;
	}
           

再進去,然後到了這裡,因為我們解析是xml,是以這個方法所在類為XmlBeanDefinitionReader

将傳進來的resource構造放入EncodedResource,然後拿到InputStream二進制流,将其封裝為一個InputSource對象,然後丢到doLoadBeanDefinitions方法,resource通過get又回到了原來姿态

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		Assert.notNull(encodedResource, "EncodedResource must not be null");
		if (logger.isInfoEnabled()) {
			logger.info("Loading XML bean definitions from " + encodedResource);
		}
        // 用一個 ThreadLocal 來存放配置檔案資源
		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
		System.out.println(Thread.currentThread().getName());
		if (currentResources == null) {
			currentResources = new HashSet<>(4);
			this.resourcesCurrentlyBeingLoaded.set(currentResources);
		}
		System.out.println("now threadName :"+Thread.currentThread().getName());
		if (!currentResources.add(encodedResource)) {
			System.out.println("insert if----"+Thread.currentThread().getName());
			throw new BeanDefinitionStoreException(
					"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
		}
		System.out.println("out if ----"+Thread.currentThread().getName());
		try {
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				// 核心部分是這裡,往下面看
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			} finally {
				inputStream.close();
			}
		} catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"IOException parsing XML document from " + encodedResource.getResource(), ex);
		} finally {
			currentResources.remove(encodedResource);
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
			}
		}
	}
           

進入doLoadBeanDefinitions

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
		  //此處省略try{}catch代碼
			// 這裡就不看了,将 xml 檔案轉換為 Document 對象
			Document doc = doLoadDocument(inputSource, resource);
			//TODO 解析及注冊 BeanDefinition
			return registerBeanDefinitions(doc, resource);
           

進入registerBeanDefinitions,原來的inputSource變為了Document,而resource還是原來的配方

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
	//TODO 單一職責原則,DefaultDocumentLoader執行得到doc,而這個BeanDefinitionDocumentReader就是邏輯處理類
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		//todo 注冊該xml前Bean 的數量
		int countBefore = getRegistry().getBeanDefinitionCount();
		//todo 加載及注冊Bean
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		//todo 記錄本次加載的 BeanDefinition 個數
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}
           

繼續進入registerBeanDefinitions

@Override
	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		logger.debug("Loading bean definitions");
		Element root = doc.getDocumentElement();
		// 前面都是XML解析的準備階段
		// 核心部分開始
		// 從 xml 根節點開始解析檔案
		doRegisterBeanDefinitions(root);
	}
           

到這裡,核心解析xml部分來了哈,進入doRegisterBeanDefinitions方法,傳入的是Element

protected void doRegisterBeanDefinitions(Element root) {
		BeanDefinitionParserDelegate parent = this.delegate;
		//TODO 委托給delegate解析    
		this.delegate = createDelegate(getReaderContext(), root, parent);
		//判斷目前Beans節點是否是預設命名空間
		if (this.delegate.isDefaultNamespace(root)) {
			// 這塊說的是根節點 <beans ... profile="dev" /> 中的 profile 是否是目前環境需要的,
			// 如果目前環境配置的 profile 不包含此 profile,那就直接 return 了,不對此 <beans /> 解析
		
			//擷取beans節點的profile屬性       "profile"
			String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
			if (StringUtils.hasText(profileSpec)) {
				//可以使用逗号或分号将目前beans标簽指定為多個profile類型
				String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
						profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
				//判斷目前beans标簽的profile是否被激活
				if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
					if (logger.isInfoEnabled()) {
						logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
								"] not matching: " + getReaderContext().getResource());
					}
					return;
				}
			}
		}
		//解析前處理,留給子類實作
		//pre和post裡面目前沒有具體實作,模闆設計模式,一個類要麼面向繼承設計,要麼就用final修飾
		preProcessXml(root);
		//看這裡
		parseBeanDefinitions(root, this.delegate);
		postProcessXml(root);
		this.delegate = parent;
	}
           

進入parseBeanDefinitions方法,主要就是Element和Node一些轉換,判斷,目前我們xml是預設标簽配置的,也就是bean開頭,當然你也可以自定義配置,這需要去寫自己的schemas及xsd

// default namespace 涉及到的就四個标簽 <import />、<alias />、<bean /> 和 <beans />,
    // 其他的屬于 custom 的
	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		//TODO 對bean
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {
						parseDefaultElement(ele, delegate);
					} else {
						delegate.parseCustomElement(ele);
					}
				}
			}
		} else {
			delegate.parseCustomElement(root);
		}
	}
           

進入parseDefaultElement方法,就到了我們解析标簽了,判斷預設标簽屬于什麼類型,找到對應解析方法,我們目前是解析标簽的

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			//解析import标簽
			importBeanDefinitionResource(ele);
		} else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			//解析alias标簽
			processAliasRegistration(ele);
		} else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			//解析bean标簽   看這裡
			processBeanDefinition(ele, delegate);
		} else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}
           

進入解析bean的對應方法,重點來了哈,各位提提精神…

到這裡,才是真正的解析單個bean标簽,變為一個javaBean,也就是我們這裡的bdHolder,然後調用registerBeanDefinition注測我們的BeanDefinition,後面我們大概會講一下這些概念,幫小夥伴們梳理一下這塊内容

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		// 将 <bean /> 節點轉換為 BeanDefinitionHolder,就是上面說的一堆
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		//TODO 終于出來了,紀念一下目前時間 2020-05-19 15:27
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// 将bdHolder注冊到bean工廠
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			} catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			// 注冊完成後,發送事件
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}
           

先看如何将一個标簽内容變為BeanDefinitionHolder,進入parseBeanDefinitionElement方法,他這裡使用的是BeanDefinitionParserDelegate解析器

@Nullable
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
		//解析 id屬性
		String id = ele.getAttribute(ID_ATTRIBUTE);
		//解析 name屬性
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
		//分割 name屬性
		List<String> aliases = new ArrayList<>();
		// 将 name 屬性的定義按照 “逗号、分号、空格” 切分,形成一個 别名清單數組,
		// 當然,如果你不定義 name 屬性的話,就是空的了
		if (StringUtils.hasLength(nameAttr)) {
			String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			aliases.addAll(Arrays.asList(nameArr));
		}

		String beanName = id;
		// 如果沒有指定id, 那麼用别名清單的第一個名字作為beanName
		if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
			beanName = aliases.remove(0);
			if (logger.isDebugEnabled()) {
				logger.debug("No XML 'id' specified - using '" + beanName +
						"' as bean name and " + aliases + " as aliases");
			}
		}

		if (containingBean == null) {
			checkNameUniqueness(beanName, aliases, ele);
		}
		// 根據 <bean ...>...</bean> 中的配置建立 BeanDefinition,然後把配置中的資訊都設定到執行個體中,
		// 細節後面細說,先知道下面這行結束後,一個 BeanDefinition 執行個體就出來了。
		// 注意: 是一個 !!!!!!!!!!!!!!!!
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
		// 到這裡,整個 <bean /> 标簽就算解析結束了,一個 BeanDefinition 就形成了。
		if (beanDefinition != null) {
			// 如果都沒有設定 id 和 name,那麼此時的 beanName 就會為 null,進入下面這塊代碼産生
			if (!StringUtils.hasText(beanName)) {
				try {
					if (containingBean != null) { // 按照我們的思路,這裡 containingBean 是 null 的
						beanName = BeanDefinitionReaderUtils.generateBeanName(
								beanDefinition, this.readerContext.getRegistry(), true);
					} else {
						beanName = this.readerContext.generateBeanName(beanDefinition);
						// Register an alias for the plain bean class name, if still possible,
						// if the generator returned the class name plus a suffix.
						// This is expected for Spring 1.2/2.0 backwards compatibility.
						String beanClassName = beanDefinition.getBeanClassName();
						if (beanClassName != null &&
								beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
								!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
							// 把 beanClassName 設定為 Bean 的别名
							aliases.add(beanClassName);
						}
					}
					if (logger.isDebugEnabled()) {
						logger.debug("Neither XML 'id' nor 'name' specified - " +
								"using generated bean name [" + beanName + "]");
					}
				} catch (Exception ex) {
					error(ex.getMessage(), ele);
					return null;
				}
			}
			String[] aliasesArray = StringUtils.toStringArray(aliases);
			// 傳回 BeanDefinitionHolder
			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
		}
		return null;
	}         
           

上面看注釋就好,然後核心方法是parseBeanDefinitionElement,傳回AbstractBeanDefinition的對象,先講講AbstractBeanDefinition,UML如下

Spring IOC源碼解析

至于這幾個類的用法小夥伴們可以自行百度,網上這些類說明及注釋很全面,隻需要記住AbstractBeanDefinition是個抽象類,提供相對比較全面的屬性,然後下面是常用的3個實作類。

進入parseBeanDefinitionElement方法,主要就是解析标簽的一些屬性放入到BeanDefinition中,bean标簽沒有的會采用預設的值,比如scope=“singleton”

@Nullable
	public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, @Nullable BeanDefinition containingBean) {

		this.parseState.push(new BeanEntry(beanName));
		//解析class屬性
		String className = null;
		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
		}
		String parent = null;
		if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
			parent = ele.getAttribute(PARENT_ATTRIBUTE);
		}

		try {
			//建立用于承載屬性的 AbstractBeanDefinition 類型的 GenericBeanDefinition
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);
			//寫死解析預設 bean 的各種屬性
			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);

			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
			/**
			 * 下面的一堆是解析 <bean>......</bean> 内部的子元素,
			 * 解析出來以後的資訊都放到 bd 的屬性中
			 */

			//解析中繼資料
			parseMetaElements(ele, bd);
			//解析 lookup-method 屬性
			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
			//解析 replaced-method 屬性
			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

			//總結:無論look-up replaced-method都是構造了一個MethodOverride,
			// 并最終記錄在了AbstractBeanDefinition的methodOverrides屬性中
			//解析構造函數參數
			parseConstructorArgElements(ele, bd);
			//解析 property 子元素
			parsePropertyElements(ele, bd);
			//解析 qualifier 子元素
			parseQualifierElements(ele, bd);

			bd.setResource(this.readerContext.getResource());
			bd.setSource(extractSource(ele));

			return bd;
		} catch (ClassNotFoundException ex) {
			error("Bean class [" + className + "] not found", ele, ex);
		} catch (NoClassDefFoundError err) {
			error("Class that bean class [" + className + "] depends on not found", ele, err);
		} catch (Throwable ex) {
			error("Unexpected failure during bean definition parsing", ele, ex);
		} finally {
			this.parseState.pop();
		}

		return null;
	}
           

總結一下parseBeanDefinitionElement方法如何産生BeanDefinitionHolder對象的

1.AbstractBeanDefinition:解析bean标簽完了将标簽屬性封裝在一個(也就是bd)

2.beanName:beanName隻有一個,别名可以有多個,兩者都是關聯起來的。

3.aliasesArray:别名集合,對應bean标簽的name屬性

然後将1,2,3構造封裝在BeanDefinitionHolder裡

注冊BeanDefinition

進入 BeanDefinitionReaderUtils 的registerBeanDefinition方法

/**
	 * 從下面面的代碼可以看出,解析的 beanDefinition 都會被注冊到 ,
	 * BeanDefinitionRegistry 類型的執行個體 registry 中,而對于 beanDefinition
	 * 的注冊分成了兩部分:通過 beanName 的注冊以及通過别名的注冊。
	 */
	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		//使用 beanName 做唯一辨別注冊
		String beanName = definitionHolder.getBeanName();
		//1.通過 beanName 注冊 BeanDefinition
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		//2.注冊所有的别名
		// 如果還有别名的話,也要根據别名全部注冊一遍,不然根據别名就會找不到 Bean 了
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}
	}
           

看看如何将BeanDefinitionHolder的BeanDefinition 注冊吧,其實這部分看起來比較常,正常邏輯會走else的this.beanDefinitionMap.put(beanName, beanDefinition);這行代碼,看到這裡,就知道前面為什麼會傳回一個DefaultListableBeanFactory的bean工廠了吧,是以最後注冊BeanDefinition是在Bean的始祖DefaultListableBeanFactory裡面注冊的,應證了我們最初的結論,這其實就是個推導到論證的過程。這部分目前隻是單個bean注冊到bean工廠的beanDefinitionMap過程。

@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");

		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				//注冊前的最後一次校驗,這裡的校驗不同于之前的XML校驗,
				// 但是此校驗非彼校驗,之前的校驗時針對于 XML 格式的校驗,而此時的校驗時針是對于 AbstractBean- Definition 的 methodOverrides 屬性的。
				//要是對于 AbstractBeanDefinition 屬性中的**
				//校驗 methodOverrides 是否與工廠方法并存或者**
				((AbstractBeanDefinition) beanDefinition).validate();
			} catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}
		//因為 beanDefinitionMap 是全局變量,這裡定會存在并發通路
		// old? 還記得 “允許 bean 覆寫” 這個配置嗎?allowBeanDefinitionOverriding
		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		// 處理重複名稱的 Bean 定義的情況
		if (existingDefinition != null) {
			if (!isAllowBeanDefinitionOverriding()) {
				// 如果不允許覆寫的話,抛異常
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
								"': There is already [" + existingDefinition + "] bound.");
			} else if (existingDefinition.getRole() < beanDefinition.getRole()) {
				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
				// log...用架構定義的 Bean 覆寫使用者自定義的 Bean
				if (logger.isWarnEnabled()) {
					logger.warn("Overriding user-defined bean definition for bean '" + beanName +
							"' with a framework-generated bean definition: replacing [" +
							existingDefinition + "] with [" + beanDefinition + "]");
				}
			} else if (!beanDefinition.equals(existingDefinition)) {
				//用新的 Bean 覆寫舊的 Bean
				if (logger.isInfoEnabled()) {
					logger.info("Overriding bean definition for bean '" + beanName +
							"' with a different definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			} else {
				//	用同等的 Bean 覆寫舊的 Bean,這裡指的是 equals 方法傳回 true 的 Bean
				if (logger.isDebugEnabled()) {
					logger.debug("Overriding bean definition for bean '" + beanName +
							"' with an equivalent definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			//覆寫
			this.beanDefinitionMap.put(beanName, beanDefinition);
		} else {
			// 判斷是否已經有其他的 Bean 開始初始化了.
			// 注意,"注冊Bean" 這個動作結束,Bean 依然還沒有初始化,我們後面會有大篇幅說初始化過程,
			// 在 Spring 容器啟動的最後,會 預初始化 所有的 singleton beans
			if (hasBeanCreationStarted()) {
				// Cannot modify startup-time collection elements anymore (for stable iteration)
				synchronized (this.beanDefinitionMap) {
					this.beanDefinitionMap.put(beanName, beanDefinition);
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					if (this.manualSingletonNames.contains(beanName)) {
						Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
						updatedSingletons.remove(beanName);
						this.manualSingletonNames = updatedSingletons;
					}
				}
			} else {
				// 最正常的應該是進到這個分支。
				// Still in startup registration phase
				// 将 BeanDefinition 放到這個 map 中,這個 map 儲存了所有的 BeanDefinition
				this.beanDefinitionMap.put(beanName, beanDefinition);
				// 這是個 ArrayList,是以會按照 bean 配置的順序儲存每一個注冊的 Bean 的名字
				this.beanDefinitionNames.add(beanName);
				// 這是個 LinkedHashSet,代表的是手動注冊的 singleton bean,
				// 注意這裡是 remove 方法,到這裡的 Bean 當然不是手動注冊的
				// 手動指的是通過調用以下方法注冊的 bean :
				//     registerSingleton(String beanName, Object singletonObject)
				// 這不是重點,解釋隻是為了不讓大家疑惑。Spring 會在後面"手動"注冊一些 Bean,
				// 如 "environment"、"systemProperties" 等 bean,我們自己也可以在運作時注冊 Bean 到容器中的
				this.manualSingletonNames.remove(beanName);
			}
			// 這個不重要,在預初始化的時候會用到,不必管它。
			this.frozenBeanDefinitionNames = null;
		}

		if (existingDefinition != null || containsSingleton(beanName)) {
			//TODO 重置所有的beanName對應的緩存
			resetBeanDefinition(beanName);
		}
	}
           

不知道到了這裡,還有多少小夥伴在堅持呢?

上面無非就是加載配置檔案讀标簽然後将标簽内容放入到BeanDefinition中,然後注冊到beanFactory的beanDefinitionMap,說到這個注冊,小夥伴千萬别搞懵了,這裡注冊的是BeanDefinition,還不是我們平常用的Spring管理的Bean,對于BeanDefinition,他隻是一個暫時存儲bean标簽資訊,如果這個bean是單例還是多例,是懶加載還是非攔截在,看下面代碼就明白了

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

	// 我們可以看到,預設隻提供 sington 和 prototype 兩種,
	// 很多讀者可能知道還有 request, session, globalSession, application, websocket 這幾種,
	// 不過,它們屬于基于 web 的擴充。
	String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;

	String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

	int ROLE_APPLICATION = 0;

	int ROLE_SUPPORT = 1;

	int ROLE_INFRASTRUCTURE = 2;

	// 設定父 Bean,這裡涉及到 bean 繼承,不是 java 繼承。請參見附錄的詳細介紹
	// 一句話就是:繼承父 Bean 的配置資訊而已
	void setParentName(@Nullable String parentName);

	// 擷取父 Bean
	@Nullable
	String getParentName();

	//設定 Bean的類名稱,将來是要通過反射來生成執行個體的
	void setBeanClassName(@Nullable String beanClassName);

	// 擷取 Bean 的類名稱
	@Nullable
	String getBeanClassName();

	// 設定 bean 的 scope
	void setScope(@Nullable String scope);

	@Nullable
	String getScope();

	// 設定是否懶加載
	void setLazyInit(boolean lazyInit);

	boolean isLazyInit();

	// 設定該 Bean 依賴的所有的 Bean,注意,這裡的依賴不是指屬性依賴(如 @Autowire 标記的),
	// 是 depends-on="" 屬性設定的值。
	void setDependsOn(@Nullable String... dependsOn);

	// 傳回該 Bean 的所有依賴
	@Nullable
	String[] getDependsOn();

	// 設定該 Bean 是否可以注入到其他 Bean 中,隻對根據類型注入有效,
	// 如果根據名稱注入,即使這邊設定了 false,也是可以的
	void setAutowireCandidate(boolean autowireCandidate);

	// 該 Bean 是否可以注入到其他 Bean 中
	boolean isAutowireCandidate();
	// 主要的。同一接口的多個實作,如果不指定名字的話,Spring 會優先選擇設定 primary 為 true 的 bean
	void setPrimary(boolean primary);

	// 是否是 primary 的
	boolean isPrimary();

	// 如果該 Bean 采用工廠方法生成,指定工廠名稱。對工廠不熟悉的讀者,請參加附錄
	// 一句話就是:有些執行個體不是用反射生成的,而是用工廠模式生成的
	void setFactoryBeanName(@Nullable String factoryBeanName);

	// 擷取工廠名稱
	@Nullable
	String getFactoryBeanName();

	// 指定工廠類中的 工廠方法名稱
	void setFactoryMethodName(@Nullable String factoryMethodName);

	// 擷取工廠類中的 工廠方法名稱
	@Nullable
	String getFactoryMethodName();

	// 構造器參數
	ConstructorArgumentValues getConstructorArgumentValues();

	default boolean hasConstructorArgumentValues() {
		return !getConstructorArgumentValues().isEmpty();
	}

	// Bean 中的屬性值,後面給 bean 注入屬性值的時候會說到
	MutablePropertyValues getPropertyValues();


	default boolean hasPropertyValues() {
		return !getPropertyValues().isEmpty();
	}

	// 是否 singleton
	boolean isSingleton();

	// 是否 prototype
	boolean isPrototype();


	// 如果這個 Bean 是被設定為 abstract,那麼不能執行個體化,
	// 常用于作為 父bean 用于繼承,其實也很少用......
	boolean isAbstract();

	int getRole();

	@Nullable
	String getDescription();

	@Nullable
	String getResourceDescription();

	@Nullable
	BeanDefinition getOriginatingBeanDefinition();

}
           

準備BeanFactory

這斷你可以了解為前面beanFactory不是拿到了,這裡是填充一下其他的東西,把要的放進來,不要的忽視就ok了,具體看注釋

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Tell the internal bean factory to use the context's class loader etc.
		// 設定 BeanFactory 的類加載器,我們知道 BeanFactory 需要加載類,也就需要類加載器,
		// 這裡設定為加載目前 ApplicationContext 類的類加載器
		beanFactory.setBeanClassLoader(getClassLoader());
		// 設定 BeanExpressionResolver
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));

		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
		// 添加一個 BeanPostProcessor,這個 processor 比較簡單:
		// 實作了 Aware 接口的 beans 在初始化的時候,這個 processor 負責回調,
		// 這個我們很常用,如我們會為了擷取 ApplicationContext 而 implement ApplicationContextAware
		// 注意:它不僅僅回調 ApplicationContextAware,
		//   還會負責回調 EnvironmentAware、ResourceLoaderAware 等,看下源碼就清楚了
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

		// 下面幾行的意思就是,如果某個 bean 依賴于以下幾個接口的實作類,在自動裝配的時候忽略它們,
		// Spring 會通過其他方式來處理這些依賴。
		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 interface not registered as resolvable type in a plain factory.
		// MessageSource registered (and found for autowiring) as a bean.
		/**
		 * 下面幾行就是為特殊的幾個 bean 指派,如果有 bean 依賴了以下幾個,會注入這邊相應的值,
		 * 之前我們說過,"目前 ApplicationContext 持有一個 BeanFactory",這裡解釋了第一行。
		 * ApplicationContext 還繼承了 ResourceLoader、ApplicationEventPublisher、MessageSource
		 * 是以對于這幾個依賴,可以指派為 this,注意 this 是一個 ApplicationContext
		 * 那這裡怎麼沒看到為 MessageSource 指派呢?那是因為 MessageSource 被注冊成為了一個普通的 bean
		 */
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

		// Register early post-processor for detecting inner beans as ApplicationListeners.
		// 這個 BeanPostProcessor 也很簡單,在 bean 執行個體化後,如果是 ApplicationListener 的子類,
		// 那麼将其添加到 listener 清單中,可以了解成:注冊 事件監聽器
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// Detect a LoadTimeWeaver and prepare for weaving, if found.
		// 這裡涉及到特殊的 bean,名為:loadTimeWeaver,這不是我們的重點,忽略它
		// tips: ltw 是 AspectJ 的概念,指的是在運作期進行織入,這個和 Spring AOP 不一樣,
		//    感興趣的讀者請參考我寫的關于 AspectJ 的另一篇文章 https://www.javadoop.com/post/aspectj
		if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// Set a temporary ClassLoader for type matching.
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
		/**
		 * 從下面幾行代碼我們可以知道,Spring 往往很 "智能" 就是因為它會幫我們預設注冊一些有用的 bean,
		 * 我們也可以選擇覆寫
		 */

		// Register default environment beans.
		// 如果沒有定義 "environment" 這個 bean,那麼 Spring 會 "手動" 注冊一個
		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
		}
		// 如果沒有定義 "systemProperties" 這個 bean,那麼 Spring 會 "手動" 注冊一個
		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
		}
		// 如果沒有定義 "systemEnvironment" 這個 bean,那麼 Spring 會 "手動" 注冊一個
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
	}
           

接下來我們開始進入到finishBeanFactoryInitialization這個方法,關于前面的幾個方法這邊再貼一下

// 這裡是提供給子類的擴充點,到這裡的時候,所有的 Bean 都加載、注冊完成了,但是都還沒有初始化
				// 具體的子類可以在這步的時候添加一些特殊的 BeanFactoryPostProcessor 的實作類或做點什麼事
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				// 調用 BeanFactoryPostProcessor 各個實作類的 postProcessBeanFactory(factory) 方法
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				// 注冊 BeanPostProcessor 的實作類,注意看和 BeanFactoryPostProcessor 的差別
				// 此接口兩個方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
				// 兩個方法分别在 Bean 初始化之前和初始化之後得到執行。注意,到這裡 Bean 還沒初始化
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				// 初始化目前 ApplicationContext 的 MessageSource,國際化這裡就不展開說了,不然沒完沒了了
				initMessageSource();

				// Initialize event multicaster for this context.
				// 初始化目前 ApplicationContext 的事件廣播器,這裡也不展開了
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				// 從方法名就可以知道,典型的模闆方法(鈎子方法),
				// 具體的子類可以在這裡初始化一些特殊的 Bean(在初始化 singleton beans 之前)
				onRefresh();

				// Check for listener beans and register them.
				// 注冊事件監聽器,監聽器需要實作 ApplicationListener 接口。這也不是我們的重點,直接過
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				// 初始化所有的 singleton beans
				//(lazy-init 的除外)
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				// 最後,廣播事件,ApplicationContext 初始化完成
				finishRefresh();
           

進入到本次IOC源碼的高潮部分了,請大家系好安全帶,即将發車…

執行個體化Bean

進入AbstractApplicationContext的finishBeanFactoryInitialization方法

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// Initialize conversion service for this context.
		// 首先,初始化名字為 conversionService 的 Bean。
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
			beanFactory.setConversionService(
					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
		}

		// Register a default embedded value resolver if no bean post-processor
		// (such as a PropertyPlaceholderConfigurer bean) registered any before:
		// at this point, primarily for resolution in annotation attribute values.
		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
		}

		// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
		// 這是 AspectJ 相關的内容,放心跳過吧
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}

		// Stop using the temporary ClassLoader for type matching.
		beanFactory.setTempClassLoader(null);

		// Allow for caching all bean definition metadata, not expecting further changes.
		// 到這一步的時候,Spring 已經開始預初始化 singleton beans 了,
		beanFactory.freezeConfiguration();

		// Instantiate all remaining (non-lazy-init) singletons.
		// 看這裡  開始初始化
		beanFactory.preInstantiateSingletons();
	}
           

進入preInstantiateSingletons方法,拿到剛剛beanFactory注冊BeanDefinition的名字集合,周遊,可能存在繼承關系,如果有則合并,然後判斷bean是否是抽象的單例的,懶加載的,滿足要求然後再判斷該bean是否是個FactoryBean,isFactoryBean方法主要還是通過instanceof來判斷的,前面那道面試題我們已經講了FactoryBean和普通Bean的差別,取得話就在于beanName前面有無"&"

@Override
	public void preInstantiateSingletons() throws BeansException {
		if (logger.isDebugEnabled()) {
			logger.debug("Pre-instantiating singletons in " + this);
		}
		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		// this.beanDefinitionNames 儲存了所有的 beanNames
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		// 下面這個循環,觸發所有的非懶加載的 singleton beans 的初始化操作
		for (String beanName : beanNames) {
			// 合并父 Bean 中的配置,注意 <bean id="" class="" parent="" /> 中的 parent,用的不多吧,
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			// 非抽象、非懶加載的 singletons。如果配置了 'abstract = true',那是不需要初始化的
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					// 處理 FactoryBean
					// FactoryBean 的話,在 beanName 前面加上 ‘&’ 符号。再調用 getBean,getBean 方法别急
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						final FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						// 判斷目前 FactoryBean 是否是 SmartFactoryBean 的實作,此處忽略,直接跳過
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
											((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						} else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				} else {
					// 對于普通的 Bean,隻要調用 getBean(beanName) 這個方法就可以進行初始化了                    
					//看這裡!!!!!!!!    
					getBean(beanName);
				}
			}
		}

		// Trigger post-initialization callback for all applicable beans...
		// 到這裡說明所有的非懶加載的 singleton beans 已經完成了初始化
		// 如果我們定義的 bean 是實作了 SmartInitializingSingleton 接口的,那麼在這裡得到回調,忽略
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				} else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}
           

AbstractBeanFactory.java

來到了getBean方法

@Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}
           

doGetBean 注意 有2個getSingleton,3個getObjectForBeanInstance,這塊一定要逐個分析一下

//告訴編譯器忽略 unchecked 警告資訊,如使用List,ArrayList等未進行參數化産生的警告資訊。
	@SuppressWarnings("unchecked")
	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
							  @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
		//1.轉換對應的beanName
		// 擷取一個 “正統的” beanName,處理兩種情況,一個是前面說的 FactoryBean(前面帶 ‘&’),
		// 一個是别名問題,因為這個方法是 getBean,擷取 Bean 用的,你要是傳一個别名進來,是完全可以的
		final String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
		//2.直接嘗試從緩存擷取或者 singleton Factories 巾的 Object Factory 獲垠
		// 這裡說下 args 呗,雖然看上去一點不重要。前面我們一路進來的時候都是 getBean(beanName),
		// 是以 args 傳參其實是 null 的,但是如果 args 不為空的時候,那麼意味着調用方不是希望擷取 Bean,而是建立 Bean
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				} else {
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			//3.如果從緩存中得到了bean的原始狀态,則對bean進行執行個體化
			// 下面這個方法:如果是普通 Bean 的話,直接傳回 sharedInstance,
			// 如果是 FactoryBean 的話,傳回它建立的那個執行個體對象
			// (FactoryBean 知識,讀者若不清楚請移步附錄)
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		} else {
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			/**
			 * 隻有在單例的情況才會嘗試解決循環依賴,原型模式情況下,如果存在
			 * A 中有B的屬性,那麼當依賴注入的時候,就會産生當且還未建立完的時候因為
			 * 對于B 創邊再次傳回建立A ,造成循環依賴, 也就是下面的情況
			 */
			//4.原型模式的依賴檢查
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			//檢查一下這個BeanDefinition 在容器中是否存在
			BeanFactory parentBeanFactory = getParentBeanFactory();
			//如果beanDefinitionMap中也就是在所有已經加載的類中不包括beanName則嘗試從parentBeanFactory中檢測
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				//遞歸到beanFactory中尋找
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				} else if (args != null) {
					// Delegation to parent with explicit args.
					//委派父級容器根據指定名稱和顯式的參數查找
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				} else {
					// No args -> delegate to standard getBean method.
					//委派父級容器根據指定名稱和類型查找
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}
			//如果不是僅僅做類型檢查則是建立bean,這裡要進行記錄
			if (!typeCheckOnly) {
				// typeCheckOnly 為 false,将目前 beanName 放入一個 alreadyCreated 的 Set 集合中。向容器标記指定的Bean已經被建立
				markBeanAsCreated(beanName);
			}
			/*
			 * 稍稍總結一下:
			 * 到這裡的話,要準備建立 Bean 了,對于 singleton 的 Bean 來說,容器中還沒建立過此 Bean;
			 * 對于 prototype 的 Bean 來說,本來就是要建立一個新的 Bean。
			 */

			try {
				//将存儲XML配置檔案的GernericBeanDefinition轉換為RootBeanDefinition,如果指定BeanName是子Bean的話同時會合并父類的相關屬性
				//主要解決Bean繼承時子類合并父類公共屬性問題
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				// 先初始化依賴的所有 Bean,這個很好了解。
				// 注意,這裡的依賴指的是 depends-on 中定義的依賴
				String[] dependsOn = mbd.getDependsOn();
				//若存在依賴則需要遞歸執行個體化依賴的bean
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						//緩存依賴調用,注冊一下依賴關系
						registerDependentBean(dep, beanName);
						try {
							//遞歸調用getBean()方法,先初始化被依賴項
							getBean(dep);
						} catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				// Create bean instance.
				// 如果是 singleton scope 的,建立 singleton 的執行個體
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							//執行建立 Bean , 詳解後面再說
							return createBean(beanName, mbd, args);
						} catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				} else if (mbd.isPrototype()) {
					//多例模式的建立
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						// 執行建立 Bean
						prototypeInstance = createBean(beanName, mbd, args);
					} finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				} else {
					//如果不是 singleton 和 Prototype 的話,需要委托給相應的實作類來處理
					//指定的scope建立bean
					String scopeName = mbd.getScope();
					final Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, () -> {
							beforePrototypeCreation(beanName);
							try {
								// 執行建立 Bean
								return createBean(beanName, mbd, args);
							} finally {
								afterPrototypeCreation(beanName);
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					} catch (IllegalStateException ex) {
						throw new BeanCreationException(beanName,
								"Scope '" + scopeName + "' is not active for the current thread; consider " +
										"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
								ex);
					}
				}
			} catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

		// Check if required type matches the type of the actual bean instance.
		// 最後,檢查一下類型對不對,不對的話就抛異常,對的話就傳回了
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
				if (convertedBean == null) {
					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
				}
				return convertedBean;
			} catch (TypeMismatchException ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("Failed to convert bean '" + name + "' to required type '" +
							ClassUtils.getQualifiedName(requiredType) + "'", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}
           

第一個getSingleton

然後到getSingleton方法,注意allowEarlyReference為true表示Spring預設是支援循環依賴的,這段邏輯到第一個判斷就直接傳回了,原因在于isSingletonCurrentlyInCreation方法,點進去就是判斷這個beanName是否在這個Set中,不滿足直接傳回了Null

@Override
	@Nullable
	public Object getSingleton(String beanName) {
		return getSingleton(beanName, true);
	}
	//然後到getSingleton方法,注意allowEarlyReference為true表示Spring預設是支援循環依賴的
		@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			//	第一次進來this.singletonObjects.get(beanName)傳回的肯定是null。然後isSingletonCurrentlyInCreation決定了能否進入二級緩存中擷取資料。
			synchronized (this.singletonObjects) {
				//從二級緩存擷取
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						//調用預先設定的getObject()方法
						singletonObject = singletonFactory.getObject();
						//記錄在緩存中,earlySingletonObjects和singletonFactories互斥
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}
           

然後因為sharedInstance為空是以if不滿足走else,然後到了這一步,對原型的檢查

//4.原型模式的依賴檢查
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}
			//如何判斷的,這裡涉及到一個ThreadLocal的概念,目前為空,
				protected boolean isPrototypeCurrentlyInCreation(String beanName) {
		Object curVal = this.prototypesCurrentlyInCreation.get();
		return (curVal != null &&
				(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
	}
           

然後就是一系列判斷,拿到我們前面注冊到bean工廠的BeanDefinition對象,也就是這裡的RootBeanDefinition,判斷他是單例的還是多例的還是其他的,然後走各自對應的處理邏輯,目前我們的beanName為messageService,預設單例,是以我們又到了看第二個getSingleton方法。

對于下面這段代碼,有個lambda表達式,也許有的老鐵就慌了,莫慌莫慌。調試一下…

// 如果是 singleton scope 的,建立 singleton 的執行個體
				if (mbd.isSingleton()) {
				    //看這裡
					sharedInstance = getSingleton(beanName, () -> {
						try {
							//執行建立 Bean , 詳解後面再說
							return createBean(beanName, mbd, args);
						} catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				} else if (mbd.isPrototype()) { ...}
           

斷點調試首先進來getSingleton方法,仔細看圖類名+$lambda,這是什麼鬼????

Spring IOC源碼解析

然後我們看下ObjectFactory,代碼如下:

@FunctionalInterface
public interface ObjectFactory<T> {
	/**
	 * Return an instance (possibly shared or independent)
	 * of the object managed by this factory.
	 * @return the resulting instance
	 * @throws BeansException in case of creation errors
	 */
	 //傳回一個由此工廠管理的執行個體,
	T getObject() throws BeansException;
}
           

然後這個lambda表達式是在調用getObject()方法的時候觸發的,小夥伴們可以自己斷點試試,這也算一個亮眼的操作了…繼續講解getSingleton方法

前面我們在if(isSingletonCurrentlyInCreation)有個判斷,如果成立則會抛出循環依賴的異常資訊,

到這個getSingleton方法裡的beforeSingletonCreation方法才是往singletonsCurrentlyInCreation添加目前的beanName。

然後就是調用singletonFactory.getObject();也就是AbstractBeanFactory的getSingleton的lambda,這塊一定要注意。

到了finally的afterSingletonCreation方法,就把singletonsCurrentlyInCreation的beanName給拿掉

如果lambda執行沒問題newSingleton指派為true,然後執行addSingleton方法。

到這裡,單例bean的外部邏輯我們已經锊清楚了。

下面是getSingleton方法和裡面幾個重要方法的代碼。

//因為在建立單例bean的時候會存在依賴注入的情況,而在建立依賴的時候為了避免循環依賴,
	// Spring建立bean的原則是不等bean建立完成就會将建立bean的ObjectFactory提早曝光加入到緩存中,一旦
	//下一個bean建立時需要依賴上個bean,則直接使用ObjectFactory.
	public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		//斷言beanName肯定不為空
		Assert.notNull(beanName, "Bean name must not be null");
		//同步全局變量,開始建立單例
		synchronized (this.singletonObjects) {
			//檢視單例是否已經被加載,凡是加載過的單例,都會存在Map<String, Object> singletonObjects裡面
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				//this.singletonsCurrentlyInDestruction是個boolean,記錄的是目前這個單例是否正在被銷毀,
				//如果是true,代表單例已經執行了自身的destroy銷毀方法,或者有異常的時候執行了destroySingleton方法等情況
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
									"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}
				//從一級緩存中取肯定為NULL,這裡往singletonsCurrentlyInCreation添加beanName
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				//如果此時suppressedExceptions為空,就new LinkedHashSet<>()來儲存接下來可能發生的異常
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					//到這裡就會調用外面的lambda表達式
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				} catch (IllegalStateException ex) {
					// Has the singleton object implicitly appeared in the meantime ->
					// if yes, proceed with it since the exception indicates that state.
					singletonObject = this.singletonObjects.get(beanName);
					//如果沒有建立報錯
					if (singletonObject == null) {
						throw ex;
					}
				} catch (BeanCreationException ex) {
					//把出現過的異常加進去
					if (recordSuppressedExceptions) {
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				} finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					//後處理,主要是把剛剛在beforeSingletonCreation方法裡面加載的bean狀态删除
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					//把結果存在緩存中,并删除一些中間狀态
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}
           

beforeSingletonCreation方法

protected void beforeSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	}
           

然後finally的afterSingletonCreation方法

protected void afterSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
			throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
		}
	}
           

addSingleton方法

if (newSingleton) {
					//把結果存在緩存中,并删除一些中間狀态
		addSingleton(beanName, singletonObject);
	}
           

建立Bean

也就是執行我們的lambda内容,IOC核心部分要來了

@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
		//要注意,在我們的初始化階段,args 是 null。
		if (logger.isDebugEnabled()) {
			logger.debug("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;

		// Make sure bean class is actually resolved at this point, and
		// clone the bean definition in case of a dynamically resolved Class
		// which cannot be stored in the shared merged bean definition.
		// 確定 BeanDefinition 中的 Class 被加載
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

		// Prepare method overrides.
		// 準備方法覆寫,這裡又涉及到一個概念:MethodOverrides,它來自于 bean 定義中的 <lookup-method />
		// 和 <replaced-method />,如果讀者感興趣,回到 bean 解析的地方看看對這兩個标簽的解析。
		// 我在附錄中也對這兩個标簽的相關知識點進行了介紹,讀者可以移步去看看
		try {
			mbdToUse.prepareMethodOverrides();
		} catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			// 讓 InstantiationAwareBeanPostProcessor 在這一步有機會傳回代理,
			// 在 《Spring AOP 源碼分析》那篇文章中有解釋,這裡先跳過
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		} catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		try {
			// 看這裡建立 bean
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isDebugEnabled()) {
				logger.debug("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		} catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			// A previously detected exception with proper bean creation context already,
			// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
			throw ex;
		} catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}
           

進入doCreateBean方法,1,2,3為其中的重點

//标記1,2,3是doCreateBean方法中3個比較重要的點
	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			//  1.說明不是 FactoryBean,這裡執行個體化 Bean,這裡非常關鍵,細節之後再說
			//根據指定Bean使用對應的政策建立Bean執行個體:如工廠方法,構造函數自動注入,簡單初始化
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		// 這個就是 Bean 裡面的 我們定義的類 的執行個體,很多地方我直接描述成 "bean 執行個體"
		final Object bean = instanceWrapper.getWrappedInstance();
		// 類型
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				} catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		// 下面這塊代碼是為了解決循環依賴的問題,以後有時間,我再對循環依賴這個問題進行解析吧
		//是否需要提前曝光,判斷條件為:單例&允許循環依賴&是否正在建立過程中
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		//允許提前暴露,添加到三級緩存中
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			//添加到三級緩存中
			//對bean再一次依賴引用。主要應用于SmartInstantiationAwareBeanPostProcessor
			//其中我們熟知的AOP的advice就是在這裡動态織入到bean中...若沒有則直接傳回bean
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			// 2.這一步也是非常關鍵的,這一步負責屬性裝配,因為前面的執行個體隻是執行個體化了,并沒有設值,這裡就是設值
			populateBean(beanName, mbd, instanceWrapper);
			// 還記得 init-method 嗎?還有 InitializingBean 接口?還有 BeanPostProcessor 接口?
			// 3.這裡就是處理 bean 初始化完成後的各種回調
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		} catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			} else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

		if (earlySingletonExposure) {
			Object earlySingletonReference = getSingleton(beanName, false);
			//如果是A和B存在循環依賴關系,在B的生命周期調用完了後置處理器之後到這,因傳入false,導緻為空,為什麼要傳入false,是因為A此時已經完了後置處理器,但A這個Bean
			//其實沒有建立完,如果還想生成代理類,是有問題的,這也就是為什麼spring二級緩存不用,選擇三級緩存的原因
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				} else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
										StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
										"] in its raw version as part of a circular reference, but has eventually been " +
										"wrapped. This means that said other beans do not use the final version of the " +
										"bean. This is often the result of over-eager type matching - consider using " +
										"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		} catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

           

推斷構造方法

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// Make sure bean class is actually resolved at this point.
		// 確定已經加載了此 class
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		// 校驗一下這個類的通路權限
		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
		}

		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}
		//如果工廠方法不為空則使用工廠方法初始化政策,其實也對是對應xml的<bean factory-method>标簽
		if (mbd.getFactoryMethodName() != null) {
			// 采用工廠方法執行個體化,不熟悉這個概念的讀者請看附錄,注意,不是 FactoryBean
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		// 如果不是第一次建立,比如第二次建立 prototype bean。
		// 這種情況下,我們可以從第一次建立知道,采用無參構造函數,還是構造函數依賴注入 來完成執行個體化
		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				//一個類中可能有多個構造函數,每個構造函數都有不同的參數,是以調用前需要先根據參數鎖定構造函數對應的工廠方法
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		if (resolved) {
			if (autowireNecessary) {
				// 構造函數依賴注入
				return autowireConstructor(beanName, mbd, null, null);
			} else {
				// 無參構造函數
				return instantiateBean(beanName, mbd);
			}
		}

		// Candidate constructors for autowiring?
		// 判斷是否采用有參構造函數
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			// 構造函數依賴注入
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		// No special handling: simply use no-arg constructor.
		// 調用無參構造函數
		return instantiateBean(beanName, mbd);
	}
           

本次我們調用的是無參構造方法,是以進入到instantiateBean,可以看到Spring将執行個體化的bean封裝成了一個BeanWrapper的包裝類

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
		try {
			Object beanInstance;
			final BeanFactory parent = this;
			if (System.getSecurityManager() != null) {
				beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
								getInstantiationStrategy().instantiate(mbd, beanName, parent),
						getAccessControlContext());
			} else {
				// 調用初始化政策
				beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
			}
			// 包裝一下,傳回
			BeanWrapper bw = new BeanWrapperImpl(beanInstance);
			initBeanWrapper(bw);
			return bw;
		} catch (Throwable ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
		}
	}
           

進入到Bean初始化政策的instantiate方法,大體邏輯我們分析一下

1.判斷bd存不存在方法覆寫,預設沒有,是以進if,他先回去嘗試一下能不能拿到我們要用的構造,也就是定義的constructorToUse,正常情況下沒配置都是拿不到,是以為NULL,再進去,通過bd拿到我們的Class,看到這裡,是不是就是我們java的反射知識了,繼續看,他會判斷這個class是不是一個接口,如果是就是抛出RuntimeException類型異常。順便再提一點,我們工作中,關于service層,注意是service層的接口哈,為什麼接口不用加注解,而在結尾為Impl的實作類加了注解@Service的原因,是以看源碼對平常工作還是有一定幫助的。

@Override
	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
		// Don't override the class with CGLIB if no overrides.
		// 如果不存在方法覆寫,那就使用 java 反射進行執行個體化,否則使用 CGLIB,這裡就是判斷采用什麼初始化bean的政策
		// 方法覆寫 eg: lookup-method 和 replaced-method 
		if (!bd.hasMethodOverrides()) {
			Constructor<?> constructorToUse;
			synchronized (bd.constructorArgumentLock) {
				constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse == null) {
					final Class<?> clazz = bd.getBeanClass();
					if (clazz.isInterface()) {
						throw new BeanInstantiationException(clazz, "Specified class is an interface");
					}
					try {
						if (System.getSecurityManager() != null) {
							constructorToUse = AccessController.doPrivileged(
									(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
						}
						else {
							//預設構造方法
							constructorToUse = clazz.getDeclaredConstructor();
						}
						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
					}
					catch (Throwable ex) {
						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
					}
				}
			}
			// 利用構造方法進行執行個體化
			return BeanUtils.instantiateClass(constructorToUse);
		}
		else {
			// Must generate CGLIB subclass.
			// 存在方法覆寫,利用 CGLIB 來完成執行個體化,需要依賴于 CGLIB 生成子類
			//  因為如果不使用 CGLIB 的話,存在 override 的情況 JDK 并沒有提供相應的執行個體化支援
			return instantiateWithMethodInjection(bd, beanName, owner);
		}
	}
           

上面通過反射拿到我們的構造,接下來傳入到一個BeanUtils的工具類進行執行個體化

public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
		Assert.notNull(ctor, "Constructor must not be null");
		try {
		//主要判斷構造的修飾符,是不是能通路,如果是私有的,或者不能通路,那麼我們就需要進行暴力通路
		//也就是加上這行代碼  ctor.setAccessible(true);
			ReflectionUtils.makeAccessible(ctor);
			//調用初始化政策,目前預設是newInstance來執行個體化的
			return (KotlinDetector.isKotlinType(ctor.getDeclaringClass()) ?
					KotlinDelegate.instantiateClass(ctor, args) : ctor.newInstance(args));
		}
		catch (InstantiationException ex) {
			throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
		}
		catch (IllegalAccessException ex) {
			throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
		}
		catch (IllegalArgumentException ex) {
			throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
		}
		catch (InvocationTargetException ex) {
			throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());
		}
	}
           

這個時候我們控制台列印了一句話,通過這個列印我們能清楚的知道這個通過構造進行執行個體化的

Spring IOC源碼解析

提前暴露工廠

執行個體化Bean講完了,下面這段代碼很重要,設及到Spring比較難的知識點:循環依賴

下面這塊代碼是為了解決循環依賴的問題,earlySingletonExposure正常情況下都是true的,isSingletonCurrentlyInCreation(beanName),還記得前面一個方法叫beforeSingletonCreation這個麼,我們這裡還沒有到afterSingletonCreation方法呢,還在lambda表達式裡的getObject()方法執行個體化Bean呢,小夥伴們可千萬别懵了。

然後到addSingletonFactory方法,這裡又傳了一個lambda,道理跟咋們前面講的一樣,

//是否需要提前曝光,判斷條件為:單例&允許循環依賴&是否正在建立過程中
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		//允許提前暴露,添加到三級緩存中
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			//添加到三級緩存中
			//對bean再一次依賴引用。主要應用于SmartInstantiationAwareBeanPostProcessor
			//其中我們熟知的AOP的advice就是在這裡動态織入到bean中...若沒有則直接傳回bean
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}
           

addSingletonFactory方法

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		synchronized (this.singletonObjects) {
			//一級緩存不存在
			if (!this.singletonObjects.containsKey(beanName)) {
				//放入三級緩存中
				this.singletonFactories.put(beanName, singletonFactory);
				//移除二技緩存
				this.earlySingletonObjects.remove(beanName);
				this.registeredSingletons.add(beanName);
			}
		}
	}
           

Q:這裡設及到Spring三級緩存方面的問題,由于本篇文章篇幅确實過長了,是以後期考慮開一篇文章來重點講講循環依賴,以及Spring為什麼要使用三級緩存來解決該問題的?

繼續第二步,DI部分

依賴注入(DI)

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
		if (bw == null) {
			if (mbd.hasPropertyValues()) {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
			} else {
				// Skip property population phase for null instance.
				//沒有需要填充的屬性
				return;
			}
		}
		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
		// state of the bean before properties are set. This can be used, for example,
		// to support styles of field injection.
		// 1.InstantiationAwareBeanPostProcessor 處理器的postProcessAfterInstantiation函數的應用,此函數可以控制程式是否繼續進行屬性填充
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						return;
					}
				}
			}
		}
		// bean 執行個體的所有屬性都在這裡了
		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
		// 2. 根據注入類型,提取依賴的bean,并統一存入PropertyValues中
		//沒配置的話預設為0 關于名字,類型,構造分别對應1,2,3
		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				// 通過名字找到所有屬性值,如果是 bean 依賴,先初始化依賴的 bean。記錄依賴關系
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
				// 通過類型裝配。複雜一些
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}
		//後處理器已經初始化
		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		//需要依賴檢查
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		if (hasInstAwareBpps || needsDepCheck) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			// 3. 應用InstantiationAwareBeanPostProcessor處理器的postProcessPropertyValues方法,對屬性擷取完畢填充前對屬性再次處理
			//典型應用是RequiredAnnotationBeanPostProcessor類中對屬性的驗證
			if (hasInstAwareBpps) {
				for (BeanPostProcessor bp : getBeanPostProcessors()) {
					if (bp instanceof InstantiationAwareBeanPostProcessor) {
						InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
						// 這裡有個非常有用的 BeanPostProcessor 進到這裡: AutowiredAnnotationBeanPostProcessor
						// 對采用 @Autowired、@Value 注解的依賴進行設值,這裡的内容也是非常豐富的,不過本文不會展開說了,感興趣的讀者請自行研究
						pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvs == null) {
							return;
						}
					}
				}
			}
			if (needsDepCheck) {
				checkDependencies(beanName, mbd, filteredPds, pvs);
			}
		}
		// 4. 将PropertyValues屬性填充到BeanWrapper中
		if (pvs != null) {
			// 設定 bean 執行個體的屬性值   看這裡
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}
           

進入到第四步,前面主要是一些條件判斷,然後拿到屬性名字,原始值,這個原始值可能還不是我們要使用的,需要再處理一下,于是,下一步…

protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
		if (pvs.isEmpty()) {
			return;
		}

		if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
			((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
		}

		MutablePropertyValues mpvs = null;
		List<PropertyValue> original;

		if (pvs instanceof MutablePropertyValues) {
			mpvs = (MutablePropertyValues) pvs;
			//如果mpvs中的值已經被轉換為對應的類型那麼可以直接設值到bw中
			if (mpvs.isConverted()) {
				// Shortcut: use the pre-converted values as-is.
				try {
					bw.setPropertyValues(mpvs);
					return;
				} catch (BeansException ex) {
					throw new BeanCreationException(
							mbd.getResourceDescription(), beanName, "Error setting property values", ex);
				}
			}
			//如果 pvs 并不是使用 MutablePropertyValues 封裝的類型,那麼直接使用原始的屬性擷取方法
			original = mpvs.getPropertyValueList();
		} else {
			original = Arrays.asList(pvs.getPropertyValues());
		}

		TypeConverter converter = getCustomTypeConverter();
		if (converter == null) {
			converter = bw;
		}
		//擷取對應·的解析器
		BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

		// Create a deep copy, resolving any references for values.
		List<PropertyValue> deepCopy = new ArrayList<>(original.size());
		boolean resolveNecessary = false;
		//周遊屬性,将屬性轉換為對應類的對應屬性的類型
		for (PropertyValue pv : original) {
			if (pv.isConverted()) {
				deepCopy.add(pv);
			} else {
				String propertyName = pv.getName();
				//原始的屬性值,即轉換之前的屬性值
				Object originalValue = pv.getValue();
				//做一些類型的強制轉換
				Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
				//轉換之後的屬性值
				Object convertedValue = resolvedValue;
				//屬性值是否可以轉換
				boolean convertible = bw.isWritableProperty(propertyName) &&
						!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
				if (convertible) {
					convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
				}
				// Possibly store converted value in merged bean definition,
				// in order to avoid re-conversion for every created bean instance.
				if (resolvedValue == originalValue) {
					if (convertible) {
						pv.setConvertedValue(convertedValue);
					}
					deepCopy.add(pv);
				} else if (convertible && originalValue instanceof TypedStringValue &&
						!((TypedStringValue) originalValue).isDynamic() &&
						!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
					pv.setConvertedValue(convertedValue);
					deepCopy.add(pv);
				} else {
					resolveNecessary = true;
					deepCopy.add(new PropertyValue(pv, convertedValue));
				}
			}
		}
		if (mpvs != null && !resolveNecessary) {
			mpvs.setConverted();
		}

		// Set our (possibly massaged) deep copy.
		try {
			// AbstractPropertyAccessor
			bw.setPropertyValues(new MutablePropertyValues(deepCopy));
		} catch (BeansException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Error setting property values", ex);
		}
	}
           

進入BeanDefinitionValueResolver的resolveValueIfNecessary方法

判斷value是不是運作時Bean的引用,顯然這裡是,進入第一個return方法

@Nullable
	public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
		// We must check each value to see whether it requires a runtime reference
		// to another bean to be resolved.
		if (value instanceof RuntimeBeanReference) {
			RuntimeBeanReference ref = (RuntimeBeanReference) value;
			return resolveReference(argName, ref);
		}
		else if (value instanceof RuntimeBeanNameReference) {
			String refName = ((RuntimeBeanNameReference) value).getBeanName();
			refName = String.valueOf(doEvaluate(refName));
			if (!this.beanFactory.containsBean(refName)) {
				throw new BeanDefinitionStoreException(
						"Invalid bean name '" + refName + "' in bean reference for " + argName);
			}
			return refName;
		}
		else if (value instanceof BeanDefinitionHolder) {
			// Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.
			BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
			return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
		}
		else if (value instanceof BeanDefinition) {
			// Resolve plain BeanDefinition, without contained name: use dummy name.
			BeanDefinition bd = (BeanDefinition) value;
			String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR +
					ObjectUtils.getIdentityHexString(bd);
			return resolveInnerBean(argName, innerBeanName, bd);
		}
		else if (value instanceof ManagedArray) {
			// May need to resolve contained runtime references.
			ManagedArray array = (ManagedArray) value;
			Class<?> elementType = array.resolvedElementType;
			if (elementType == null) {
				String elementTypeName = array.getElementTypeName();
				if (StringUtils.hasText(elementTypeName)) {
					try {
						elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
						array.resolvedElementType = elementType;
					}
					catch (Throwable ex) {
						// Improve the message by showing the context.
						throw new BeanCreationException(
								this.beanDefinition.getResourceDescription(), this.beanName,
								"Error resolving array type for " + argName, ex);
					}
				}
				else {
					elementType = Object.class;
				}
			}
			return resolveManagedArray(argName, (List<?>) value, elementType);
		}
		else if (value instanceof ManagedList) {
			// May need to resolve contained runtime references.
			return resolveManagedList(argName, (List<?>) value);
		}
		else if (value instanceof ManagedSet) {
			// May need to resolve contained runtime references.
			return resolveManagedSet(argName, (Set<?>) value);
		}
		else if (value instanceof ManagedMap) {
			// May need to resolve contained runtime references.
			return resolveManagedMap(argName, (Map<?, ?>) value);
		}
		else if (value instanceof ManagedProperties) {
			Properties original = (Properties) value;
			Properties copy = new Properties();
			original.forEach((propKey, propValue) -> {
				if (propKey instanceof TypedStringValue) {
					propKey = evaluate((TypedStringValue) propKey);
				}
				if (propValue instanceof TypedStringValue) {
					propValue = evaluate((TypedStringValue) propValue);
				}
				if (propKey == null || propValue == null) {
					throw new BeanCreationException(
							this.beanDefinition.getResourceDescription(), this.beanName,
							"Error converting Properties key/value pair for " + argName + ": resolved to null");
				}
				copy.put(propKey, propValue);
			});
			return copy;
		}
		else if (value instanceof TypedStringValue) {
			// Convert value to target type here.
			TypedStringValue typedStringValue = (TypedStringValue) value;
			Object valueObject = evaluate(typedStringValue);
			try {
				Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
				if (resolvedTargetType != null) {
					return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
				}
				else {
					return valueObject;
				}
			}
			catch (Throwable ex) {
				// Improve the message by showing the context.
				throw new BeanCreationException(
						this.beanDefinition.getResourceDescription(), this.beanName,
						"Error converting typed String value for " + argName, ex);
			}
		}
		else if (value instanceof NullBean) {
			return null;
		}
		else {
			return evaluate(value);
		}
	}

           

看到這裡,不知道小夥伴是明白了還是懵了,哈哈,我們說說這斷代碼:拿到beanName,然後判斷,又是一個beanFactory,沒錯,這就是我們前面得到的DefaultListableBeanFactory,IOC的始祖

@Nullable
	private Object resolveReference(Object argName, RuntimeBeanReference ref) {
		try {
			Object bean;
			String refName = ref.getBeanName();
			refName = String.valueOf(doEvaluate(refName));
			if (ref.isToParent()) {
				if (this.beanFactory.getParentBeanFactory() == null) {
					throw new BeanCreationException(
							this.beanDefinition.getResourceDescription(), this.beanName,
							"Can't resolve reference to bean '" + refName +
									"' in parent factory: no parent factory available");
				}
				bean = this.beanFactory.getParentBeanFactory().getBean(refName);
			}
			else {
				//-----------------------------看這裡------------------------------------------
				bean = this.beanFactory.getBean(refName);
				this.beanFactory.registerDependentBean(refName, this.beanName);
			}
			if (bean instanceof NullBean) {
				bean = null;
			}
			return bean;
		}
		catch (BeansException ex) {
			throw new BeanCreationException(
					this.beanDefinition.getResourceDescription(), this.beanName,
					"Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
		}
	}
           

進入getBean方法

又到了我們最初的messageService的起點了,不過這次是beanName為message的bean

@Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}
           

這是我們開始的xml配置

<bean id="messageService" name="m1,m2,m3" scope="singleton" class="com.whp.service.impl.MessageServiceImpl">
		<!--引入下面id為message的bean-->
		<property name="message" ref="message"/>
	</bean>
	<bean id="message" class="com.whp.bean.Message"/>
           

然後重複messageService之後,我們拿到了beanName為message的bean,這時候需要給MessageServiceImpl這個類的屬性message指派了,還是我們前面的DI的過程,然後接下來就是指派了。

Bean執行個體化完成函數回調

前面2步我們已經把Bean執行個體化以及DI完成了,最後就是回調以及通知了,工作亦是如此…

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		//JDK的安全機制驗證權限
		if (System.getSecurityManager() != null) {
			//實作PrivilegedAction接口的匿名内部類
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		} else {
			// 如果 bean 實作了 BeanNameAware、BeanClassLoaderAware 或 BeanFactoryAware 接口,回調
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			// BeanPostProcessor 的 postProcessBeforeInitialization 回調
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			// 處理 bean 中定義的 init-method,
			// 或者如果 bean 實作了 InitializingBean 接口,調用 afterPropertiesSet() 方法
			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()) {
			// BeanPostProcessor 的 postProcessAfterInitialization 回調
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}
           

部分Aware回調

進入invokeAwareMethods方法,這部分我們叫做部分Aware回調,這裡就三個,對于Aware接口的實作肯定有多個,是以這裡我們叫部分Aware接口回調

private void invokeAwareMethods(final String beanName, final Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}
			if (bean instanceof BeanClassLoaderAware) {
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) {
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				}
			}
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}
           

還記得嘛,我開始在MessageServiceImpl實作了BeanNameAware,然後setBeanName方法,就是為了這一步

Spring IOC源碼解析

然後到了BeanPostProcessor的前後通知

applyBeanPostProcessorsBeforeInitialization方法

@Override
	public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessBeforeInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}
           

applyBeanPostProcessorsAfterInitialization方法

@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}
           

對于BeanPostProcessor,是Spring提供給我們開發者的一個非常重要的拓展點,還有FactoryBean

,InitializingBean我們也可以利用它來初始化我們自定義的一些Bean,Aware接口我們也可以利用起來

第3步完成過後有個if (earlySingletonExposure) {…}這塊屬于循壞依賴東西,後期有時間會開篇文章重點講講。

這個時候我們的beanName為messageService的Bean執行個體化完成了,最後需要把它放入到Spring的一級緩存中,供開發者使用。

Spring IOC源碼解析

afterSingletonCreation(beanName)将singletonsCurrentlyInCreation的beanName移除

protected void afterSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
			throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
		}
	}
           

addSingleton方法

//一句話,Bean添加到一級緩存,移除二三級緩存。
	protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			//一級緩存添加
			this.singletonObjects.put(beanName, singletonObject);
			//移除三級,二級緩存
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			//	registeredSingletons這個Set是記錄已經建立好的bean
			this.registeredSingletons.add(beanName);
		}
	}
           

最後一個就是getObjectForBeanInstance方法了

if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							//執行建立 Bean , 詳解後面再說
							return createBean(beanName, mbd, args);
						} catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				} else if (mbd.isPrototype()) {
           

* 這個方法就三個判斷:

* 1、如果不是factoryBean 但是name開頭為&,那麼報錯

* 2、如果是FactoryBean,并且name開頭不為&,就取FactoryBean的getObject方法

* 3、如果是FactoryBean,并且name開頭為&,那麼傳回FactoryBean本身。

protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		// Don't let calling code try to dereference the factory if the bean isn't a factory.
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			//
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			if (!(beanInstance instanceof FactoryBean)) {
				//如果name開頭&,但又不是factoryBean就報錯
				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
			}
		}

		// Now we have the bean instance, which may be a normal bean or a FactoryBean.
		// If it's a FactoryBean, we use it to create a bean instance, unless the
		// caller actually wants a reference to the factory.
		//如果不是FactoryBean,那麼就屬于正常的bean執行個體了,直接傳回
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}
		//加載FactoryBean
		Object object = null;
		if (mbd == null) {
			//嘗試從緩存中擷取bean
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// Return bean instance from factory.
			//強轉為beanFactory。此時的beanInstance一定是FactoryBean類型的,因為如果不是,就會在上面的if中直接傳回了
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton.
			//檢測這個bean是否已經被加載過
			//containsBeanDefinition中會傳回beanDefinitionMap.containsKey(beanName)的值
			if (mbd == null && containsBeanDefinition(beanName)) {
				//進行父類和子類的合并,把存儲xml配置的GernericBeanDefinition轉換為RootBeanDefinition
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			//我的bean是FactoryBean,那麼就會通過FactoryBean的getObject方法
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}
           

到這裡,可以說是Spring初始化完成了,我們可以通過一下進行調用使用了

本次的Spring IOC源碼解析已接近了尾聲,不知道有多少小夥伴堅持看完了,看完的可以在下方回複Spring IOC,也表示對部落客寫了這麼久的認可哈哈,确實有點辛苦,如果本篇文章有缺點,歡迎指教,需要源碼項目的也可以找我要,省的大家去下載下傳了,本次Spring IOC源碼解析到此結束。

繼續閱讀