1、Spring中的BeanFactory
1.1、BeanFactory类视图
1.2 、工厂详解
1.2.1、BeanFactory
BeanFactory 中定义的各种方法如上面方法注释,整个设计还是比较简洁、直观的,其中将近一半是获取 bean 对象的各种方法,另外就是对 bean 属性的获取和判定,该接口仅仅是定义了 IoC 容器的最基本基本形式,具体实现都交由子类来实现。
1.2.2 、HierarchicalBeanFactory
HierarchicalBeanFactory 译为中文是“分层的”,它相对于 BeanFactory 增加了对父BeanFactory 的获取,子容器可以通过接口方法访问父容器,让容器的设计具备了层次性。这种层次性增强了容器的扩展性和灵活性,我们可以通过编程的方式为一个已有的容器添加一个或多个子容器,从而实现一些特殊功能。层次容器有一个特点就是子容器对于父容器来说是透明的,而子容器则能感知到父容器的存在。典型的应用场景就是 Spring MVC,控制层的 bean 位于子容器中,并将业务层和持久层的 bean 所在的容器设置为父容器,这样的设计可以让控制层的 bean 访问业务层和持久层的 bean,反之则不行,从而在容器层面对三层软件结构设计提供支持。
1.2.3 、ListableBeanFactory
ListableBeanFactory 引入了获取容器中 bean 的配置信息的若干方法,比如获取容器中 bean 的个数,获取容器中所有 bean 的名称列表,按照目标类型获取 bean 名称,以及检查容器中是否包含指定名称的 bean 等等。Listable 中文译为“可列举的”,对于容器而言,bean 的定义和属性是可以列举的对象。
1.2.4 、AutowireCapableBeanFactory
AutowireCapableBeanFactory 提供了创建 bean、自动注入,初始化以及应用 bean 的后置处理器等功能。自动注入让配置变得更加简单,也让注解配置成为可能,Spring 提供了四种自动注入类型:
byName:
根据名称自动装配。假设 bean A 有一个名为 b 的属性,如果容器中刚好存在一个 bean的名称为 b,则将该 bean 装配给 bean A 的 b 属性。
byType:
根据类型自动匹配。假设 bean A 有一个类型为 B 的属性,如果容器中刚好有一个 B 类型的 bean,则使用该 bean 装配 A 的对应属性。
constructor:
仅针对构造方法注入而言,类似于 byType。如果 bean A 有一个构造方法,构造方法包含一个 B 类型的入参,如果容器中有一个 B 类型的 bean,则使用该 bean 作为入参,如果找不到,则抛出异常。
autodetect:
根据 bean 的自省机制决定采用 byType 还是 constructor 进行自动装配。如果bean 提供了默认的构造函数,则采用 byType,否则采constructor。
总结:
<beans/> 元素标签中的 default-autowire 属性可以配置全局自动匹配,default-autowire 默认值为 no,表示不启用自动装配。在实际开发中,XML 配置方 式很少启用自动装配功能,而基于注解的配置方式默认采用 byType 自动装配策略。
1.2.5 、ConfigurableBeanFactory
ConfigurableBeanFactory 提供配置 Factory 的各种方法,增强了容器的可定制性,定义了设置类装载器、属性编辑器、容器初始化后置处理器等方法。
1.2.6 、DefaultListableBeanFactory
DefaultListableBeanFactory 是一个非常重要的类,它包含了 IoC 容器所应该具备的重要功能,是容器完整功能的一个基本实现,XmlBeanFactory 是一个典型的由该类派生出来的 Factory,并且只是增加了加载 XML 配置资源的逻辑,而容器相关的特性则全部由 DefaultListableBeanFactory 来实现
1.2.7 、ApplicationContext
ApplicationContext 是 Spring 为开发者提供的高级容器形式,也是我们初始化 Spring 容器的常用方式,除了简单容器所具备的功能外,ApplicationContext 还提供了许多额外功能来降低开发人员的开发量,提升框架的使用效率。这些额外的功能主要包括:
国际化支持:
ApplicationContext 实现了 org.springframework.context.MessageSource接口,该接口为容器提供国际化消息访问功能,支持具备多语言版本需求的应用开发,并提供了多种实现来简化国际化资源文件的装载和获取。
发布应用上下文事件:
ApplicationContext 实现了org.springframework.context.ApplicationEventPublisher 接口,该接口让容器拥有发布应用
上下文事件的功能,包括容器启动、关闭事件等,如果一个 bean 需要接收容器事件,则只需要实现ApplicationListener 接口即可,Spring 会自动扫描对应的监听器配置,并注册成为主题的观察者。
丰富的资源获取的方式:
ApplicationContext 实现了org.springframework.core.io.support.ResourcePatternResolver 接口,ResourcePatternResolver 的实现类 PathMatchingResourcePatternResolver 让我们可以采用Ant 风格的资源路径去加载配置文件。
1.2.8 、ConfigurableApplicationContext
ConfigurableApplicationContext 中主要增加了 refresh 和 close 两个方法,从而为应用上下文提供了启动、刷新和关闭的能力。其中 refresh 方法是高级容器的核心方法,方法中概括了高级容器初始化的主要流程(包含简单的容器的全部功能,以及高级容器特有的扩展功能)
1.2.9 、WebApplicationContext
WebApplicationContext 是为 WEB 应用定制的上下文,可以基于 WEB 容器来实现配置文件的加载,以及初始化工作。对于非 WEB 应用而言,bean 只有 singleton 和 prototype 两种作用域,而在WebApplicationContext 中则新增了 request、session、globalSession,以及 application四种作用域。
WebApplicationContext 将整个应用上下文对象以属性的形式放置到 ServletContext 中,所以在WEB 应用中,我们可以通过 WebApplicationContextUtils 的getWebApplicationContext(ServletContext sc) 方法,从 ServletContext 中获取到
ApplicationContext 实例。为了支持这一特性,WebApplicationContext 定义了一个常量:ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() +".ROOT".
并在初始化应用上下文时以该常量为 key,将 WebApplicationContext 实例存放到 ServletContext的属性列表中,当我们在调用WebApplicationContextUtils 的getWebApplicationContext(ServletContext sc) 方法时,本质上是在调用 ServletContext 的getAttribute(String name) 方法,只不过 Spring 会对获取的结果做一些校验。
1.2.10 、高级容器的一些具体实现类型
AnnotationConfigApplicationContext:
是基于注解驱动开发的高级容器类,该类中提供了AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner两个成员,AnnotatedBeanDefinitionReader用于读取注解创建Bean的定义信息,ClassPathBeanDefinitionScanner负责扫描指定包获取Bean的定义信息。
ClasspathXmlApplicationContext:
是基于xml配置的高级容器类,它用于加载类路径下配置文件。
FileSystemXmlApplicationContext:
是基于xml配置的高级容器类,它用于加载文件系统中的配置文件。
AnnotationConfigWebApplicationContext:
是注解驱动开发web应用的高级容器类。