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(); }
這個構造方法只有三行:
- 注冊內置的BeanPostProcessor的BeanDefinition到容器
- 注冊配置類 BeanDefinition 到容器
- 加載或者刷新容器中的Bean
容器的初始化過程我認為大致分為:
- 注冊內置的BeanPostProcessor的BeanDefinition到容器
- 注冊配置類 BeanDefinition 到容器
- 解析配置類
- 初始化所有單例Bean,並注冊到容器
AnnotationConfigApplicationContext 總攬
我們來看下AnnotationConfigApplicationContext的類圖:
(進入AnnotationConfigApplicationContext-> 在Idea類中右鍵 ->查看類圖)
接下來我們來看具體Spring的相關結構
(類圖使用技巧:右鍵某個接口或者類可對整個類圖的相關類屬性進行查看,很多時候源碼沒法看細節性的東西,粗略的看下類結構及方法即可)
- 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>的形式<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延遲實例化