全方位解析Spring IoC:(二)容器

Spring中,IoC容器主要负责对bean进行实例化、配置和组装,其中对于这些bean需要我们通过XMLJava代码等方式声明在Metadata配置中以让容器进行读取并获得指导。

Spring中,IoC容器所管理的对象称之为bean,它是由IoC容器实例化、组装和管理的对象。

下图从宏观视角来给出Spring是如何工作的。

text 复制代码
                              +
                              |
                              | Your Business Objects(POJOs)
                              |
                              v
                   +----------+-----------+
                   |                      |
+----------------->+ The Spring Container |
  Configuration    |                      |
     Metadata      +----------+-----------+
                              |
                              | produces
                              |
                              v
                  +-----------+-------------+
                  |                         |
                  | Fully configured system |
                  |      Ready for Use      |
                  |                         |
                  +-------------------------+

从上图中显示,在IoC容器中通过结合业务对象类和Metadata配置来创建和初始化容器类(例如,ApplicationContext),以此来得到一个配置完全并可执行的系统或应用。

需要注意,容器本身并不会对Metadata配置的格式作任何限制,即对于存储的配置格式是LDAPRDBMS还是XML都没有任何限制。所有这些不同格式的配置,容器都是通过扩展类(例如XmlBeanDefinitionReaderAutowiredAnnotationBeanPostProcessor等)进行解析,并存储为BeanDefinition来进行处理,这也大幅增加了容器的灵活性和可扩展性。

ApplicationContext

Spring使用了ApplicationContext表示IoC容器,它会读取Metadata配置中的指令对bean进行实例化、配置和组装。因此,在将业务对象类和Metadata配置注入到容器ApplicationContext后,我们就可以使用它来获取对应的bean实例,例如:

java 复制代码
// create and configure beans
ApplicationContext context = ...;
// retrieve configured instance
IocService service = context.getBean("iocService", IocService.class);

在开发过程中一个比较好的做法是通过依赖注入的方式来配置应用实例。换句话说,我们应该通过容器Push配置到相应的地方;而不是主动从容器中Pull相应的配置,比如主动通过ApplicationContext来获取对象(以任何形式)。

BeanFactory

实际上,ApplicationContextbean相关的能力都源自于BeanFactory(继承自BeanFactory),所以我们也能通过BeanFactory完成bean的实例化、配置和组装。即:

java 复制代码
// create and configure beans
BeanFactory factory = ...;
// retrieve configured instance
IocService service = factory.getBean("iocService", IocService.class);

本质上,BeanFactory相当于是应用组件的注册中心,持有并集中了大量的应用组件的配置信息(例如,持有大量的bean定义,每个bean定义都具有独一无二的名字)。当然,我们也可以将BeanFactory看作是IoC容器的"客户端",通过这个"客户端"我们可以完成会IoC容器访问。

ApplicationContext vs. BeanFactory

虽说ApplicationContextBeanFactory都能完成bean的实例化、配置和组装,但是我们一般更加推荐使用ApplicationContext。因为ApplicationContext不但包含了BeanFactory所有的能力,而且它还会将几种特殊的bean(特别是后置处理器BeanPostProcessor)加入到容器中激活Spring的一些特性(例如,注解的处理或者AOP代理的处理)。

当然,如果想在bean的处理流程上得到完全的控制,我们也可以直接使用BeanFactory。对于这种情况,默认是不会有上述ApplicationContext的特性,而如果要加入这些特性则需要额外将这些特殊的bean配置进BeanFactory,例如:

  • 将特殊的BeanPostProcessor应用到BeanFactory

    java 复制代码
    // BeanFactory的默认实现
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    
    // populate the factory with bean definitions
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
    reader.loadBeanDefinitions(new FileSystemResource("beans.xml"));
    
    // now register any needed BeanPostProcessor instances
    factory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
    
    // now start using the factory
  • 将特殊的BeanFactoryPostProcessor应用到BeanFactory

    java 复制代码
    // BeanFactory的默认实现
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    
    // populate the factory with bean definitions
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
    reader.loadBeanDefinitions(new FileSystemResource("beans.xml"));
    
    // bring in some property values from a Properties file
    // PropertySourcesPlaceholderConfigurer属于BeanFactoryPostProcessor的一种实现
    PropertySourcesPlaceholderConfigurer cfg = new PropertySourcesPlaceholderConfigurer();
    cfg.setLocation(new FileSystemResource("jdbc.properties"));
    
    // now actually do the replacement
    cfg.postProcessBeanFactory(factory);

不难看出,将特殊的bean逐个注册到BeanFactory中是一件十分烦杂的事情,所以这就是为什么Spring更加推荐使用ApplicationContext

BeanFactoryPostProcessorBeanPostProcessor对于许多容器的功能特性是必不可少的,例如注解处理和AOP代理等功能都是通过它来实现的。

最后,这里列出了BeanFactoryApplicationContext提供功能的对比:

Feature BeanFactory ApplicationContext
Bean instantiation/wiring Yes Yes
Integrated lifecycle management No Yes
Automatic BeanPostProcessor registration No Yes
Automatic BeanFactoryPostProcessor registration No Yes
Convenient MessageSource access (for internationalization) No Yes
Built-in ApplicationEvent publication mechanism No Yes

Spring官方推荐: 除非有特别充分的理由,否则推荐使用ApplicationContext

相关推荐
lizi888881 小时前
单组件的编写
java
java_heartLake1 小时前
设计模式之代理模式
java·设计模式·代理模式
魏 无羡1 小时前
pgsql 分组查询方法
java·服务器·数据库
兩尛2 小时前
java--面向对象编程(中级部分)
java·开发语言
Xxxx. .Xxxx2 小时前
C语言程序设计实验与习题指导 (第4版 )课后题-第二章+第三章
java·c语言·开发语言
姜西西_2 小时前
[Spring]Spring MVC 请求和响应及用到的注解
java·spring·mvc
逸狼2 小时前
【JavaEE初阶】多线程6(线程池\定时器)
java·开发语言·算法
qq_35323353892 小时前
【原创】java+springboot+mysql科研成果管理系统设计与实现
java·spring boot·mysql·mvc·web
dawn1912282 小时前
SpringMVC 入门案例详解
java·spring·html·mvc
极客先躯2 小时前
高级java每日一道面试题-2024年9月16日-框架篇-Spring MVC和Struts的区别是什么?
java·spring·面试·mvc·struts2·框架篇·高级java