龙空技术网

Spring的两种容器类型

是蜃楼啊 161

前言:

此刻朋友们对“spring的容器有哪些”大致比较讲究,你们都需要知道一些“spring的容器有哪些”的相关知识。那么小编同时在网络上搜集了一些关于“spring的容器有哪些””的相关资讯,希望你们能喜欢,姐妹们快快来了解一下吧!

Spring提供了两种容器类型:BeanFactory和ApplicationContext

BeanFactory

基础类型IoC容器,提供完整的IoC服务支持。如果没有特殊指定,默认采用延迟初始化策略(lazy-load)。只有当客户端对象需要访问容器中的某个受管对象的时候,才对 该受管对象进行初始化以及依赖注入操作。所以,相对来说,容器启动初期速度较快,所需 要的资源有限。对于资源有限,并且功能要求不是很严格的场景,BeanFactory是比较合适的 IoC容器选择。

ApplicationContext

ApplicationContext在BeanFactory的基础上构建,是相对比较高 级的容器实现,除了拥有BeanFactory的所有支持,ApplicationContext还提供了其他高级特性,比如事件发布、国际化信息支持等。ApplicationContext所管理 的对象,在该类型容器启动之后,默认全部初始化并绑定完成。所以,相对于BeanFactory来 说,ApplicationContext要求更多的系统资源,同时,因为在启动时就完成所有初始化,容 器启动时间较之BeanFactory也会长一些。在那些系统资源充足,并且要求更多功能的场景中,ApplicationContext类型的容器是比较合适的选择。

BeanFactory和Applicationontext的继承关系图:

BeanFactory接口中的方法

//主要包含以下方法(有许多重载方法)Object getBean(String name) throws BeansException;<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);boolean containsBean(String name);boolean isSingleton(String name) throws NoSuchBeanDefinitionException;boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

上面代码中的方法基本上都是查询相关的方法,例如,取得某个对象的方法(getBean)、查询 某个对象是否存在于容器中的方法(containsBean),或者取得某个bean的状态或者类型的方法等 。

DefaultListableBeanFactory

BeanFactory只是一个接口,需要一个接口的实现类来进行Bean的管理。DefaultListableBeanFactory是BeanFactory接口的实现类。DefaultListableBeanFactory接口除了间接地实现了BeanFactory接口还实现了BeanDefinitionRegistry接口。

每一个受管的对象,在容器中都会有一个BeanDefinition的实例(instance)与之相对应,该BeanDefinition的实例负责保存对象的所有必要信息,包括其对应的对象的class类型、是否是抽象类、构造方法参数以及其他属性等。当客户端向BeanFactory请求相应对象的时候,BeanFactory会通过这些信息为客户端返回一个完备可用的对象实例。RootBeanDefinition和ChildBeanDefinition是BeanDefinition的两个主要实现类。

FactoryBean

某些对象的实例化过程过于烦琐,通过XML配置过于复杂,使我们宁愿使用Java代码来完成这 个实例化过程的时候,或者,某些第三方库(比如Mybatis)不能直接注册到Spring容器的时候,就可以实现org.spring.framework.beans.factory.FactoryBean接口,给出自己的对象实例化逻辑代代码。

FactoryBean作为一个接口,其内部仅包含三个方法:

T getObject() throws Exception;Class<?> getObjectType();default boolean isSingleton() {        return true;    }

getObjet()方法会返回按照程序员意愿使用FactoryBean生产出来的对象实例。 getObjectType()方法仅返回getObject()方法所返回的对象的类型,如果预先 无法确定,则返回null;isSingleton()方法返回结果用于表明,工厂方法(getObject())所“生 产”的对象是否要以singleton形式存在于容器中。如果以singleton形式存在,则返回true,否则返回false;

容器启动阶段

容器启动伊始,首先会通过某种途径加载Configuration MetaData。除了代码方式比较直接,在大部分情况下,容器需要依赖某些工具类(BeanDefinitionReader)对加载的Configuration MetaData 进行解析和分析,并将分析后的信息编组为相应的BeanDefinition,最后把这些保存了bean定义必 要信息的BeanDefinition,注册到相应的BeanDefinitionRegistry,这样容器启动工作就完成了。

干涉容器的启动BeanFactoryPostProcess

Spring提供了一种叫做BeanFactoryPostProcessor的容器扩展机制。该机制允许我们在容器实 例化相应对象之前,对注册到容器的BeanDefinition所保存的信息做相应的修改。这就相当于在容 器实现的第一阶段最后加入一道工序,让我们对最终的BeanDefinition做一些额外的操作,比如修 改其中bean定义的某些属性,为bean定义增加其他信息等。

Bean的实例化阶段

经过第一阶段,现在所有的bean定义信息都通过BeanDefinition的方式注册到了BeanDefinitionRegistry中。当某个请求方通过容器的getBean方法明确地请求某个对象,或者因依赖关系容器 需要隐式地调用getBean方法时,就会触发第二阶段的活动。

该阶段,容器会首先检查所请求的对象之前是否已经初始化。如果没有,则会根据注册的 BeanDefinition所提供的信息实例化被请求对象,并为其注入依赖。如果该对象实现了某些回调接口,也会根据回调接口的要求来装配它。当该对象装配完毕之后,容器会立即将其返回请求方使用。

容器启动之后,并不会马上就实例化相应的bean定义。我们知道,容器现在仅仅拥有所有对象的 BeanDefinition来保存实例化阶段将要用的必要信息。只有当请求方通过BeanFactory的getBean() 方法来请求某个对象实例的时候,才有可能触发Bean实例化阶段的活动。BeanFactory的getBe 法可以被客户端对象显式调用,也可以在容器内部隐式地被调用。隐式调用有如下两种情况。

对于BeanFactory来说,对象实例化默认采用延迟初始化。通常情况下,当对象A被请求而需 要第一次实例化的时候,如果它所依赖的对象B之前同样没有被实例化,那么容器会先实例化 对象A所依赖的对象。这时容器内部就会首先实例化对象B,以及对象 A依赖的其他还没有 实例化的对象。这种情况是容器内部调用getBean(),对于本次请求的请求方是隐式的。

ApplicationContext启动之后会实例化所有的bean定义,这个特性在本书中已经多次提到。 但ApplicationContext在实现的过程中依然遵循Spring容器实现流程的两个阶段,只不过它 会在启动阶段的活动完成之后,紧接着调用注册到该容器的所有bean定义的实例化方法 getBean()。这就是为什么当你得到ApplicationContext类型的容器引用时,容器内所有对 象已经被全部实例化完成。ApplicationContext

较之BeanFactory更为先进的IoC容器实现,ApplicationContext除了拥有 BeanFactory支持的所有功能之外,还进一步扩展了基本容器的功能,包括BeanFactoryPostProcessor、BeanPostProcessor以及其他特殊类型bean的自动识别、容器启动后bean实例的自动初始化、 国际化的信息支持、容器内事件发布等。

标签: #spring的容器有哪些