1. 程式人生 > >簡單的Spring的bean例項化過程

簡單的Spring的bean例項化過程

以XmlBeanFactory為例,最簡單的取bean方式是:

BeanFactory factory = new XmlBeanFactory(new FileSystemResource("D:\\workspace\\JavaApplication2\\src\\javaapplication2\\spring\\beans.xml"));
            Car obj = (Car)factory.getBean("car");

 Bean的配置檔案內容也很簡單:

    <bean id="vehicle"   abstract="true">
        <property name="wheel" value="Four wheeler"/>        
    </bean>
    <bean id="car" class="javaapplication2.spring.Car" parent="vehicle">
        <property name="dicky" value="Flat dicky"/>    
    </bean>

先看起始點,載入先走AbstractBeanFactory

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

doGetBean方法中:

// Create bean instance.
if (mbd.isSingleton()) {
         //傳入一個內聯類ObjectFactory並實現了getObject方法。
         sharedInstance = getSingleton(beanName, new ObjectFactory() {
	public Object getObject() throws BeansException {
	try {
	    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); //有異常則銷燬bean
			throw ex;
	}
}
});
	bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
        //此處開始例項化bean

}

通過new ObjectFactory()的回撥方法,回調當前類繼承的createBean方法,該方法在父類AbstractAutowireCapableBeanFactory中:

AbstractAutowireCapableBeanFactory->

protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
			throws BeanCreationException {

		// Make sure bean class is actually resolved at this point.
		resolveBeanClass(mbd, beanName);  //載入該bean的class,並放置到mbd裡面,bean的生成不在這裡。

		// Prepare method overrides.
		try {
			mbd.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			Object bean = resolveBeforeInstantiation(beanName, mbd);  //嘗試獲取一個proxy,普通bean這裡一般是空的返回
			
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		Object beanInstance = doCreateBean(beanName, mbd, args);  //開始create bean的例項,mbd中包括了需要的class
		if (logger.isDebugEnabled()) {
			logger.debug("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}

進入AbstractBeanFactory中的protected Class resolveBeanClass方法:

try {
	if (mbd.hasBeanClass()) {
		return mbd.getBeanClass();
	}
	if (System.getSecurityManager() != null) {
		return AccessController.doPrivileged(new PrivilegedExceptionAction<Class>() {
			public Class run() throws Exception {
				return doResolveBeanClass(mbd, typesToMatch);
			}
		}, getAccessControlContext());
	}
	else {
		return doResolveBeanClass(mbd, typesToMatch);   <---還要繼續進去看生成方法。
	}
}

轉入doResolveBeanClass:

private Class doResolveBeanClass(RootBeanDefinition mbd, Class... typesToMatch) throws ClassNotFoundException {
	if (!ObjectUtils.isEmpty(typesToMatch)) {
		ClassLoader tempClassLoader = getTempClassLoader();
		if (tempClassLoader != null) {
			if (tempClassLoader instanceof DecoratingClassLoader) {
				DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
			for (Class<?> typeToMatch : typesToMatch) {
				dcl.excludeClass(typeToMatch.getName())
			}
		}
		String className = mbd.getBeanClassName();
		return (className != null ? ClassUtils.forName(className, tempClassLoader) : null); //通過自己的ClassUtils的forName方法來例項化class
		}
	}
	return mbd.resolveBeanClass(getBeanClassLoader());  <----這裡傳入了bean的classloader,下面繼續看這裡
}

AbstractBeanDefinition->resolveBeanClass

public Class resolveBeanClass(ClassLoader classLoader) throws ClassNotFoundException {
		String className = getBeanClassName();
		if (className == null) {
			return null;
		}
		Class resolvedClass = ClassUtils.forName(className, classLoader);//classloader傳入後,仍然是用forName方法載入class
		this.beanClass = resolvedClass;
		return resolvedClass;
	}

再來看forName做了些什麼

ClassUtils ->

ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
	classLoaderToUse = getDefaultClassLoader();
}
try {
	return classLoaderToUse.loadClass(name); //也比較簡單,直接呼叫loadClass方法載入
}

最終將class load進來。

Bean例項化過程:

AbstractAutowireCapableBeanFactory->createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) 
	// Need to determine the constructor...
	//提取建構函式,如果沒有就是空
	Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
	if (ctors != null ||mbd.getResolvedAutowireMode() == RootBeanDefinition.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); //這裡例項化

進入

AbstractAutowireCapableBeanFactory->instantiateBean

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd)
...這裡省略沒用的		
	else {
		beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);//下面看這裡的例項化
	}		
			
	BeanWrapper bw = new BeanWrapperImpl(beanInstance);   //返回一個包裝類物件
	initBeanWrapper(bw);
	return bw;

SimpleInstantiationStrategy->instantiate

public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner)
	synchronized (beanDefinition.constructorArgumentLock) {
			constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;
		...
	}
	return BeanUtils.instantiateClass(constructorToUse);	 //BeanUtils來初始化例項 ,給出了例項化需要的建構函式

再來看BeanUtils的例項化方法,比較簡單,直接用反射的建構函式來newInstance。

BeanUtils->

public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
	try {
		ReflectionUtils.makeAccessible(ctor);
		return ctor.newInstance(args);
	}

AbstractAutowireCapableBeanFactory->

Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) 

	// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			if (exposedObject != null) {
				exposedObject = initializeBean(beanName, exposedObject, mbd);
			}
		}
	return exposedObject;		//返回給AbstractBeanFactory

相關推薦

簡單的Spring的bean例項過程

以XmlBeanFactory為例,最簡單的取bean方式是: BeanFactory factory = new XmlBeanFactory(new FileSystemResource("D:\\workspace\\JavaApplication2\\src\\javaapplication2\\

面向物件【day07】:類的例項過程剖析(三)

本節內容 1、概述 2、類的語法 3、總結 一、概述    之前我們說關於python中的類,都一臉懵逼,都想說,類這麼牛逼到底是什麼,什麼才是類?下面我們就來講講,什麼是類?它具有哪些特性。 二、類的語法 2.1 語法

JVM總括四-類載入過程、雙親委派模型、物件例項過程 JVM思考-init和clinit區別

JVM總括四-類載入過程、雙親委派模型、物件例項化過程 目錄:JVM總括:目錄 一、 類載入過程 類載入過程就是將.class檔案轉化為Class物件,類例項化的過程,(User user = new User(); 這個過程是物件例項化的過程); 一個.class檔案只有一個Class物件(位元

JVM思考-init和clinit區別 JVM總括四-類載入過程、雙親委派模型、物件例項過程

JVM思考-init和clinit區別 目錄:JVM總括:目錄 clinit和init的區別其實也就是Class物件初始化物件初始化的區別,詳情看我上一篇部落格:  JVM總括四-類載入過程、雙親委派模型、物件例項化過程 一、init和clinit方法執行時機不同   init是物件構

JVM總括四-類載入過程、雙親委派模型、物件例項過程

JVM總括四-類載入過程、雙親委派模型、物件例項化過程 目錄:JVM總括:目錄 一、 類載入過程 類載入過程就是將.class檔案轉化為Class物件, 類例項化 的過程 ,(User user = new User(); 這個過程是 物件例項化 的

類載入過程(clinit()),物件例項過程(init())

類載入過程: 1、類載入就是執行Java程式編譯之後在位元組碼檔案中生成的clinit()方法(稱之為類構造器),clinit()方法由靜態變數和靜態程式碼塊組成。 2、子類的載入首先需要先載入父類,如果父類為介面。則不會呼叫父類的clinit方法。一個類中可以沒有clinit方法。 3、clinit方

子類物件例項過程

2018年11月05日 08:58:03 aprildusk 閱讀數:3 個人分類: java

Java子父類中的建構函式例項過程

其實我們發現子類繼承父類操作很簡單,如果要是去深入的研究下會發現,例項化過程並非是我們看到的那樣,我們就以程式碼舉例來說明; 問大家,以下程式碼執行會輸出什麼呢? package com.oop; /** * 定義動物物件 * @author

spring裝配Bean過程以及Bean例項過程

<ol class="linenums" style="margin:0px; word-wrap:break-word; padding:0px 0px 0px 40px"><li class="L0" style="word-wrap:break-word; padding-left:

Angular2 依賴注入之例項過程

這裡會介紹 Angular 的注入器和例項化過程,基於 [email protected] Angular 依賴注入過程主要有下面幾個重要的部分組成: Inject 和 Injectable 裝飾器 解析提供商,構造注入器 獲取例項化物件

JAVA new流程(例項過程

1.首先去JVM 的方法區中區尋找類的class物件,如果能找到,則按照定義生成物件,找不到則轉2 2.載入類定義:類載入器(classLoader)尋找該類的 .class檔案,找到後對檔案進行分析轉換為class物件存入方法區方便以後呼叫。     其中jdk 的cla

springboot bean的例項過程和屬性注入過程

瞭解過springboot的載入流程的都知道springboot初始化bean都在refresh方法中。這個方法程式碼如下:// Prepare this context for refreshing. prepareRefresh(); // Tell the subcla

AnnotationConfigApplicationContext的例項過程

1,類繼承結構 理解AnnotationConfigApplicationContext的例項化過程之前先看一下它的類繼承結構: 主要涉及到的類或介面有以下幾個: GenericApplicationContext——通用應用上下文,內部持有一個De

Java類載入與例項過程

0x00 背景知識 1、虛擬機器在首次載入Java類時,會對靜態初始化塊、靜態成員變數、靜態方法(下文將這三種統稱為靜態程式碼塊)進行一次初始化 具體過程是: ①裝(加)載類的載入指的是將類的.class檔案中的二進位制資料讀入到記

java面向物件——繼承最終章--子類的例項過程(記憶體)

一個物件的例項化過程:Person p=new Person(); 1.jvm會讀取指定的路徑下的Person.class檔案,並載入進記憶體。    並會先載入Person中的父類(如果有父類物件的情況下)。 2.在堆記憶體中開闢空間,分配地址 3.並在物件空間中,對物件

java之面向物件:子類物件的例項過程詳解

在子類建構函式中,發現,訪問子類建構函式時,父類也運行了。原因是什麼呢? 在子類的建構函式裡第一行有一個預設的隱式語句:super() ExtendsDemo.java class Fu { Fu() { System.out.println("fu run")

Fabric1.4原始碼解析:鏈碼例項過程

之前說完了鏈碼的安裝過程,接下來說一下鏈碼的例項化過程好了,再然後是鏈碼的呼叫過程。其實這幾個過程內容已經很相似了,都是涉及到Proposal,不過整體流程還是要說一下的。 同樣,切入點仍然是fabric/peer/main.go檔案中的main()方法: #這一句定義了關於通過Peer節點操作鏈碼的命令 m

Spring 原始碼學習 - 單例bean的例項過程

> 本文作者:geek,一個聰明好學的同事 ## 1. 簡介 開發中我們常用@Commpont,@Service,@Resource等註解或者配置xml去宣告一個類,使其成為spring容器中的bean,以下我將用從原始碼角度看以AnnotationConfigApplicationContext

JVM總括四-類載入過程、雙親委派模型、物件例項

JVM總括四-類載入過程、雙親委派模型、物件例項化 一、 類載入過程 一定要注意每個過程執行的內容!!!!!! 1、Load:   將編譯後的.class檔案以二進位制流的方式載入到JVM記憶體中,並轉化為特定的資料結構,用到的就是classLoad二類載入器。這個過程中校驗cafe babe

類初始例項初始過程

類初始化過程①,一個類要建立例項需要先載入並初始化該類--》main方法所在的類需要先載入和初始化②,一個子類要初始化需要先初始化父類③,一個類初始化就是執行<clinit>() 方法--》<clinit>() 由靜態類變數賦值程式碼和靜態程式碼塊組成--》靜態類變數賦值程式碼和靜態程