本节来学习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); }