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

Spring源碼閱讀入門(mén)指引

開(kāi)發(fā) 后端
本文大概的對(duì)IOC和AOP進(jìn)行了解,入門(mén)先到這一點(diǎn)便已經(jīng)有了大概的印象了,詳細(xì)內(nèi)容請(qǐng)看下文。

本文說(shuō)明2點(diǎn):

1.閱讀源碼的入口在哪里?

2.入門(mén)前必備知識(shí)了解:IOC和AOP

一、我們從哪里開(kāi)始

1.準(zhǔn)備工作:在官網(wǎng)上下載了Spring源代碼之后,導(dǎo)入Eclipse,以方便查詢(xún)。

2.打開(kāi)我們使用Spring的項(xiàng)目工程,找到Web.xml這個(gè)網(wǎng)站系統(tǒng)配置文件,在其中找到Spring的初始化信息:

  1. <listener> 
  2.  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
  3. </listener> 

由配置信息可知,我們開(kāi)始的入口就這里ContextLoaderListener這個(gè)監(jiān)聽(tīng)器。

在源代碼中我們找到了這個(gè)類(lèi),它的定義是:

  1. public class ContextLoaderListener extends ContextLoader  
  2.  implements ServletContextListener {  
  3.     …  
  4.  /**  
  5.   * Initialize the root web application context.  
  6.   */ 
  7.  public void contextInitialized(ServletContextEvent event) {  
  8.   this.contextLoader = createContextLoader();  
  9.   if (this.contextLoader == null) {  
  10.    this.contextLoader = this;  
  11.   }  
  12.   this.contextLoader.initWebApplicationContext(event.getServletContext());  
  13.  }  
  14.   ...  
  15. }  

該類(lèi)繼續(xù)了ContextLoader并實(shí)現(xiàn)了監(jiān)聽(tīng)器,關(guān)于Spring的信息載入配置、初始化便是從這里開(kāi)始了,具體其他閱讀另外寫(xiě)文章來(lái)深入了解。

二、關(guān)于IOC和AOP

關(guān)于Spring IOC 網(wǎng)上很多相關(guān)的文章可以閱讀,那么我們從中了解到的知識(shí)點(diǎn)是什么?

1)IOC容器和AOP切面依賴(lài)注入是Spring是核心。

IOC容器為開(kāi)發(fā)者管理對(duì)象之間的依賴(lài)關(guān)系提供了便利和基礎(chǔ)服務(wù),其中Bean工廠(BeanFactory)和上下文(ApplicationContext)就是IOC的表現(xiàn)形式

BeanFactory是個(gè)接口類(lèi),只是對(duì)容器提供的最基本服務(wù)提供了定義,而DefaultListTableBeanFactory、XmlBeanFactory、ApplicationContext等都是具體的實(shí)現(xiàn)。

接口:

  1. public interface BeanFactory {  
  2.  //這里是對(duì)工廠Bean的轉(zhuǎn)義定義,因?yàn)槿绻褂胋ean的名字檢索IOC容器得到的對(duì)象是工廠Bean生成的對(duì)象,  
  3.  //如果需要得到工廠Bean本身,需要使用轉(zhuǎn)義的名字來(lái)向IOC容器檢索  
  4.  String FACTORY_BEAN_PREFIX = "&";  
  5.  //這里根據(jù)bean的名字,在IOC容器中得到bean實(shí)例,這個(gè)IOC容器就象一個(gè)大的抽象工廠,用戶(hù)可以根據(jù)名字得到需要的bean  
  6.  //在Spring中,Bean和普通的JAVA對(duì)象不同在于:  
  7.  //Bean已經(jīng)包含了我們?cè)贐ean定義信息中的依賴(lài)關(guān)系的處理,同時(shí)Bean是已經(jīng)被放到IOC容器中進(jìn)行管理了,有它自己的生命周期  
  8.  Object getBean(String name) throws BeansException;  
  9.  //這里根據(jù)bean的名字和Class類(lèi)型來(lái)得到bean實(shí)例,和上面的方法不同在于它會(huì)拋出異常:如果根名字取得的bean實(shí)例的Class類(lèi)型和需要的不同的話。  
  10.  Object getBean(String name, Class requiredType) throws BeansException;  
  11.  //這里提供對(duì)bean的檢索,看看是否在IOC容器有這個(gè)名字的bean  
  12.  boolean containsBean(String name);  
  13.  //這里根據(jù)bean名字得到bean實(shí)例,并同時(shí)判斷這個(gè)bean是不是單件,在配置的時(shí)候,默認(rèn)的Bean被配置成單件形式,如果不需要單件形式,需要用戶(hù)在Bean定義信息中標(biāo)注出來(lái),這樣IOC容器在每次接受到用戶(hù)的getBean要求的時(shí)候,會(huì)生成一個(gè)新的Bean返回給客戶(hù)使用 - 這就是Prototype形式  
  14.  boolean isSingleton(String name) throws NoSuchBeanDefinitionException;  
  15.  //這里對(duì)得到bean實(shí)例的Class類(lèi)型  
  16.  Class getType(String name) throws NoSuchBeanDefinitionException;  
  17.  //這里得到bean的別名,如果根據(jù)別名檢索,那么其原名也會(huì)被檢索出來(lái)  
  18.  String[] getAliases(String name);  

實(shí)現(xiàn):

XmlBeanFactory的實(shí)現(xiàn)是這樣的:

  1. public class XmlBeanFactory extends DefaultListableBeanFactory {  
  2.  //這里為容器定義了一個(gè)默認(rèn)使用的bean定義讀取器,在Spring的使用中,Bean定義信息的讀取是容器初始化的一部分,但是在實(shí)現(xiàn)上是和容器的注冊(cè)以及依賴(lài)的注入是分開(kāi)的,這樣可以使用靈活的 bean定義讀取機(jī)制。  
  3.  private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);  
  4.  //這里需要一個(gè)Resource類(lèi)型的Bean定義信息,實(shí)際上的定位過(guò)程是由Resource的構(gòu)建過(guò)程來(lái)完成的。  
  5.  public XmlBeanFactory(Resource resource) throws BeansException {  
  6.  this(resource, null);  
  7.  }  
  8.  //在初始化函數(shù)中使用讀取器來(lái)對(duì)資源進(jìn)行讀取,得到bean定義信息。這里完成整個(gè)IOC容器對(duì)Bean定義信息的載入和注冊(cè)過(guò)程  
  9.  public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws 
  10.  BeansException {  
  11.  super(parentBeanFactory);  
  12.  this.reader.loadBeanDefinitions(resource);  

我們可以看到IOC容器使用的一些基本過(guò)程:

如:DefaultListableBeanFactory

  1. ClassPathResource res = new ClassPathResource("beans.xml");//讀取配置文件  
  2. DefaultListableBeanFactory factory = new DefaultListableBeanFactory();  
  3. XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);  
  4. reader.loadBeanDefinitions(res);  

這些代碼演示了以下幾個(gè)步驟:

1. 創(chuàng)建IOC配置文件的抽象資源

2. 創(chuàng)建一個(gè)BeanFactory,這里我們使用DefaultListableBeanFactory;

3. 創(chuàng)建一個(gè)載入bean定義信息的讀取器,這里使用XmlBeanDefinitionReader來(lái)載入XML形式的bean定義信息,配置給BeanFactory;

4. 從定義好的資源位置讀入配置信息,具體的解析過(guò)程由XmlBeanDefinitionReader來(lái)完成,這樣完成整個(gè)載入和注冊(cè)bean定義的過(guò)程。我們的IoC容器就建立起來(lái)了。

再簡(jiǎn)單的說(shuō),我的系統(tǒng)在啟動(dòng)時(shí)候,會(huì)完成的動(dòng)作就是:

1.由ResourceLoader獲取資源文件,也即bean的各種配置文件;

2.由BeanDefintion對(duì)配置文件的定義信息的載入;

3.用BeanDefinitionRegistry接口來(lái)實(shí)現(xiàn)載入bean定義信息并向IOC容器進(jìn)行注冊(cè)。

注意,IOC容器和上下文的初始化一般不包含Bean的依賴(lài)注入的實(shí)現(xiàn)。

2)AOP這個(gè)過(guò)程并不是在注冊(cè)bean的過(guò)程實(shí)現(xiàn)的。

我們只看到在處理相關(guān)的Bean屬性的時(shí)候,使用了RuntimeBeanReference對(duì)象作為依賴(lài)信息的紀(jì)錄。

在IOC容器已經(jīng)載入了用戶(hù)定義的Bean信息前提下,這個(gè)依賴(lài)注入的過(guò)程是用戶(hù)第一次向IOC容器索要Bean的時(shí)候觸發(fā)的,或者是我們可以在Bean定義信息中通過(guò)控制lazy-init屬性來(lái)使得容器完成對(duì)Bean的預(yù)實(shí)例化 - 這個(gè)預(yù)實(shí)例化也是一個(gè)完成依賴(lài)注入的過(guò)程。

我們說(shuō)明一下過(guò)程:

1.用戶(hù)想IOC容器請(qǐng)求Bean。

2.系統(tǒng)先在緩存中查找是否有該名稱(chēng)的Bean(去各個(gè)BeanFactory去查找)

3.沒(méi)有的話就去創(chuàng)建Bean并進(jìn)行依賴(lài)注入,并且這個(gè)請(qǐng)求將被記錄起來(lái)。

請(qǐng)求Bean具體的實(shí)現(xiàn):

代碼入口在DefaultListableBeanFactory的基類(lèi)AbstractBeanFactory中:

  1. public Object getBean(String name, Class requiredType, final Object[] args) throwsBeansException {  
  2. ...  
  3.  Object sharedInstance = getSingleton(beanName);//先去緩存取  
  4.  if (sharedInstance != null) {  
  5.  ...  
  6.   if (containsBeanDefinition(beanName)) {  
  7.    RootBeanDefinition mergedBeanDefinition = getMergedBeanDefinition(beanName, false);  
  8.    bean = getObjectForBeanInstance(sharedInstance, name,mergedBeanDefinition);  
  9.   }  
  10.   else {  
  11.    bean = getObjectForBeanInstance(sharedInstance, name, null);  
  12.   }  
  13.  }  
  14.  else {  
  15.    
  16.  }  
  17.  
  18. ...  

注入Bean具體的實(shí)現(xiàn):

具體的bean創(chuàng)建過(guò)程和依賴(lài)關(guān)系的注入在createBean中,這個(gè)方法在AbstractAutowireCapableBeanFactory中給出了實(shí)現(xiàn):

  1. protected Object createBean(String beanName, RootBeanDefinition  
  2. mergedBeanDefinition, Object[] args)  
  3. throws BeanCreationException {  
  4.  // Guarantee initialization of beans that the current one depends on.  
  5.  // 這里對(duì)取得當(dāng)前bean的所有依賴(lài)bean,確定能夠取得這些已經(jīng)被確定的bean,如果沒(méi)有被創(chuàng)建,那么這個(gè)createBean會(huì)被這些IOC  
  6.  // getbean時(shí)創(chuàng)建這些bean  
  7.  if (mergedBeanDefinition.getDependsOn() != null) {  
  8.   for (int i = 0; i < mergedBeanDefinition.getDependsOn().length; i++) {  
  9.    getBean(mergedBeanDefinition.getDependsOn()[i]);  
  10.   }  
  11.  }  
  12.  ........  
  13.  // 這里是實(shí)例化bean對(duì)象的地方,注意這個(gè)BeanWrapper類(lèi),是對(duì)bean操作的主要封裝類(lèi)  
  14.  if (instanceWrapper == null) {  
  15.   instanceWrapper = createBeanInstance(beanName, mergedBeanDefinition,args);  
  16.  }  
  17.  Object bean = instanceWrapper.getWrappedInstance();  
  18.  ......  
  19.  //這個(gè)populate方法,是對(duì)已經(jīng)創(chuàng)建的bean實(shí)例進(jìn)行依賴(lài)注入的地方,會(huì)使用到在loadBeanDefinition的時(shí)候得到的那些propertyValue來(lái)對(duì)bean進(jìn)行注入。  
  20.  if (continueWithPropertyPopulation) {  
  21.   populateBean(beanName, mergedBeanDefinition, instanceWrapper);  
  22.  }  
  23.  //這里完成客戶(hù)自定義的對(duì)bean的一些初始化動(dòng)作  
  24.  Object originalBean = bean;  
  25.  bean = initializeBean(beanName, bean, mergedBeanDefinition);  
  26.  // Register bean as disposable, and also as dependent on specified "dependsOn"beans.  
  27.  registerDisposableBeanIfNecessary(beanName, originalBean,mergedBeanDefinition);  
  28.  return bean;  
  29. }  
  30. .........  

這就是整個(gè)依賴(lài)注入的部分處理過(guò)程,在這個(gè)過(guò)程中起主要作用的是WrapperImp ,這個(gè)Wrapper不是一個(gè)簡(jiǎn)單的對(duì)bean對(duì)象的封裝,因?yàn)樗枰幚碓赽eanDefinition中的信息來(lái)迭代的處理依賴(lài)注入。

到這里,這是簡(jiǎn)單的,大概的對(duì)IOC和AOP進(jìn)行了解,入門(mén)先到這一點(diǎn)便已經(jīng)有了大概的印象了。

參考資料:《Spring_IOC詳解》

原文鏈接:http://blog.csdn.net/achan2090/article/details/7248043

【編輯推薦】

  1. Java多線程之消費(fèi)者生產(chǎn)者模式
  2. 深入理解Java對(duì)象序列化
  3. 對(duì)于Java類(lèi)加載過(guò)程中的順序問(wèn)題探究
  4. 菜鳥(niǎo)入門(mén)Java語(yǔ)言學(xué)習(xí)的要點(diǎn)
  5. Java自定義范型的應(yīng)用技巧

 

責(zé)任編輯:林師授 來(lái)源: achan2090的博客
相關(guān)推薦

2013-12-24 10:05:04

memcached

2018-11-16 16:35:19

Java源碼編程語(yǔ)言

2021-12-26 18:30:56

嵌入式ARM鏈接

2022-10-08 08:01:17

Spring源碼服務(wù)

2017-04-05 16:40:45

2017-03-16 11:39:33

Openstack源碼姿勢(shì)

2018-03-28 16:10:23

閱讀源碼境界

2021-08-02 09:50:47

Vetur源碼SMART

2017-04-13 19:26:21

2021-12-20 07:58:59

GitHub源碼代碼

2014-07-29 09:44:58

jQuery源碼

2021-03-13 14:08:00

Hadoop 源碼HDFS

2009-06-26 17:34:29

Spring入門(mén)

2020-12-07 11:29:24

ReactVueVue3

2017-03-27 15:15:43

Hive源碼編譯

2023-07-10 08:43:53

SpringIDEA

2019-07-26 15:49:25

代碼開(kāi)發(fā)工具

2011-02-28 13:34:51

SpringMVC

2021-03-13 11:23:51

源碼邏輯框架

2021-09-16 10:36:34

開(kāi)源技術(shù) 項(xiàng)目
點(diǎn)贊
收藏

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