Spring 4.x IOC介绍(一.BeanFactory 、ApplicationContext、WebApplicationContext之BeanFactory)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/java_yes/article/details/81505865

BeanFactory介绍

Spring通过一个配置文件描述Bean及Bean之间的依赖关系,利用Java语言的反射子功能实例化Bean并建立Bean之间的依赖关系。Spring的IoC容器在完成这些底层工作的基础上,还提供Bean实例缓存、生命周期管理、Bean实例代理、时间发布、资源装载等高级服务。

  • Bean工厂 — com.springframework.beans.factory.BeanFactory是Spring框架最核心的接口,他提供了高级IoC的配置机制。BeanFactory是管理不同类型的Java对象成为可能。
  • 应用上下文 — com.springframework.context.ApplicationContext建立在BeanFactory基础之上,提供了更多面向应用的功能,它提供了国际化支持和框架时间体系,更易于创建市级应用。

我们一般称BeanFactory为IoC容器,而称ApplicationContext为应用上下文。但有时为了行文方便,我们也将ApplicationContext称为Spring容器。
对于二者的用途,我们可以进行很简单划分:BeanFactory是Spring框架的基础设施,面向Spring本身;ApplicationContext面向使用Spring框架的开发者,几乎所有的应用场合都可以直接使用ApplicationContext而非底层的BeanFactory。

BeanFactory

诚如其名,BeanFactory是一个类工厂,但和传统的类工厂不同,传统的类工厂斤负责构造一个或几个类的实例;而BeanFactory是类的通用工厂,他可以创建并管理各种类的对象。这些可被创建和管理的对象本身没有什么特别之处,仅是一个POJO,Spring称这些被创建和管理的Jaba对象为Bean。我们知道JavaBean是要满足一定规范的,如唏嘘提供一个默认不带参的构造函数、不依赖于某一特定的容器等,但Spring中所说的Bean比JavaBean更宽泛一些,所有可以被Spring容器实例化并管理的Java类都可以称为Bean

BeanFactory的类体系结构

Spring为BeanFactory提供了多种实现,最常用的是XmlBeanFactory,但在Spring3.2中已经废弃,建议使用XmlBeanDefinitionReader、DefaultListableBeanFactory代替。BeanFactory的类继承体系设计优雅,堪称经典、通过继承体系,我们可以很容易地了解到BeanFactory具有哪些功能,如下图所示:
BeanFactory类继承体系
BeanFactory接口位于类结构树的顶端,它最主要的方法就是getBean(String beanName),该方法从容其中返回特定名称的Bean。BeanFactory的功能通过其它接口得到不断拓展。下面对上图中设计的其他接口分别进行说明。

  • ListableBeanFactory:该接口定义了访问容器中Bean基本信息的若干方法,如查看Bean的个数、获取某一类型Bean的配置名、查看容器中是否包括某一Bean等。
  • HireachicalBeanFactory:父子级联IoC容器的接口,自容器可以通过接口方法访问父容器。
  • ConfigurableBeanFactory:这是一个重要的接口,增强了IoC容器的可定制型。它定义了设置类装载器、属性编辑器、容器初始化后置处理器等方法。
  • AutowireCapableBeanFactory:定义了将容器中的Bean按某种规则(如按名字匹配、按类型匹配等)进行自动装配的方法。
  • SingletonBeanFactory:定义了允许在运行期向容器注册单实例Bean的方法。
  • BeanDefinitionRegistry:Spring配置文件中每一个bean节点元素在Spring容器里都通过一个BeanDefinition对象表示,它描述了Bean的配置信息。而BeanDefinitionRegistry接口提供了向容器手工注册BeanDefinition对象的方法。

初始化BeanFactory

下面使用Spring配置文件为Car提供配置信息,然后通过BeanFactory装在配置文件,启动SpringIoC容器。Spring配置文件如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="car1" class="com.smart.Car"
          p:brand="Cadillac CT6"
          p:color = "白色"
          p:maxSpeed="320">
    </bean>
</beans>

下面通过XmlBeanDefinitionReader、DefaultListableBeanFactory实现类启动SpringIoC容器,如下所示:

public class BeanFactoryTest {
    public void getBean() throws IOException {
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource res = resolver.getResource("classpath:resource/spring-config.xml");
        System.out.println(res.getURL());
        // 废弃,不建议使用
        // BeanFactory bf = new XmlBeanFactory(res);
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
        reader.loadBeanDefinitions(res);
        System.out.println("init BeanFactory.");
        Car car = factory.getBean("car",Car.class);
        System.out.println("Car bean is ready for use!");
        car.introduce();
    }

    public static void main(String[] args) throws IOException {
        BeanFactoryTest beanFactoryTest = new BeanFactoryTest();
        beanFactoryTest.getBean();
    }
}

结果如下:
结果
XmlBeanDefinitionReader通过Resource装载Spring配置信息并启动IoC容器,然后就可以通过BeanFactory #getBean(beanName) 方法从IoC容器中获取Bean。

总结

  1. 我们研究BeanFactory的类体继承体系设计优雅,不仅仅为了研究Spring,更要了解其中设计的思想。
  2. BeanFactory的体系结构中我们经常使用的是XmlBeanDefinitionReader、DefaultListableBeanFactory。其中ConfigurableBeanFactory接口增强了IoC容器可定制性。
  3. 通过BeanFactory启动IoC容器时,并不会初始化配置文件中定义的Bean,初始化动作发生在第一个调用时。对于单实例(singleton)的Bean来说,BeanFactory会缓存Bean实例,所以第二次使用getBean()获取Bean时,将直接从IoC容器的缓存中获取Bean实例。
  4. Spring在DefaultSingletonBeanRegistry类中提供了一个用于缓存单实例Bean的缓存器,他是一个用HashMap实现的缓存器,单实例的Bean以beanName为键保存在这个HashMap中。
  5. 在初始化BeanFactory时,必须为其提供一种日志框架。

猜你喜欢

转载自blog.csdn.net/java_yes/article/details/81505865