1 IOC容器设计与实现

在Spring IOC容器的设计中,可以看到两个主要的容器系列,一个是实现BeanFactory接口的简单容器系列,这系列容器只实现了容器的最基本功能;另一个是ApplicationContext应用上下文,它作为容器的高级形态而存在。应用上下文在简单容器的基础上,增加了许多面向框架的特性,同时对应用环境做了许多适配。


1 BeanFactory

1.1 BeanFactory的应用场景

BeanFactory接口的第一行有这样一段代码

<span style="font-size:18px;">String FACTORY_BEAN_PREFIX = "&";</span>

它定义了一个转义字符“&”,用来区分通过容器获取FactoryBean产生的对象和获取FactoryBean本身。例如,myFactory是一个FactoryBean,那么使用“&myFactory”得到的是FactoryBean,而不是myFactory产生的对象

这BeanFactory接口中,定义了如下方法:

  • BeanFactory接口设计了getBean方法,这个方法是使用IoC容器API的主要方法,通过这个方法,可以取得IoC容器中管理的Bean,Bean的取得是通过指定名字来索引的。如果需要在获取Bean时对Bean的类型进行检查,BeanFactory接口定义了带有参数的getBean方法,这个方法的使用与不带参数的getBean方法类似,不同的是增加了对Bean检索的类型的要求。
    Object getBean(String name) throws BeansException;
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;
    <T> T getBean(Class<T> requiredType) throws BeansException;
    Object getBean(String name, Object... args) throws BeansException;
    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
    
  • 通过接口方法containsBean让用户能够判断容器是否含有指定名字的Bean。
    <span style="font-size:18px;">boolean containsBean(String name);</span>
  • 通过接口方法isSingleton来查询指定名字的Bean是否是Singleton类型的Bean。对于Singleton属性,用户可以在BeanDefinition中指定。
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
  • 通过接口方法isPrototype来查询指定名字的Bean是否是prototype类型的。与Singleton属性一样,这个属性也可以由用户在BeanDefinition中指定。
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
  • 通过接口方法isTypeMatch来查询指定了名字的Bean的Class类型是否是特定的Class类型。这个Class类型可以由用户来指定。
    boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;
  • 通过接口方法getType来查询指定名字的Bean的Class类型。
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;
  • 通过接口方法getAliases来查询指定了名字的Bean的所有别名,这些别名都是用户在BeanDefinition中定义的。
    String[] getAliases(String name);

1.2BeanFactory 容器的设计原理

XMLBeanFactory是BeanFactory的最简单、也是常用的实现类

public class XmlBeanFactory extends DefaultListableBeanFactory {

	private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);


	/**
	 * Create a new XmlBeanFactory with the given resource,
	 * which must be parsable using DOM.
	 * @param resource XML resource to load bean definitions from
	 * @throws BeansException in case of loading or parsing errors
	 */
	public XmlBeanFactory(Resource resource) throws BeansException {
		this(resource, null);
	}

	/**
	 * Create a new XmlBeanFactory with the given input stream,
	 * which must be parsable using DOM.
	 * @param resource XML resource to load bean definitions from
	 * @param parentBeanFactory parent bean factory
	 * @throws BeansException in case of loading or parsing errors
	 */
	public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
		super(parentBeanFactory);
		this.reader.loadBeanDefinitions(resource);
	}

}

它继承自DefaultListableBeanFactory这个类,在Spring中,实际上是把DefaultListableBeanFactory作为一个默认的功能完整的IoC容器来使用的。XmlBeanFactory在继承了DefaultListableBeanFactory容器的功能的同时,增加了新的功能,那就是解析XML文件来初始化BeanFactory。

根据源码可以看出,XMLBeanFactory的构造需要指定BeanDefinition 的来源,这个源自于Resouce的封装。这样IOC容器就可以利用BeanDefinition进行容器的初始化和依赖注入过程。


实际上整个BeanFactory的构建过程由如下几步完成

(1) 指定一个BeanDefinition的来源,这里用的是Resouce类

(2) 定义一个IOC容器,即XMLBeanFactory ,也可以认为是DefaultListableBeanFactory,这时这个容器还是空的,里面什么都没有

(3) 需要在BeanDefinitionIOC容器之间建立起关系,在XMLBeanFactory中使用的是XmlBeanDefinitionReader,它将完成完成IOC容器的配置,这个时候IOC容器就建立完成。

在BeanFactory的初始化时候,不会初始化所有的Bean,而是在getBean的时候才进行Bean的初始化

2 ApplicationContext

这是BeanFactory的继承体系中,一个位于中间位置的接口,它在BeanFactory的基础上,提供了一些更高级的功能。

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
		MessageSource, ApplicationEventPublisher, ResourcePatternResolver 

  • 支持不同的信息源。我们看到ApplicationContext扩展了MessageSource接口,这些信息源的扩展功能可以支持国际化的实现,为开发多语言版本的应用提供服务。
  • 访问资源。这一特性体现在对ResourceLoader和Resource的支持上,这样我们可以从不同地方得到Bean定义资源。这种抽象使用户程序可以灵活地定义Bean定义信息,尤其是从不同的I/O途径得到Bean定义信息。这在接口关系上看不出来,不过一般来说,具体ApplicationContext都是继承了DefaultResourceLoader的子类。因为DefaultResourceLoader是AbstractApplicationContext的基类,关于Resource在IoC容器中的使用,后面会有详细的讲解。
  • 支持应用事件。继承了接口ApplicationEventPublisher,从而在上下文中引入了事件机制。这些事件和Bean的生命周期的结合为Bean的管理提供了便利。
  • 在ApplicationContext中提供的附加服务。这些服务使得基本IoC容器的功能更丰富。因为具备了这些丰富的附加功能,使得ApplicationContext与简单的BeanFactory相比,对它的使用是一种面向框架的使用风格,所以一般建议在开发应用时使用ApplicationContext作为IoC容器的基本形式。

ApplicationContext的常用实现类是ClassPathXmlApplicationContext, FileSystemXmlApplicationContext和AnnotationConfigApplicationContext,如果在Web中使用Spring容器,则通常有XmlWebApplicationContext和AnnotationConfigWebApplicationContext两个实现类

在ApplicationContext初始化时,默认会预初始化所有的sigletonBean。这意味着在系统创建ApplicationContext时有较大的开销
















你可能感兴趣的:(1 IOC容器设计与实现)