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延遲實例化
