当前位置 : 主页 > 编程语言 > java >

Spring5 IOC容器解析——BeanFactory、ApplicationContext

来源:互联网 收集:自由互联 发布时间:2023-02-04
BeanFactory DefaultListableBeanFactory简单容器 此图是默认容器DefaultListableBeanFactory的继承实现关系图: 1、BeanFactory接口:容器顶级接口,提供了容器最基本的能力,包括获取bean,是否包含bean

BeanFactory

DefaultListableBeanFactory简单容器

此图是默认容器DefaultListableBeanFactory的继承实现关系图:

  • 1、BeanFactory接口:容器顶级接口,提供了容器最基本的能力,包括获取bean,是否包含bean,是否单例,获取bean类型,Bean的别名等方法。

  • 2、ListableBeanFactory接口:BeanFactory的子接口;具有批量获取Bean的能力

  • 3、HierarchicalBeanFactory接口:具有访问父容器的能力。有层次的BeanFactory。

  • 4、AutowireCapableBeanFactory接口:继承BeanFactory,扩展了自动装配能力。这个接口更多的作用是用于于与其他框架集成,把不在spring容器中的Bean加入到Spring容器生命周期管理中来。此接口很少用

  • 5、ConfigurableBeanFactory:定义了BeanFactory的配置。继承HierarchicalBeanFactory和SingletonBeanRegistry接口。实现了此接口的容器,具有层次,单例BeanDefinition注册功能。

  • 6、ConfigurableListableBeanFactory:大融合接口,除了具有上述接口的能外,还具有类加载器、类型转化、属性编辑器、BeanPostProcessor、作用域、bean定义、处理bean依赖关系、bean销毁等功能。

  • 7、SingletonBeanRegistry接口:具有Bean的操作能力,注册、查询、获取Bean数量等能力。注意此处的Bean是实例,区别于BeanDefinition。

  • 8、SimpleAliasRegistry:Bean的别名操作类,实现了AliasRegistry,具有存储Bean别名,注册Bean别名,获取Bean别名的功能,aliasMap属性存储Bean别名。

  • 9、DefaultSingletonBeanRegistry:除了继承了SimpleAliasRegistry的功能外,最重要的是实现了SingletonBeanRegistry接口,具有存储Bean实例、注册Bean、获取Bean的能力。我们定义的被Spring管理的Class类的实例对象,以及实例的之间的相互依赖关系都是存储在此类中,默认常用的容器DefaultListableBeanFactory的Bean的相关能力,就是通过间接继承此类来实现的。

/** Disposable bean instances: bean name to disposable instance. */ private final Map<String, Object> disposableBeans = new LinkedHashMap<>(); /** Map between containing bean names: bean name to Set of bean names that the bean contains. */ private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16); /** Map between dependent bean names: bean name to Set of dependent bean names. */ private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64); /** Map between depending bean names: bean name to Set of bean names for the bean's dependencies. */ private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
  • 10、FactoryBeanRegistrySupport:提供多工厂Bean的支持,FactoryBean通过其名字我也可以看出是生产Bean的Bean。

  • 11、AbstractBeanFactory抽象类:承上启下,从图中我们看出AbstractBeanFactory通过继承关系继承FactoryBeanRegistrySupport各种能力,而且实现了右边部分接口,已然是比较完备的Bean容器了。AbstractBeanFactory还通过模板模式定义了获取Bean的算法骨架。

  • 12、AbstractAutowireCapableBeanFactory:具有大部分的能力,实现了AbstractBeanFactory定义的模板方法,其中doCreateBean方法逻辑是把一个BeanDefinition变成Bean的过程,这个方法非常重要。通常我们使用类创建对象,直接new出来,spring把BeanDefinition到Bean的过程模板化,留下了很多扩展点,留给使用者可以在不同的时刻自定义BeanDefition创建Bean的过程。

  • 13、DefaultListableBeanFactory常用的默认容器实现,也是spring最常使用的容器类。DefaultListableBeanFactory实现了BeanDefinitionRegistry接口,说明DefaultListableBeanFactory具有存储BeanDefinition、操作BeanDefinition的能力,DefaultListableBeanFactory通过继承关系也具有了Bean的存储操作功能。

小结:

  • 1、BeanFactory体系,接口分明,完美的体现了接口分离原则。
  • 2、BeanFactory体系中有两种存储:一种是BeanDefinition的存储,另一个是Bean的存储。
  • 3、DefaultListableBeanFactory作为最常用的容器类,不但具有BeanDefinition的存储操作功能,而且通过继承具有Bean的存储操作功能的DefaultListableBeanFactory把存储的BeanDefinition通过一定算法创建Bean并存储起来。

BeanDefinition、BeanFactory、Bean三者关系

通过上面的对各个接口、类的认识,我们再来看看三者的关系。

我们向BeanFactory容器中注入一个BeanDefinition。BeanFactory帮我们存储起来。当我们想要得到一个Bean时,BeanFactory 帮我们把BeanDefinition创建成Bean并缓存起来,这个创建过程是可参与的。

  • BeanFactory保存了BeanDefiniton与Bean。
  • BeanFactory具有使用BeanDefinition创建Bean的功能。
  • BeanFactory允许使用者可以干预BeanDefinition生成Bean的功能。

BeanFactory中的扩展点

设计原则之开闭原则说的特别好:说一个软件实体应该通过扩展来实现变化。 很多优秀的框架都有类似的扩展点设计,列如:

  • Tomcat中的Filter
  • Tomcat中的pipline-valve
  • springmvc中的Interceptor

BeanFactory中从BeanDefinition到Bean并不是一下子就完成的,这有一个过程。spring正是在这个过程中留下扩展点来实现BeanDefinition到Bean的过程中的各种自定义变化。

 

从上面我们得知:AbstractAutowireCapableBeanFactory中有个doCreateBean()正是BeanDefinition到Bean的创建方法,接下来我们看看这个方法有哪些扩展点:

  • 1、xxxAware接口:使Bean可以获得xxx。列如实现了BeanFactoryAware接口的类,可以在该Bean被加载的过程中获取加载该Bean的BeanFactory。
  • 2、BeanPostProcessor:BeanPostProcessor接口定义的两个方法,分别在bean的初始化方法(InitializingBean接口,或者init-method定义)执行的前后执行
  • 3、InitializingBean接口:实现了InitializingBean接口的类,执行afterPropertiesSet
  • 4、自定义的init-method方法。

ApplicationContext高级容器

容器分为两套体系:一套是早期的 BeanFactory 体系;还有一套是现在常用的ApplicationContext,也可称为应用上下文,它继承了 BeanFactory,它除了有 BeanFactory 的功能外,还提供了其他服务,例如事务和 AOP 服务、国际化(il8n)的消息源以及应用程序事件处理等企业级的服务。

 

Spring支持两种配置方式,在早期都是 XML 配置文件的方式,而现在使用的是注解配置的方式。BeanFactory体系的容器一般用来处理 XML配置文件的方式,而ApplicationContext 体系则都可以处理。

 

ApplicationContext 是 BeanFactory 子类,它不仅包含 BeanFactory 所有功能,还对其进行了扩展,而我们习惯将 ApplicationContext 称为应用上下文,因为容器只是它的基本功能。

传统的基于XML配置的经典容器:

  • FileSystemXmlApplicationContext:从文件系统加载配置
  • ClassPathXmlApplicationContext:从ClassPath加载配置
  • XmlWebApplicationContext:用于Web应用程序的容器

目前比较流行的基于注解的容器:

  • AnnotationConfigServletWebServerApplicationContext:该类在SpringBoot的boot模块中
  • AnnotationConfigReactiveWebServerApplicationContext:满足响应式的容器需求,该类在SpringBoot的boot模块中。
  • AnnotationConfigApplicationContext:普通的非Web应用使用该容器
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver { // 返回此应用程序上下文的唯一ID @Nullable String getId(); // 返回此上下文所属的应用程序名称 String getApplicationName(); // 返回应用上下文具像化的类名 String getDisplayName(); // 返回第一次加载此上下文时的时间戳 long getStartupDate(); // 获取父级应用上下文 @Nullable ApplicationContext getParent(); // 将 AutowireCapableBeanFactory 接口暴露给外部使用 AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException; }

ApplicationContext 自身提供的方法非常简单,但它继承了六个接口,来扩展自身功能:

  • EnvironmentCapable:获取 Environment。
  • ListableBeanFactory、HierarchicalBeanFactory:这是 BeanFactory 体系接口,分别提供 Bean 迭代和访问父容器的功能。
  • MessageSource:支持国际化功能。
  • ApplicationEventPublisher:应用事件发布器,封装事件发布功能的接口。
  • ResourcePatternResolver:该接口继承至 ResourceLoader ,作用是加载多个 Resource。

ApplicationContext 同样提供了非常多的实现类,其又可细分为两大类, ConfigurableApplicationContext 和 WebApplicationContext。

ConfigurableApplicationContext

该接口是比较重要的一个接口,几乎所有的应用上下文都实现了该接口。该接口在ApplicationContext的基础上提供了配置应用上下文的能力,此外提供了生命周期的控制能力。

public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable { // 应用上下文配置时,这些符号用于分割多个配置路径 String CONFIG_LOCATION_DELIMITERS = ",; \t\n"; // BeanFactory中,ConversionService类所对应的bean的名字。如果没有此类的实例的话吗,则使用默认的转换规则 String CONVERSION_SERVICE_BEAN_NAME = "conversionService"; //LoadTimeWaver类所对应的Bean在容器中的名字。如果提供了该实例,上下文会使用临时的 ClassLoader ,这样,LoadTimeWaver就可以使用bean确切的类型了 String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver"; // Environment 类在容器中实例的名字 String ENVIRONMENT_BEAN_NAME = "environment"; // System 系统变量在容器中对应的Bean的名字 String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties"; // System 环境变量在容器中对应的Bean的名字 String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment"; // 设置容器的唯一ID void setId(String id); // 设置此容器的父容器 void setParent(@Nullable ApplicationContext parent); // 设置容器的 Environment 变量 void setEnvironment(ConfigurableEnvironment environment); // 以 ConfigurableEnvironment 的形式返回此容器的环境变量。以使用户更好的进行配置 @Override ConfigurableEnvironment getEnvironment(); // 此方法一般在读取应用上下文配置的时候调用,用以向此容器中增加BeanFactoryPostProcessor。增加的Processor会在容器refresh的时候使用。 void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor); // 向容器增加一个 ApplicationListener,增加的 Listener 用于发布上下文事件,如 refresh 和 shutdown 等 void addApplicationListener(ApplicationListener<?> listener); // 向容器中注入给定的 Protocol resolver void addProtocolResolver(ProtocolResolver resolver); // 这是初始化方法,因此如果调用此方法失败的情况下,要将其已经创建的 Bean 销毁。 // 换句话说,调用此方法以后,要么所有的Bean都实例化好了,要么就一个都没有实例化 void refresh() throws BeansException, IllegalStateException; // 向JVM注册一个回调函数,用以在JVM关闭时,销毁此应用上下文 void registerShutdownHook(); // 关闭此应用上下文,释放其所占有的所有资源和锁。并销毁其所有创建好的 singleton Beans @Override void close(); // 检测此 FactoryBean 是否被启动过 boolean isActive(); // 返回此应用上下文的容器。 // 千万不要使用此方法来对 BeanFactory 生成的 Bean 做后置处理,因为单例 Bean 在此之前已经生成。 // 这种情况下应该使用 BeanFactoryPostProcessor 来在 Bean 生成之前对其进行处理 ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException; }

该接口下又有几个重要的实现类:

  • AbstractApplicationContext:这是个抽象类,仅实现了公共的上下文特性。这个抽象类使用了模板方法设计模式,需要具体的实现类去实现这些抽象的方法。
  • GenericApplicationContext:该类继承自 AbstractApplicationContext,是为通用目的设计的,它能加载各种配置文件,例如 xml,properties 等等。它的内部持有一个 DefaultListableBeanFactory 的实例,实现了 BeanDefinitionRegistry 接口,以便允许向其应用任何 bean 的定义的读取器。
  • AnnotationConfigApplicationContext:该类继承自 GenericApplicationContext ,提供了注解配置(例如:@Configuration、@Component等)和类路径扫描(scan方法)的支持。

WebApplicationContext

该接口是专门为 Web 应用准备的,其允许从相对于 Web 根目录的路径中装载配置文件完成初始化。

public interface WebApplicationContext extends ApplicationContext { // 整个 Web 应用上下文是作为属性放置在 ServletContext 中的,该常量就是应用上下文在 ServletContext 属性列表中的 key String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT"; // 定义了三个作用域的名称 String SCOPE_REQUEST = "request"; String SCOPE_SESSION = "session"; String SCOPE_APPLICATION = "application"; // 在工厂中的 bean 名称 String SERVLET_CONTEXT_BEAN_NAME = "servletContext"; // ServletContext 初始化参数名称 String CONTEXT_PARAMETERS_BEAN_NAME = "contextParameters"; // 在工厂中 ServletContext 属性值环境bean的名称 String CONTEXT_ATTRIBUTES_BEAN_NAME = "contextAttributes"; // 用来获取 ServletContext 对象 @Nullable ServletContext getServletContext(); }

该接口的核心实现类有:

  • ConfigurableWebApplicationContext:该接口同时继承了 WebApplicationContext 和 ConfigurableApplicationContext,提供了 Web 应用上下文的可配置的能力。
  • GenericWebApplicationContext:该类继承自 GenericApplicationContext,实现了 ConfigurableWebApplicationContext。
  • XmlWebApplicationContext:该上下文是使用 Xml 配置文件的方式,不过是在 Web 环境中使用的。
  • AnnotationConfigServletWebServerApplicationContext:该类是被 SpringBoot 扩展而来的,SpringBoot 使用的就是该上下文。

差异对比

从上面可以看出 BeanFactory 是 Sping 框架的基础接口,一般是面向 Spring 本身;而 ApplicationContext 是以 BeanFactory 为基础进行综合能力扩展,用于满足大型业务应用的创建, ApplicationContext 一般面向使用 Sping 框架的开发者。几乎所有的应用场合我们都是直接使用 ApplicationContet 而非底层的 BeanFactory。

 

下表列出了BeanFactory 和 ApplicationContext 接口和实现所提供的功能:

功能 / 特点 BeanFactory ApplicationContext Bean 实例化/装配 有 有 BeanPostProcessor 自动注册 没有 有 BeanFactoryPostProcessor 自动注册 没有 有 MessageSource 便捷访问(针对i18n) 没有 有 ApplicationEvent 发布 没有 有

参考: https://www.cnblogs.com/smallstudent/p/11641173.html

https://www.cnblogs.com/loongk/p/12216526.html

上一篇:Spring5 IOC容器解析——Resource与ResourceLoader
下一篇:没有了
网友评论