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進來。

進入

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  

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/250043.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/250043.shtml
英文地址,請注明出處:http://en.pswp.cn/news/250043.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

最全整理瀏覽器兼容性問題與解決方案(轉)

所謂的瀏覽器兼容性問題&#xff0c;是指因為不同的瀏覽器對同一段代碼有不同的解析&#xff0c;造成頁面顯示效果不統一的情況。在大多數情況下&#xff0c;我們的需求是&#xff0c;無論用戶用什么瀏覽器來查看我們的網站或者登陸我們的系統&#xff0c;都應該是統一的顯示效…

【算法】 - 滑動窗口

1. 題目鏈接 2. 分析 最多可以將K個值從0變成1,因此滑動窗口的限制條件: 0的數量(zeros)小于K,算法過程如下 有一個滑動窗口(slipper),每次都會從A中讀入一個數當讀入的數為0時,zeros當zeros的數量大于K時,會取出slipper首部的元素,當取值為0時zeros-- 總體代碼如下: var lo…

Springboot整合thymeleaf模板

Thymeleaf是個XML/XHTML/HTML5模板引擎&#xff0c;可以用于Web與非Web應用。 Thymeleaf的主要目標在于提供一種可被瀏覽器正確顯示的、格式良好的模板創建方式&#xff0c;因此也可以用作靜態建模。你可以使用它創建經過驗證的XML與HTML模板。相對于編寫邏輯或代碼&#xff0…

Java代碼輸出到txt文件(申請專利貼源碼的必備利器)

最近公司在申請專利&#xff0c;編寫不少文檔&#xff0c;項目的代碼量實在是過于龐大。如果一個一個的復制粘貼雖然能夠完成&#xff0c;但是對于程序員而言實在沒有這個必要。shell或者python就能解決這個問題。由于我個人對于shell和python不是非常熟練的情況下&#xff0c;…

【算法】 - 動態規劃 + 位運算

題目描述 思路1: 寫一個返回2進制中1數量的函數countOne遍歷0到num,對每一個數使用countOne,并將結果保存到res中返回 var countBits function (num) {let res new Array(num 1).fill(0);for (let i 0; i < num; i) {res[i] countOne(i.toString(2));}return res; };…

Spring配置AOP切入點execution詳解

例&#xff1a; execution (* com.sample.service…*. *(…)) 整個表達式可以分為五個部分&#xff1a; 1、execution():&#xff1a;表達式主體。 2、第一個*號&#xff1a;表示返回類型&#xff0c; *號表示所有的類型。 3、包名&#xff1a;表示需要攔截的包名&#xff…

Netty

1BS/CS? 2斷點續傳需要activeX,需要獨立客戶端有狀態,tomcat無狀態,或者Netty有狀態,可以斷點續傳 3Netty核心java nio性能比較高 4Jetty和Netty和dubbo區別? 5 轉載于:https://www.cnblogs.com/xinglongbing521/p/10105351.html

sympy科學計算器

SymPy庫常用函數 簡介 本文抄于https://www.cnblogs.com/baby123/p/6296629.html SymPy是一個符號計算的Python庫。它的目標是成為一個全功能的計算機代數系統&#xff0c;同時保持代碼簡 潔、易于理解和擴展。它完全由Python寫成&#xff0c;不依賴于外部庫。SymPy支持符號計算…

【異或運算】 - 交換2個數

1. 代碼 let a 3; let b 4; a a ^ b; b a ^ b; a a ^ b;2. 異或的性質 不同為1,相同為0(可以看做是無進制位的加法)交換律: a ^ b b ^ a;結合律: (a ^ b) ^ c a ^ (b ^ a);0 ^ x x;x ^ x 0; 3. 證明 下面證明1中的代碼 a 3 ^ 4;b (3 ^ 4) ^ 4 3 ^ 0 3;a (3…

Spring底層控制反轉解耦合(IOC)

簡單的例子解釋IOC控制反轉進行解耦合 一、相關概念 &#xff08;1&#xff09;解耦合 解耦合就是把程序中互相不相關或有限相關的模塊分割開來&#xff0c;把不同模塊互相之間的關系用接口進行準確定義&#xff0c;解耦前&#xff0c;兩個模塊之間共享所有信息&#xff1b; &…

Manacher算法學習筆記 | LeetCode#5

Manacher算法學習筆記 DECLARATION 引用來源&#xff1a;https://www.cnblogs.com/grandyang/p/4475985.html CONTENT 用途&#xff1a;尋找一個字符串的最長回文子串時間復雜度&#xff1a;O(N)算法步驟&#xff1a; 1.添加特殊字符 由于回文串的長度可奇可偶&#xff0c;比如…

content-type對照表

轉載于:https://www.cnblogs.com/mxyr/p/9238329.html

【算法小積累】 - 提取非0數最右側的1

參考 - 69:49 const getRightOne num > {return num & (~num 1); };

解耦合

廣大程序猿同胞&#xff0c;經常會看到“解耦合”&#xff0c;也有很多人&#xff0c;會用這個詞來裝X&#xff0c;但是&#xff0c;實際真正能理解的人&#xff0c;并不多。接下來&#xff0c;帶大家深入淺出的走一遍&#xff0c;如何解耦合。 首先&#xff0c;我們要知道&am…

CentOS安裝和配置Rsync進行文件同步

Liunx系統實現文件同步不需要搭建FTP這類的工具&#xff0c;只需要按照Rsync配置下文件就可以。 本文以Centos7.0為例。 1. 首先關閉SELINUX&#xff08;不關閉無法同步&#xff0c;權限太高了&#xff09; vi /etc/selinux/config #編輯防火墻配置文件 #SELINUXenforcing #注釋…

【linux】 -設備名稱與文件目錄

參考 - 鳥哥的linux私房菜基礎篇 在linux系統中,每個設備都被當成一個文件來對待幾乎所有的硬件設備文件都在/dev這個目錄內 下面給出,常見設備和文件路徑的對應關系 設備設備在Linux中的文件名SCSI、SATA、USB磁盤驅動器/dev/sd[a-p]U盤/dev/sd[a-p] (與SATA相同)Virtio接口/…

數據結構開發(7):典型問題分析(Bugfix)

0.目錄 1.創建異常對象時的空指針問題 2.LinkList 中的數據元素刪除 3.LinkList 中遍歷操作與刪除操作的混合使用 4.StaticLinkList 中數據元素刪除時的效率問題 5.StaticLinkList 是否需要提供析構函數&#xff1f; 6.StLib 是否有必要增加多維數組類&#xff1f; 1.創建異常對…

spring boot 使用視圖modelandview

1&#xff1a;springboot使用視圖解析器&#xff0c;添加依賴 <!-- freemarker模板引擎視圖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency>&…

題解-BOI 2004 Sequence

Problem bzoj & Luogu 題目大意&#xff1a; 給定序列\(\{a_i\}\)&#xff0c;求一個嚴格遞增序列\(\{b_i\}\)&#xff0c;使得\(\sum \bigl |a_i-b_i\bigr|\)最小 Thought 正序&#xff1a;直接對應 逆序&#xff1a;取中位數&#xff08;證明&#xff1a;“醫院設置”&am…

【vscode】編譯java時報錯亂碼

報錯如下 解決方案 改變終端的編碼格式 chcp 946注意: chcp 65001 UTF-8編碼chcp 936 GBK2312代碼頁