深入研究Spring-IoC:两种设计和实现

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

一.Sprng IOC

  • 解除了对象实例化造成的耦合现象;将对象的创建和对生命周期的管理交给了容器来管理,可以通过注入的方式将IOC容器中的对象供给开发者使用,极大方便了开发。

二.IOC容器系列的两种设计和实现–BeanFactory和ApplicationContext

  • Spring
    IOC容器的设计中,IOC容器是一个统一称呼,具体担当容器的角色的Bean可以主要分为两种:BeanFactory系列、ApplicationContext系列;

  • 前一种是简单实现了BenFacotry这个接口的实现思路。后一种不仅仅实现
    BeanFacorty接口,还实现了其他接口,这样就赋予了ApplicationContext系列容器更多的特性。

  • PS:在实际的开发中以第二中形式为多。

这里写图片描述

  • PS:红色的是BeanFacotry系列容器;绿色的是ApplicationContext系列。 两条设计思路:

  • BeanFatory:

    1. 在这条设计路径中,BeanFactory接口定义了基本的IOC容器特性GetBean())。

    2. HierarchicalBeanFactory接口增加了getParentBeanFacory()的接口功能,使得BeanFacotry具备了双亲IOC容器的管理功能。

    3. ConfigurableBeanFatory接口定义了对BeanFactory的配置功能,比如setParentBeanFactory()、addBeanPostProcessor()配置bean的后只处理器等。

  • ApplicationContext:

  • 第二条接口设计主线是,以ApplicationContext应用上下文接口为核心的接口设计,这里涉及的主要接口设计有,从BeanFactory到ListableBeanFactory,再到ApplicationContext,再到我们常用的WebApplicationContext或者ConfigurableApplicationContext接口。

  • 我们常用的应用上下文基本上都是ConfigurableApplicationContext或者WebApplicationContext的实现。

  • 在这个接口体系中,ListableBeanFactory和HierarchicalBeanFactory两个接口,连接BeanFactory接口定义和ApplicationContext应用上下文的接口定义。在ListableBeanFactory接口中,细化了许多BeanFactory的接口功能,比如定义了getBeanDefinitionNames()接口方法;对于ApplicationContext接口,通过继承MessageSource、ResourceLoader、ApplicationEventPublisher接口,在BeanFactory简单IoC容器的基础上添加了许多对高级容器的特性的支持。

    区别:

    1. BeanFactory负责读取bean配置文档,管理bean的加载,实例化,维护bean之间的依赖关系,负责bean的声明周期。
      ApplicationContext除了提供上述BeanFactory所能提供的功能之外,还提供了更完整的框架功能:
      a、提供文本信息解析,支持I18N
      b、提供载入文件资源的通用方法
      c、向注册为监听器的Bean发送事件
      d、ApplicationContext接口扩展BeanFactory接口
      e、ApplicationContext提供附加功能

    2. 硬编码区别:

XmlBeanFactory bFactory = new XmlBeanFactory(new ClassPathResource("Spring.xml"));
BeansDemoClass beans = (BeansDemoClass) bFactory.getBean("beansDemoClass");
ApplicationContext aContext = new ClassPathXmlApplicationContext("Spring.xml");
BeansDemoClass beans = (BeansDemoClass)aContext.getBean("beansDemoClass");
  1. 初始化
    BeanFactory当需要调用时读取配置信息,生成某个类的实例。如果读入的Bean配置正确,则其他的配置中有错误也不会影响程序的运行。而ApplicationContext在初始化时就把 xml 的配置信息读入内存,对 XML 文件进行检验,如果配置文件没有错误,就创建所有的Bean,直接为应用程序服务。相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。

  2. 补充
    ApplicationContext会利用Java反射机制自动识别出配置文件中定义的BeanPostProcessor、InstantiationAwareBeanPostProcessor和BeanFactoryPostProcessor,并自动将它们注册到应用上下文中;而BeanFactory需要在代码中通过手工调用addBeanPostProcessor()方法进行注册。
    Ps:主要作用是就是让容器知道程序中都有哪些Bean。

三.创建IOC用到的核心类:Resource、BeanDefinition、BeanFactory

  • Resource :主要作用是指定IOC容器加载对象的数据来源。

    1. 在Spring内部,针对于资源文件有一个统一的接口Resource表示。其主要实现类有ClassPathResource、FileSystemResource、UrlResource、ByteArrayResource、ServletContextResource和InputStreamResource。

    2. ClassPathResource可用来获取类路径下的资源文件。假设我们有一个资源文件test.txt在类路径下,我们就可以通过给定对应资源文件在类路径下的路径path来获取它,new
      ClassPathResource(“test.txt”)。

    3. FileSystemResource可用来获取文件系统里面的资源。我们可以通过对应资源文件的文件路径来构建一个FileSystemResource。FileSystemResource还可以往对应的资源文件里面写内容,当然前提是当前资源文件是可写的,这可以通过其isWritable()方法来判断。FileSystemResource对外开放了对应资源文件的输出流,可以通过getOutputStream()方法获取到。

    4. UrlResource可用来代表URL对应的资源,它对URL做了一个简单的封装。通过给定一个URL地址,我们就能构建一个UrlResource。

    5. ByteArrayResource是针对于字节数组封装的资源,它的构建需要一个字节数组。

    6. ServletContextResource是针对于ServletContext封装的资源,用于访问ServletContext环境下的资源。ServletContextResource持有一个ServletContext的引用,其底层是通过ServletContext的getResource()方法和getResourceAsStream()方法来获取资源的。

这里写图片描述

  • BeanDefinition:加载对象的数据结构(个人愚见就是我们自己写的类的抽象结构再加上什么其他信息);

    1. Spring通过定义BeanDefinition来管理Spring应用中各种对象以及他们之间的依赖关系。BeanDefinition抽象了我们对Bean的定义,是让容器起作用的主要数据类型。
  • BeanFactory:用于盛放对象的Bean;

    1. BeanFactory是用于生产的Bean的工厂,如果有兴趣可以和FactoryBean比较一下。其中,定义了容器的基本规范(比如说能盛水的木质东西就是桶)用来产生各种各样的IOC容器。
  • 总结:如果把IOC比喻成水桶,那么BeanFactory是木桶,BeanDefinition是桶里的水,Resource是水来的方法。其中水桶按照样式大小分为不同的系列(BeanFacotry和ApplicationContext),而水(Bean)也有脏水和干净水之分(BeanDefinition是不同Bean的抽象)。

四.IOC容器初始化的三个步骤

1.Resource定位

  • Resource是封装的I/O操作类的接口,用于读取指定(URL、XML)的资源内容。通常由Resource接口的实现类来完成。例如:ClassPathResource
    或者ClassPathContextResource 来实现。
  • -

2.BeanDefinition载入

  1. 将我们定义好的Bean(类;一般为XML中的Bean)通过Resource读取,然后解析成Documnet对象,然后再解析成Bean的抽象的数据结构(BeanFactory可以根据这些数据结构实例化出一个我们定义的Bean类)

3.向ioc注册这些BeanDefinition

  • 拿到BeanDefinition后通过注册(告诉BeanFactory有哪些Bean)保存到BeanFatory中,以HashMap(Key,BeanDefinition)的形式存储起来,可以通过BeanFatory的实例调用getBean(Key)的方法,Spring会通过反射的机制给我注入我们想要的Bean;

学习博客:
http://blog.csdn.net/u011202334/article/details/51509235
《Spring技术内幕》

猜你喜欢

转载自blog.csdn.net/mengdonghui123456/article/details/77511324