本節來學習IOC容器的設計:
IOC容器的設計UML:
- 從接口BeanFactory到HierarchicalBeanFactory,再到ConfigurableBeanFactory,是一條主要的beanFactory的設計路徑。其中,BeanFactory接口定義了基本的IOC容器的規範。在這個接口定義中,包含了getBean()這樣的IOC容器的基本方法。而HierarchicalBeanFactory接口繼承了BeanFactory的基本接口後,增加了getParentBeanFactory()的接口功能,使BeanFactory具備了雙親Ioc容器的管理功能。在接下來的ConfigurableBeanFactory接口中,主要定義了一些對BeanFactory的配置功能,比如通過setParentBeanFactory設置雙親Ioc容器,通過addBeanPostProcessor配置Bean的後置處理器,等等。
- 從BeanFactory到ListableBeanFactory到ApplicationContext再到WebApplicationContext或者ConfigurableApplicationContext接口,是一條以ApplicationContext應用上下文接口爲核心的接口設計。ListableBeanFactory細化了許多BeanFactory的接口功能,如定義了getBeanDefinitionNames接口方法,ApplicationContext通過繼承MessageSource、ApplicationEventPublisher、ResourcePatternResolver接口,在BeanFactory簡單IOC容器的基礎上添加了許多對高級容器的特性的支持。
- DefaultListableBeanFactory這個基本的IOC容器就是實現了ConfigurableListableBeanFactory、BeanDefinitionRegistry從而成爲一個簡單IOC容器的實現。
1.BeanFactory的應用場景:
用戶在使用容器時,可以使用&得到FactoryBean本身,用來區分通過容器來獲取FactoryBean產生的對象和獲取FactoryBean本身。
public interface BeanFactory {
/**
* 通過名稱獲取bean
*/
Object getBean(String name) throws BeansException;
/**
* 通過名稱和類型獲取Bean
*/
<T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;
/**
*
*/
Object getBean(String name, Object... args) throws BeansException;
/**
* 通過類型獲取Bean
*/
<T> T getBean(Class<T> requiredType) throws BeansException;
/**
*
*/
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
/**
* 判斷容器是否含有指定名字的Bean
*/
boolean containsBean(String name);
/**
* 查詢指定名字的Bean是否是單例類型的
*/
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
/**
* 查詢指定名字的Bean是否是prototype類型的
*/
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
/**
* 指定了名字的Bean的Class類型是否是特定的Class類型
*/
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
/**
* 指定了名字的Bean的Class類型是否是特定的Class類型
*/
boolean isTypeMatch(String name, @Nullable Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
/**
* 查詢指定名字的Bean的Class類型
*/
@Nullable
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
/**
* 查詢指定了名字的Bean的所有別名
*/
String[] getAliases(String name);
2.BeanFactory容器的設計原理
XmlBeanFactory設計的類繼承關係:
注意:XmlBeanFactory在最新的版本中已經不建議使用
在Spring中,實際上DefaultListableBeanFactory作爲一個默認的功能完整的IOC容器來使用的。XmlBeanFactory在繼承了DefaultListableBeanFactory容器功能的同時,增加了新的功能,可以讀取以XML文件方式定義的BeanDefinition的IOC容器。
XMl讀取的功能,是在XmlBeanFactory類中初始化了一個XmlBeanDefinitionReader對象,這個對象可以處理XMl文件讀取。
@Deprecated
@SuppressWarnings({"serial", "all"})
public class XmlBeanFactory extends DefaultListableBeanFactory {
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
}
3.ApplicationContext的應用場景
ApplicationContext是一個高級形態的IOC容器
3.1支持不同的信息源。ApplicationContext擴展了MessageSource接口,這些信息源的擴展功能可以支持國際化的實現,爲開發多語言版本的應用提供服務。
3.2訪問資源。這點體現在對ResourceLoader的支持上,可以從不同地方得到Bean的資源。
3.3支持應用事件。繼承了接口ApplicationEventPublisher,從而在上下文中引入事件機制。這些事件和Bean的生命週期的結合爲Bean的管理提供了便利。
4.ApplicationContext容器的設計原理
以FileSystemXmlApplicationContext實現類爲例子,可以看到主要功能已經在基類AbstractXmlApplicationContext實現了,在FileSystemXmlApplicationContext中,作爲一個具體的應用上下文,只需要實現兩個功能:
public FileSystemXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
啓動IOC容器的refresh,後續再展開。
另一個功能是從文件系統中加載XMl的Bean定義資源
@Override
protected Resource getResourceByPath(String path) {
if (path.startsWith("/")) {
path = path.substring(1);
}
return new FileSystemResource(path);
}