自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Spring源碼之Bean實(shí)例化基本原理

開發(fā) 前端
在實(shí)例化Bean之前在BeanDefinition里頭已經(jīng)有了所有需要實(shí)例化時(shí)用到的元數(shù)據(jù),接下來Spring只需要選擇合適的實(shí)例化方法以及策略即可。

 [[346085]]

創(chuàng)建Spring Bean實(shí)例化是Spring Bean生命周期的第一階段

Bean的生命周期主要有如下幾個(gè)步驟:

「詳細(xì)介紹:Spring In Action是這樣講的:」

  • 實(shí)例化Bean對象,這個(gè)時(shí)候Bean的對象是非常低級(jí)的,基本不能夠被我們使用,因?yàn)檫B最基本的屬性都沒有設(shè)置,可以理解為連Autowired注解都是沒有解析的;
  • 填充屬性,當(dāng)做完這一步,Bean對象基本是完整的了,可以理解為Autowired注解已經(jīng)解析完畢,依賴注入完成了;
  • 如果Bean實(shí)現(xiàn)了BeanNameAware接口,則調(diào)用setBeanName方法;
  • 如果Bean實(shí)現(xiàn)了BeanClassLoaderAware接口,則調(diào)用setBeanClassLoader方法;
  • 如果Bean實(shí)現(xiàn)了BeanFactoryAware接口,則調(diào)用setBeanFactory方法;
  • 調(diào)用BeanPostProcessor的postProcessBeforeInitialization方法;
  • 如果Bean實(shí)現(xiàn)了InitializingBean接口,調(diào)用afterPropertiesSet方法;
  • 如果Bean定義了init-method方法,則調(diào)用Bean的init-method方法;
  • 調(diào)用BeanPostProcessor的postProcessAfterInitialization方法;當(dāng)進(jìn)行到這一步,Bean已經(jīng)被準(zhǔn)備就緒了,一直停留在應(yīng)用的上下文中,直到被銷毀;
  • 如果應(yīng)用的上下文被銷毀了,如果Bean實(shí)現(xiàn)了DisposableBean接口,則調(diào)用destroy方法,如果Bean定義了destory-method聲明了銷毀方法也會(huì)被調(diào)用。

在實(shí)例化Bean之前在BeanDefinition里頭已經(jīng)有了所有需要實(shí)例化時(shí)用到的元數(shù)據(jù),接下來Spring只需要選擇合適的實(shí)例化方法以及策略即可。

「BeanDefinition」

Spring容器啟動(dòng)的時(shí)候會(huì)定位我們的配置文件,加載文件,并解析成Bean的定義文件BeanDefinition

右邊的Map里存儲(chǔ)這bean之間的依賴關(guān)系的定義BeanDefinition,比如OrderController依賴OrderService這種

實(shí)例化方法有兩大類分別是工廠方法和構(gòu)造方法實(shí)例化,后者是最常見的。其中Spring默認(rèn)的實(shí)例化方法就是無參構(gòu)造函數(shù)實(shí)例化。

如我們在xml里定義的以及用注解標(biāo)識(shí)的bean都是通過默認(rèn)實(shí)例化方法實(shí)例化的

實(shí)例化方法

「使靜態(tài)工廠方法實(shí)例化」

  1. public class FactoryInstance { 
  2.  
  3.     public FactoryInstance() { 
  4.         System.out.println("instance by FactoryInstance"); 
  5.     } 
  1. public class MyBeanFactory { 
  2.  
  3.     public static FactoryInstance getInstanceStatic(){ 
  4.         return new FactoryInstance(); 
  5.     } 
  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <beans xmlns="http://www.springframework.org/schema/beans" 
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  4.        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
  5.  
  6.     <bean id="factoryInstance" class="spring.service.instance.MyBeanFactory"  
  7.           factory-method="getInstanceStatic"/> 
  8. </beans> 

「使用實(shí)例工廠方法實(shí)例化」

  1. public class MyBeanFactory { 
  2.  
  3.     /** 
  4.      * 實(shí)例工廠創(chuàng)建bean實(shí)例 
  5.      * 
  6.      * @return 
  7.      */ 
  8.     public FactoryInstance getInstance() { 
  9.         return new FactoryInstance(); 
  10.     } 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">  
  5.     <!-- 工廠實(shí)例 -- >     
  6.     <bean id="myBeanFactory" class="MyBeanFactory"/>  
  7.     <bean id="factoryInstance" factory-bean="myBeanFactory" factory-method="getInstance"/>  
  8. </beans>  

「使用無參構(gòu)造函數(shù)實(shí)例化(默認(rèn)的)」

  1. public class ConstructorInstance { 
  2.  
  3.     public ConstructorInstance() { 
  4.         System.out.println("ConstructorInstance none args"); 
  5.     } 
  6.  
  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <beans xmlns="http://www.springframework.org/schema/beans" 
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  4.        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
  5.     <bean id="constructorInstance" class="spring.service.instance.ConstructorInstance"/> 
  6. </beans> 

「使用有參構(gòu)造函數(shù)實(shí)例化」

  1. public class ConstructorInstance { 
  2.  
  3.     private String name
  4.      
  5.     public ConstructorInstance(String name) { 
  6.         System.out.println("ConstructorInstance with args"); 
  7.         this.name = name
  8.     } 
  9.  
  10.     public String getName() { 
  11.         return name
  12.     } 
  13.  
  14.     public void setName(String name) { 
  15.         this.name = name
  16.     } 
  17.  
  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <beans xmlns="http://www.springframework.org/schema/beans" 
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  4.        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
  5.         
  6.    <bean id="constructorInstance" class="spring.service.instance.ConstructorInstance"
  7.         <constructor-arg index="0" name="name" value="test constructor with args"/> 
  8.     </bean> 
  9. </beans> 

源碼閱讀

直接來看看doCreateBean方法

具體實(shí)現(xiàn)在AbstractAutowireCapableBeanFactory類里面。

我們這里只需關(guān)注第一步創(chuàng)建bean實(shí)例的流程即可

  1. instanceWrapper = createBeanInstance(beanName, mbd, args); 

上面代碼就是spring 實(shí)現(xiàn)bean實(shí)例創(chuàng)建的核心代碼。這一步主要根據(jù)BeanDefinition里的元數(shù)據(jù)定義決定使用哪種實(shí)例化方法,主要有下面三種:

  • instantiateUsingFactoryMethod 工廠方法實(shí)例化的具體實(shí)現(xiàn)
  • autowireConstructor 有參構(gòu)造函數(shù)實(shí)例化的具體實(shí)現(xiàn)
  • instantiateBean 默認(rèn)實(shí)例化具體實(shí)現(xiàn)(無參構(gòu)造函數(shù))

「實(shí)例化策略(cglib or 反射)」

❝工廠方法的實(shí)例化手段沒有選擇策略直接用了反射實(shí)現(xiàn)的,所以這個(gè)實(shí)例化策略都是對于構(gòu)造函數(shù)實(shí)例化而言的❞

下面選一個(gè)instantiateBean的實(shí)現(xiàn)來介紹


 

 

上面說到的兩構(gòu)造函數(shù)實(shí)例化方法不管是哪一種都會(huì)選一個(gè)實(shí)例化策略進(jìn)行,到底選哪一種策略也是根據(jù)BeanDefinition里的定義決定的。

下面這一行代碼就是選擇實(shí)例化策略的代碼

  1. beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); 

「選擇使用反射還是cglib」

 

先判斷如果beanDefinition.getMethodOverrides()為空也就是用戶沒有使用replace或者lookup的配置方法,那么直接使用反射的方式,簡單快捷

但是如果使用了這兩個(gè)特性,在直接使用反射的方式創(chuàng)建實(shí)例就不妥了,因?yàn)樾枰獙⑦@兩個(gè)配置提供的功能切入進(jìn)去,所以就必須要使用動(dòng)態(tài)代理的方式將包含兩個(gè)特性所對應(yīng)的邏輯的攔截增強(qiáng)器設(shè)置進(jìn)去,這樣才可以保證在調(diào)用方法的時(shí)候會(huì)被相應(yīng)的攔截器增強(qiáng),返回值為包含攔截器的代理實(shí)例-----Spring源碼深度解析

  1. <bean id="constructorInstance" class="spring.service.instance.ConstructorInstance" > 
  2.         <lookup-method name="getName" bean="xxx"/> 
  3.         <replaced-method name="getName" replacer="yyy"/> 
  4.     </bean> 

如果使用了lookup或者replaced的配置的話會(huì)使用cglib,否則直接使用反射。

  1. public static final String LOOKUP_METHOD_ELEMENT = "lookup-method"
  2.  
  3. public static final String REPLACED_METHOD_ELEMENT = "replaced-method"

覺得不錯(cuò),點(diǎn)個(gè)贊再走吧,謝謝

參考:

Spring源碼深度解析

Spring In Action

 

https://url.ms/owy8p

本文轉(zhuǎn)載自微信公眾號(hào)「月伴飛魚」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系月伴飛魚公眾號(hào)。

 

責(zé)任編輯:武曉燕 來源: 月伴飛魚
相關(guān)推薦

2012-01-12 14:37:34

jQuery

2011-11-29 12:17:00

2009-02-24 09:43:00

IP電話原理

2016-08-17 23:53:29

網(wǎng)絡(luò)爬蟲抓取系統(tǒng)

2021-02-08 21:40:04

SockmapBPF存儲(chǔ)

2011-08-10 19:33:09

Cocoa對象

2016-08-18 00:04:09

網(wǎng)絡(luò)爬蟲抓取系統(tǒng)服務(wù)器

2010-08-20 13:29:33

OFDM

2020-03-21 14:57:14

手機(jī)定位智能手機(jī)APP

2013-04-07 14:09:55

Android應(yīng)用基本

2019-11-28 10:45:28

ZooKeeper源碼分布式

2011-07-07 14:46:10

Cocoa Xcode

2010-03-17 13:35:02

2010-03-18 20:13:03

Java socket

2020-12-29 16:55:44

ZooKeeper運(yùn)維數(shù)據(jù)結(jié)構(gòu)

2011-07-07 14:10:21

Cocoa 內(nèi)省 hash

2009-06-11 09:56:09

MySQL Repli原理

2010-01-07 09:53:09

Winform多線程編

2012-09-28 10:12:55

2020-11-26 13:54:03

容器LinuxDocker
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)