Spring 源碼(一)Spring 容器的入口及簡單介紹


說明:
1.本篇不講述具體的Spring相關功能源碼分析,僅對源碼導讀的一些前提做一些准備和記錄

Spring 容器的初始化

 
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);

當我們完成一個ApplicationContext的實例化時就完成了Spring容器的初始化,而AnnotationConfigApplicationContext的構造方法也就是Spring容器的入口。

(IDEA當中可通過crtl+鼠標左鍵進入源碼查看 ,此處我已簡單的方式進行)

// 初始化容器 public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) { // 注冊 Spring 內置后置處理器的 BeanDefinition 到容器 this(); // 注冊配置類 BeanDefinition 到容器 register(annotatedClasses); // 加載或者刷新容器中的Bean refresh(); } 

這個構造方法只有三行:

  1. 注冊內置的BeanPostProcessor的BeanDefinition到容器
  2. 注冊配置類 BeanDefinition 到容器
  3. 加載或者刷新容器中的Bean

容器的初始化過程我認為大致分為:

  1. 注冊內置的BeanPostProcessor的BeanDefinition到容器
  2. 注冊配置類 BeanDefinition 到容器
  3. 解析配置類
  4. 初始化所有單例Bean,並注冊到容器

AnnotationConfigApplicationContext 總攬

我們來看下AnnotationConfigApplicationContext的類圖:

(進入AnnotationConfigApplicationContext-> 在Idea類中右鍵 ->查看類圖)

 

 接下來我們來看具體Spring的相關結構

 

 (類圖使用技巧:右鍵某個接口或者類可對整個類圖的相關類屬性進行查看,很多時候源碼沒法看細節性的東西,粗略的看下類結構及方法即可)

AnnotationConfigApplicationContext說明
  • BeanFactory:它定義了Spring IOC容器最基本的功能規范,主要用來實例化、配置和管理Bean,它是IOC容器容器的心脹。主要包括bean獲取,單例多例判斷,Bean類型及別名獲取

  • HierarchicalBeanFactory:繼承BeanFactory接口,新增了getParentBeanFactory()方法,使BeanFactory具備了雙親IOC容器的管理功能。

  • ListableBeanFactory:細化了許多BeanFactory接口的功能,比如getBeanDefinitionNames()方法(獲取容器中所有Bean定義的名稱)。

  • ResourceLoader:資源加載器。

  • MessageSource:支持不同的信息源,從而實現國際化。

  • ApplicationEventPublisher:支持應用事件,提供事件機制的定義。

  • EnvironmentCapable:提供了對環境變量的支持。

  • ApplicationContext:它繼承了上述所有接口,是IOC容器的高級形態,它定了一個完成容器的雛形。(重點的類需要稍微記一下 方便后續進行回顧學習)

  • AbstractApplicationContext:一個容器的抽象實現

用戶使用容器時,可以使用轉義符"&"來得到FactoryBean本身,如果不加則是獲取FactoryBean產生的對象。

BeanFactory和FactoryBean的區別

  • BeanFactory:它是對IOC容器所有Bean進行管理,如實例化,配置和獲取容器中的Bean。
  • FactoryBean:它是一個能夠生產或者修飾對象生成的工廠Bean。

BeanFactory :(通用bean處理)

  BeanFactory 是基礎類型的 IoC 容器,它由 org.springframework.beans.facytory.BeanFactory 接口定義,並提供了完整的 IoC 服務支持。簡單來說,BeanFactory 就是一個管理 Bean 的工廠,它主要負責初始化各種 Bean,並調用它們的生命周期方法。
BeanFactory 接口有多個實現類,最常見的是 org.springframework.beans.factory.xml.XmlBeanFactory,它是根據 XML 配置文件中的定義裝配 Bean 的。
創建 BeanFactory 實例時,需要提供 Spring 所管理容器的詳細配置信息,這些信息通常采用 XML 文件形式管理。其加載配置信息的代碼具體如下所示:

BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource("D://applicationContext.xml"));

FactoryBean:(復雜自定義bean處理)

  一般情況下,Spring通過反射機制利用<bean>的class屬性指定實現類實例化Bean,在某些情況下,實例化Bean過程比較復雜,如果按照傳統的方式,則需要在<bean>中提供大量的配置信息。配置方式的靈活性是受限的,這時采用編碼的方式可能會得到一個簡單的方案。Spring為此提供了一個org.springframework.bean.factory.FactoryBean的工廠類接口,用戶可以通過實現該接口定制實例化Bean的邏輯。FactoryBean接口對於Spring框架來說占用重要的地位,Spring自身就提供了70多個FactoryBean的實現。它們隱藏了實例化一些復雜Bean的細節,給上層應用帶來了便利。從Spring3.0開始,FactoryBean開始支持泛型,即接口聲明改為FactoryBean<T>的形式
 
下面簡單給一個FactoryBean的例子
1.Bean的Resourse配置
<beans xmlns="http://www.springframework.org/schema/beans"  
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
             xmlns:context="http://www.springframework.org/schema/context"  
             xmlns:aop="http://www.springframework.org/schema/aop"  
             xmlns:tx="http://www.springframework.org/schema/tx"  
             xsi:schemaLocation="http://www.springframework.org/schema/beans  
                     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
                     http://www.springframework.org/schema/context  
                     http://www.springframework.org/schema/context/spring-context-3.0.xsd  
                     http://www.springframework.org/schema/aop  
                     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
                     http://www.springframework.org/schema/tx  
                     http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">  
      
 <bean id="student" class="com.spring.bean.Student">    
  <property name="name" value="zhangsan" />    
 </bean>    
   
 <bean id="school" class="com.spring.bean.School">    
 </bean>   
   
 <bean id="factoryBeanPojo" class="com.spring.bean.FactoryBeanPojo">    
    <property name="type" value="student" />  
 </bean>   
</beans>

2. FactoryBean的實現類  實現FactoryBean  實現其接口方法  重寫getObject等其他bean方法

import org.springframework.beans.factory.FactoryBean;  
  
public class FactoryBeanPojo implements FactoryBean{  
    private String type;  
  
    @Override  
    public Object getObject() throws Exception {  
        if("student".equals(type)){  
            return new Student();             
        }else{  
            return new School();  
        }  
          
    }  
  
    @Override  
    public Class getObjectType() {  
        return School.class;  
    }  
  
    @Override  
    public boolean isSingleton() {  
        return true;  
    }  
  
    public String getType() {  
        return type;  
    }  
  
    public void setType(String type) {  
        this.type = type;  
    }  
      
}

3.普通bean注冊

public class School {  
    private String schoolName;  
    private String address;  
    private int studentNumber;  
    public String getSchoolName() {  
        return schoolName;  
    }  
    public void setSchoolName(String schoolName) {  
        this.schoolName = schoolName;  
    }  
    public String getAddress() {  
        return address;  
    }  
    public void setAddress(String address) {  
        this.address = address;  
    }  
    public int getStudentNumber() {  
        return studentNumber;  
    }  
    public void setStudentNumber(int studentNumber) {  
        this.studentNumber = studentNumber;  
    }  
    @Override  
    public String toString() {  
        return "School [schoolName=" + schoolName + ", address=" + address  
                + ", studentNumber=" + studentNumber + "]";  
    }  
}

public class Student {  
    private String name;    
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
}
 
         

 4.測試

import org.springframework.context.support.ClassPathXmlApplicationContext;  
  
import com.spring.bean.FactoryBeanPojo;  

public class FactoryBeanTest {  
    public static void main(String[] args){  
        String url = "com/spring/config/BeanConfig.xml";  
        ClassPathXmlApplicationContext cpxa = new ClassPathXmlApplicationContext(url);  
     //Bean工廠獲取FactoryBean來獲取bean
        Object school=  cpxa.getBean("factoryBeanPojo");  
     //獲取自定義BeanFactory工廠   需要加&符號來標識
        FactoryBeanPojo factoryBeanPojo= (FactoryBeanPojo) cpxa.getBean("&factoryBeanPojo");  

        System.out.println(school.getClass().getName());  
        System.out.println(factoryBeanPojo.getClass().getName());  
    }  
}

  結果:

com.spring.bean.Student 
com.spring.bean.FactoryBeanPojo

  總結:BeanFacoty是SpringIOC容器的默認Bean管理,通過Factotybean可以自定義一些復雜的Bean

BeanFactory和ApplicationContext的區別

通過繼承圖我們可以發現

  • BeanFactory是容器的基本定義。
  • ApplicationContext繼承自BeanFactory,是容器的高級形態,在BeanFactory的基礎上添加了許多對高級容器特性的支持。

 其次:

BeanFactory:

BeanFactory在啟動的時候不會去實例化Bean,有從容器中拿Bean的時候才會去實例化;

ApplicationContext:

ApplicationContext在啟動的時候就把所有的Bean全部實例化了。它還可以為Bean配置lazy-init=true來讓Bean延遲實例化


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM